wiggum-cli 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/ralph.js +0 -0
- package/dist/agent/memory/ingest.d.ts +14 -0
- package/dist/agent/memory/ingest.js +77 -0
- package/dist/agent/memory/store.d.ts +15 -0
- package/dist/agent/memory/store.js +98 -0
- package/dist/agent/memory/types.d.ts +16 -0
- package/dist/agent/memory/types.js +14 -0
- package/dist/agent/orchestrator.d.ts +7 -0
- package/dist/agent/orchestrator.js +266 -0
- package/dist/agent/resolve-config.d.ts +26 -0
- package/dist/agent/resolve-config.js +43 -0
- package/dist/agent/tools/backlog.d.ts +27 -0
- package/dist/agent/tools/backlog.js +51 -0
- package/dist/agent/tools/dry-run.d.ts +106 -0
- package/dist/agent/tools/dry-run.js +119 -0
- package/dist/agent/tools/execution.d.ts +51 -0
- package/dist/agent/tools/execution.js +256 -0
- package/dist/agent/tools/feature-state.d.ts +43 -0
- package/dist/agent/tools/feature-state.js +184 -0
- package/dist/agent/tools/introspection.d.ts +23 -0
- package/dist/agent/tools/introspection.js +40 -0
- package/dist/agent/tools/memory.d.ts +44 -0
- package/dist/agent/tools/memory.js +99 -0
- package/dist/agent/tools/preflight.d.ts +7 -0
- package/dist/agent/tools/preflight.js +137 -0
- package/dist/agent/tools/reporting.d.ts +58 -0
- package/dist/agent/tools/reporting.js +119 -0
- package/dist/agent/tools/schemas.d.ts +2 -0
- package/dist/agent/tools/schemas.js +3 -0
- package/dist/agent/types.d.ts +45 -0
- package/dist/agent/types.js +1 -0
- package/dist/ai/conversation/conversation-manager.js +8 -0
- package/dist/ai/conversation/url-fetcher.js +27 -0
- package/dist/ai/providers.js +5 -5
- package/dist/commands/agent.d.ts +17 -0
- package/dist/commands/agent.js +114 -0
- package/dist/commands/monitor.js +50 -183
- package/dist/commands/new-auto.d.ts +15 -0
- package/dist/commands/new-auto.js +237 -0
- package/dist/commands/run.js +20 -10
- package/dist/commands/sync.d.ts +15 -0
- package/dist/commands/sync.js +68 -0
- package/dist/generator/config.d.ts +1 -41
- package/dist/generator/config.js +7 -0
- package/dist/generator/index.d.ts +2 -2
- package/dist/generator/templates.d.ts +2 -0
- package/dist/generator/templates.js +9 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +115 -4
- package/dist/repl/command-parser.d.ts +5 -0
- package/dist/repl/command-parser.js +5 -0
- package/dist/templates/prompts/PROMPT.md.tmpl +13 -10
- package/dist/templates/prompts/PROMPT_e2e.md.tmpl +13 -7
- package/dist/templates/prompts/PROMPT_feature.md.tmpl +16 -3
- package/dist/templates/prompts/PROMPT_review_auto.md.tmpl +32 -12
- package/dist/templates/prompts/PROMPT_review_manual.md.tmpl +4 -1
- package/dist/templates/prompts/PROMPT_review_merge.md.tmpl +39 -14
- package/dist/templates/prompts/PROMPT_verify.md.tmpl +5 -2
- package/dist/templates/scripts/feature-loop.sh.tmpl +441 -69
- package/dist/tui/app.d.ts +19 -2
- package/dist/tui/app.js +22 -4
- package/dist/tui/components/IssuePicker.d.ts +27 -0
- package/dist/tui/components/IssuePicker.js +64 -0
- package/dist/tui/components/RunCompletionSummary.js +6 -3
- package/dist/tui/hooks/useAgentOrchestrator.d.ts +29 -0
- package/dist/tui/hooks/useAgentOrchestrator.js +453 -0
- package/dist/tui/orchestration/interview-orchestrator.d.ts +5 -1
- package/dist/tui/orchestration/interview-orchestrator.js +27 -6
- package/dist/tui/screens/AgentScreen.d.ts +21 -0
- package/dist/tui/screens/AgentScreen.js +159 -0
- package/dist/tui/screens/InitScreen.js +4 -0
- package/dist/tui/screens/InterviewScreen.d.ts +3 -1
- package/dist/tui/screens/InterviewScreen.js +146 -10
- package/dist/tui/screens/MainShell.d.ts +1 -1
- package/dist/tui/screens/MainShell.js +36 -1
- package/dist/tui/screens/RunScreen.js +38 -6
- package/dist/tui/utils/build-run-summary.d.ts +1 -1
- package/dist/tui/utils/build-run-summary.js +40 -84
- package/dist/tui/utils/clear-screen.d.ts +14 -0
- package/dist/tui/utils/clear-screen.js +16 -0
- package/dist/tui/utils/loop-status.d.ts +41 -1
- package/dist/tui/utils/loop-status.js +243 -35
- package/dist/tui/utils/pr-summary.d.ts +3 -2
- package/dist/tui/utils/pr-summary.js +41 -6
- package/dist/utils/config.d.ts +8 -0
- package/dist/utils/config.js +8 -0
- package/dist/utils/github.d.ts +32 -0
- package/dist/utils/github.js +106 -0
- package/package.json +4 -1
- package/src/templates/prompts/PROMPT.md.tmpl +13 -10
- package/src/templates/prompts/PROMPT_e2e.md.tmpl +13 -7
- package/src/templates/prompts/PROMPT_feature.md.tmpl +16 -3
- package/src/templates/prompts/PROMPT_review_auto.md.tmpl +32 -12
- package/src/templates/prompts/PROMPT_review_manual.md.tmpl +4 -1
- package/src/templates/prompts/PROMPT_review_merge.md.tmpl +39 -14
- package/src/templates/prompts/PROMPT_verify.md.tmpl +5 -2
- package/src/templates/scripts/feature-loop.sh.tmpl +441 -69
package/dist/tui/app.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ import type { SessionState } from '../repl/session-state.js';
|
|
|
16
16
|
/**
|
|
17
17
|
* Available screen types for the App component
|
|
18
18
|
*/
|
|
19
|
-
export type AppScreen = 'shell' | 'interview' | 'init' | 'run';
|
|
19
|
+
export type AppScreen = 'shell' | 'interview' | 'init' | 'run' | 'agent';
|
|
20
20
|
/**
|
|
21
21
|
* Props for the interview screen
|
|
22
22
|
*/
|
|
@@ -31,6 +31,19 @@ export interface InterviewAppProps {
|
|
|
31
31
|
model: string;
|
|
32
32
|
/** Optional scan result with detected tech stack */
|
|
33
33
|
scanResult?: ScanResult;
|
|
34
|
+
/** References to auto-add during context phase (from CLI --issue/--context flags) */
|
|
35
|
+
initialReferences?: string[];
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Props for the agent screen when launched directly from CLI
|
|
39
|
+
*/
|
|
40
|
+
export interface AgentAppProps {
|
|
41
|
+
modelOverride?: string;
|
|
42
|
+
maxItems?: number;
|
|
43
|
+
maxSteps?: number;
|
|
44
|
+
labels?: string[];
|
|
45
|
+
reviewMode?: 'manual' | 'auto' | 'merge';
|
|
46
|
+
dryRun?: boolean;
|
|
34
47
|
}
|
|
35
48
|
/**
|
|
36
49
|
* Props for the run/monitor screen when launched directly from CLI
|
|
@@ -57,6 +70,8 @@ export interface AppProps {
|
|
|
57
70
|
interviewProps?: InterviewAppProps;
|
|
58
71
|
/** Props for the run/monitor screen (required when screen is 'run') */
|
|
59
72
|
runProps?: RunAppProps;
|
|
73
|
+
/** Props for the agent screen (required when screen is 'agent') */
|
|
74
|
+
agentProps?: AgentAppProps;
|
|
60
75
|
/** Called when the screen completes successfully */
|
|
61
76
|
onComplete?: (result: string) => void;
|
|
62
77
|
/** Called when the user exits/cancels */
|
|
@@ -69,7 +84,7 @@ export interface AppProps {
|
|
|
69
84
|
* and receives a shared headerElement prop.
|
|
70
85
|
*/
|
|
71
86
|
export declare function App({ screen: initialScreen, initialSessionState, version, // Fallback if package.json read fails (keep in sync with index.ts)
|
|
72
|
-
interviewProps, runProps, onComplete, onExit, }: AppProps): React.ReactElement | null;
|
|
87
|
+
interviewProps, runProps, agentProps, onComplete, onExit, }: AppProps): React.ReactElement | null;
|
|
73
88
|
/**
|
|
74
89
|
* Render options for renderApp
|
|
75
90
|
*/
|
|
@@ -84,6 +99,8 @@ export interface RenderAppOptions {
|
|
|
84
99
|
interviewProps?: InterviewAppProps;
|
|
85
100
|
/** Props for run/monitor screen (if starting directly on run screen) */
|
|
86
101
|
runProps?: RunAppProps;
|
|
102
|
+
/** Props for agent screen (if starting directly on agent screen) */
|
|
103
|
+
agentProps?: AgentAppProps;
|
|
87
104
|
/** Called when spec generation completes */
|
|
88
105
|
onComplete?: (result: string) => void;
|
|
89
106
|
/** Called when user exits */
|
package/dist/tui/app.js
CHANGED
|
@@ -19,6 +19,7 @@ import { logger } from '../utils/logger.js';
|
|
|
19
19
|
import { InterviewScreen } from './screens/InterviewScreen.js';
|
|
20
20
|
import { InitScreen } from './screens/InitScreen.js';
|
|
21
21
|
import { RunScreen } from './screens/RunScreen.js';
|
|
22
|
+
import { AgentScreen } from './screens/AgentScreen.js';
|
|
22
23
|
import { MainShell } from './screens/MainShell.js';
|
|
23
24
|
import { HeaderContent } from './components/HeaderContent.js';
|
|
24
25
|
import { useBackgroundRuns } from './hooks/useBackgroundRuns.js';
|
|
@@ -29,7 +30,7 @@ import { useBackgroundRuns } from './hooks/useBackgroundRuns.js';
|
|
|
29
30
|
* and receives a shared headerElement prop.
|
|
30
31
|
*/
|
|
31
32
|
export function App({ screen: initialScreen, initialSessionState, version = '0.12.1', // Fallback if package.json read fails (keep in sync with index.ts)
|
|
32
|
-
interviewProps, runProps, onComplete, onExit, }) {
|
|
33
|
+
interviewProps, runProps, agentProps, onComplete, onExit, }) {
|
|
33
34
|
const [currentScreen, setCurrentScreen] = useState(initialScreen);
|
|
34
35
|
const [screenProps, setScreenProps] = useState(() => {
|
|
35
36
|
if (initialScreen === 'run' && runProps) {
|
|
@@ -184,7 +185,7 @@ interviewProps, runProps, onComplete, onExit, }) {
|
|
|
184
185
|
navigate('shell', { message: 'Feature name is required for the run screen.' });
|
|
185
186
|
}
|
|
186
187
|
}
|
|
187
|
-
else if (currentScreen !== 'shell' && currentScreen !== 'init') {
|
|
188
|
+
else if (currentScreen !== 'shell' && currentScreen !== 'init' && currentScreen !== 'agent') {
|
|
188
189
|
// Unknown screen — redirect to shell on next tick
|
|
189
190
|
navigate('shell', { message: `Internal error: unknown screen "${currentScreen}". Returned to shell.` });
|
|
190
191
|
}
|
|
@@ -198,7 +199,7 @@ interviewProps, runProps, onComplete, onExit, }) {
|
|
|
198
199
|
if (!featureName || typeof featureName !== 'string' || !sessionState.provider) {
|
|
199
200
|
return null; // useEffect will redirect to shell
|
|
200
201
|
}
|
|
201
|
-
return (_jsx(InterviewScreen, { header: headerElement, featureName: featureName, projectRoot: sessionState.projectRoot, provider: sessionState.provider, model: sessionState.model, scanResult: sessionState.scanResult, specsPath: sessionState.config?.paths.specs, onComplete: handleInterviewComplete, onCancel: handleInterviewCancel }));
|
|
202
|
+
return (_jsx(InterviewScreen, { header: headerElement, featureName: featureName, projectRoot: sessionState.projectRoot, provider: sessionState.provider, model: sessionState.model, scanResult: sessionState.scanResult, specsPath: sessionState.config?.paths.specs, initialReferences: interviewProps?.initialReferences, onComplete: handleInterviewComplete, onCancel: handleInterviewCancel }));
|
|
202
203
|
}
|
|
203
204
|
case 'init':
|
|
204
205
|
return (_jsx(InitScreen, { header: headerElement, projectRoot: sessionState.projectRoot, sessionState: sessionState, onComplete: handleInitComplete, onCancel: () => navigate('shell') }));
|
|
@@ -211,6 +212,23 @@ interviewProps, runProps, onComplete, onExit, }) {
|
|
|
211
212
|
const reviewMode = screenProps?.reviewMode;
|
|
212
213
|
return (_jsx(RunScreen, { header: headerElement, featureName: featureName, projectRoot: sessionState.projectRoot, sessionState: sessionState, monitorOnly: monitorOnly, reviewMode: reviewMode, onComplete: handleRunComplete, onBackground: handleRunBackground, onCancel: () => navigate('shell') }));
|
|
213
214
|
}
|
|
215
|
+
case 'agent': {
|
|
216
|
+
// Merge CLI-provided agentProps with navigation screenProps (from /agent command)
|
|
217
|
+
const resolvedAgentOptions = {
|
|
218
|
+
...agentProps,
|
|
219
|
+
...(screenProps?.dryRun != null ? { dryRun: screenProps.dryRun } : {}),
|
|
220
|
+
...(screenProps?.maxItems != null ? { maxItems: screenProps.maxItems } : {}),
|
|
221
|
+
...(screenProps?.reviewMode != null ? { reviewMode: screenProps.reviewMode } : {}),
|
|
222
|
+
};
|
|
223
|
+
return (_jsx(AgentScreen, { header: headerElement, projectRoot: sessionState.projectRoot, agentOptions: resolvedAgentOptions, onExit: () => {
|
|
224
|
+
if (initialScreen === 'agent') {
|
|
225
|
+
onExit?.();
|
|
226
|
+
}
|
|
227
|
+
else {
|
|
228
|
+
navigate('shell');
|
|
229
|
+
}
|
|
230
|
+
} }));
|
|
231
|
+
}
|
|
214
232
|
default: {
|
|
215
233
|
// Return fallback UI instead of calling navigate() during render (which would be setState during render).
|
|
216
234
|
// The useEffect guard above will redirect to shell on next tick.
|
|
@@ -224,5 +242,5 @@ interviewProps, runProps, onComplete, onExit, }) {
|
|
|
224
242
|
* Render the App component to the terminal
|
|
225
243
|
*/
|
|
226
244
|
export function renderApp(options) {
|
|
227
|
-
return render(_jsx(App, { screen: options.screen, initialSessionState: options.initialSessionState, version: options.version, interviewProps: options.interviewProps, runProps: options.runProps, onComplete: options.onComplete, onExit: options.onExit }));
|
|
245
|
+
return render(_jsx(App, { screen: options.screen, initialSessionState: options.initialSessionState, version: options.version, interviewProps: options.interviewProps, runProps: options.runProps, agentProps: options.agentProps, onComplete: options.onComplete, onExit: options.onExit }));
|
|
228
246
|
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* IssuePicker - GitHub issue selection dropdown
|
|
3
|
+
*
|
|
4
|
+
* Displays a bordered list of GitHub issues for the user to navigate
|
|
5
|
+
* and select from. Follows the visual style of CommandDropdown.
|
|
6
|
+
* Supports arrow keys and j/k for navigation, Enter to select, Esc to cancel.
|
|
7
|
+
*/
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import type { GitHubIssueListItem } from '../../utils/github.js';
|
|
10
|
+
/**
|
|
11
|
+
* Props for the IssuePicker component
|
|
12
|
+
*/
|
|
13
|
+
export interface IssuePickerProps {
|
|
14
|
+
/** List of issues to display */
|
|
15
|
+
issues: GitHubIssueListItem[];
|
|
16
|
+
/** Repository slug (e.g. "owner/repo") shown in header */
|
|
17
|
+
repoSlug: string;
|
|
18
|
+
/** Called when an issue is selected */
|
|
19
|
+
onSelect: (issue: GitHubIssueListItem) => void;
|
|
20
|
+
/** Called when the picker is dismissed (Escape) */
|
|
21
|
+
onCancel: () => void;
|
|
22
|
+
/** Whether issues are currently loading */
|
|
23
|
+
isLoading: boolean;
|
|
24
|
+
/** Optional error message to display */
|
|
25
|
+
error?: string;
|
|
26
|
+
}
|
|
27
|
+
export declare function IssuePicker({ issues, repoSlug, onSelect, onCancel, isLoading, error, }: IssuePickerProps): React.ReactElement;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* IssuePicker - GitHub issue selection dropdown
|
|
4
|
+
*
|
|
5
|
+
* Displays a bordered list of GitHub issues for the user to navigate
|
|
6
|
+
* and select from. Follows the visual style of CommandDropdown.
|
|
7
|
+
* Supports arrow keys and j/k for navigation, Enter to select, Esc to cancel.
|
|
8
|
+
*/
|
|
9
|
+
import React, { useState } from 'react';
|
|
10
|
+
import { Box, Text, useInput, useStdout } from 'ink';
|
|
11
|
+
import Spinner from 'ink-spinner';
|
|
12
|
+
import { colors, box } from '../theme.js';
|
|
13
|
+
const MAX_LABELS = 2;
|
|
14
|
+
function truncate(text, maxLen) {
|
|
15
|
+
if (text.length <= maxLen)
|
|
16
|
+
return text;
|
|
17
|
+
return text.slice(0, maxLen - 1) + '\u2026';
|
|
18
|
+
}
|
|
19
|
+
export function IssuePicker({ issues, repoSlug, onSelect, onCancel, isLoading, error, }) {
|
|
20
|
+
const [selectedIndex, setSelectedIndex] = useState(0);
|
|
21
|
+
const { stdout } = useStdout();
|
|
22
|
+
const columns = stdout?.columns ?? 80;
|
|
23
|
+
React.useEffect(() => {
|
|
24
|
+
setSelectedIndex(0);
|
|
25
|
+
}, [issues]);
|
|
26
|
+
// Handle keyboard input
|
|
27
|
+
useInput((input, key) => {
|
|
28
|
+
if (key.escape) {
|
|
29
|
+
onCancel();
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
if (key.return && issues.length > 0) {
|
|
33
|
+
onSelect(issues[selectedIndex]);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (key.upArrow || input === 'k') {
|
|
37
|
+
setSelectedIndex((prev) => Math.max(0, prev - 1));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (key.downArrow || input === 'j') {
|
|
41
|
+
setSelectedIndex((prev) => Math.min(issues.length - 1, prev + 1));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
});
|
|
45
|
+
// Build border strings
|
|
46
|
+
const countSuffix = !isLoading && !error ? ` (${issues.length})` : '';
|
|
47
|
+
const headerLabel = ` GitHub Issues ${box.horizontal} ${repoSlug}${countSuffix} `;
|
|
48
|
+
const contentWidth = Math.min(Math.max(60, headerLabel.length + 10), columns - 6);
|
|
49
|
+
const topBorderFill = contentWidth - headerLabel.length - 1;
|
|
50
|
+
const topBorder = box.topLeft + box.horizontal + headerLabel + box.horizontal.repeat(Math.max(0, topBorderFill)) + box.topRight;
|
|
51
|
+
const bottomBorder = box.bottomLeft + box.horizontal.repeat(contentWidth) + box.bottomRight;
|
|
52
|
+
// Space budget for title: total width minus number, labels, borders, padding
|
|
53
|
+
const numberWidth = 6; // " #999 " — enough for 3-digit issues
|
|
54
|
+
const labelBudget = 24; // space for up to 2 labels
|
|
55
|
+
const chrome = 4; // borders + padding
|
|
56
|
+
const titleMaxLen = Math.max(20, contentWidth - numberWidth - labelBudget - chrome);
|
|
57
|
+
return (_jsxs(Box, { flexDirection: "column", marginLeft: 2, marginTop: 1, children: [_jsx(Text, { dimColor: true, children: topBorder }), isLoading && (_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { dimColor: true, children: box.vertical }), _jsx(Text, { children: " " }), _jsx(Spinner, { type: "dots" }), _jsx(Text, { color: colors.yellow, children: " Searching..." }), _jsx(Text, { children: ' '.repeat(Math.max(0, contentWidth - 16)) }), _jsx(Text, { dimColor: true, children: box.vertical })] })), !isLoading && error && (_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { dimColor: true, children: box.vertical }), _jsxs(Text, { color: colors.pink, children: [" ", error] }), _jsx(Text, { children: ' '.repeat(Math.max(0, contentWidth - error.length - 1)) }), _jsx(Text, { dimColor: true, children: box.vertical })] })), !isLoading && !error && issues.length === 0 && (_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { dimColor: true, children: box.vertical }), _jsx(Text, { dimColor: true, children: " No open issues found" }), _jsx(Text, { children: ' '.repeat(Math.max(0, contentWidth - 21)) }), _jsx(Text, { dimColor: true, children: box.vertical })] })), !isLoading && !error && issues.map((issue, index) => {
|
|
58
|
+
const isSelected = index === selectedIndex;
|
|
59
|
+
const numberText = `#${issue.number}`;
|
|
60
|
+
const title = truncate(issue.title, titleMaxLen);
|
|
61
|
+
const labelTags = issue.labels.slice(0, MAX_LABELS).join(' ');
|
|
62
|
+
return (_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { dimColor: true, children: box.vertical }), _jsxs(Text, { backgroundColor: isSelected ? colors.yellow : undefined, color: isSelected ? colors.brown : colors.yellow, children: [' ', numberText] }), _jsxs(Text, { backgroundColor: isSelected ? colors.yellow : undefined, color: isSelected ? colors.brown : undefined, children: [' ', title] }), labelTags && (_jsxs(Text, { backgroundColor: isSelected ? colors.yellow : undefined, color: isSelected ? colors.brown : colors.gray, children: [' ', labelTags] })), _jsxs(Text, { dimColor: true, children: [' '.repeat(1), box.vertical] })] }, issue.number));
|
|
63
|
+
}), _jsx(Text, { dimColor: true, children: bottomBorder }), _jsx(Box, { marginLeft: 1, children: _jsxs(Text, { color: colors.gray, children: ['(', '\u2191\u2193 navigate, Enter select, Esc cancel', ')'] }) })] }));
|
|
64
|
+
}
|
|
@@ -116,10 +116,12 @@ export function RunCompletionSummary({ summary, }) {
|
|
|
116
116
|
return (_jsxs(SummaryBox, { minWidth: 60, children: [_jsx(Text, { bold: true, children: summary.feature }), _jsxs(Box, { flexDirection: "row", gap: 1, children: [_jsxs(Text, { bold: true, color: exitStatus.color, children: [statusIcon, " ", exitStatus.label] }), _jsx(Text, { dimColor: true, children: "\u00B7" }), _jsx(Text, { dimColor: true, children: subtitleParts.join(' · ') })] }), _jsxs(SummaryBoxSection, { children: [_jsx(Text, { bold: true, children: "Phases" }), summary.phases && summary.phases.length > 0 ? (summary.phases.map((phaseInfo) => {
|
|
117
117
|
const phaseIcon = phaseInfo.status === 'success' ? phase.complete :
|
|
118
118
|
phaseInfo.status === 'failed' ? phase.error :
|
|
119
|
-
phase.
|
|
119
|
+
phaseInfo.status === 'started' ? phase.active :
|
|
120
|
+
phase.pending;
|
|
120
121
|
const phaseColor = phaseInfo.status === 'success' ? colors.green :
|
|
121
122
|
phaseInfo.status === 'failed' ? colors.pink :
|
|
122
|
-
colors.
|
|
123
|
+
phaseInfo.status === 'started' ? colors.yellow :
|
|
124
|
+
colors.gray;
|
|
123
125
|
const durationText = phaseInfo.durationMs !== undefined
|
|
124
126
|
? formatDurationMs(phaseInfo.durationMs)
|
|
125
127
|
: 'Not available';
|
|
@@ -127,7 +129,8 @@ export function RunCompletionSummary({ summary, }) {
|
|
|
127
129
|
? ` (${phaseInfo.iterations} iterations)`
|
|
128
130
|
: '';
|
|
129
131
|
const statusText = phaseInfo.status === 'skipped' ? ' skipped' :
|
|
130
|
-
phaseInfo.status === 'failed' ? ' failed' :
|
|
132
|
+
phaseInfo.status === 'failed' ? ' failed' :
|
|
133
|
+
phaseInfo.status === 'started' ? ' in progress' : '';
|
|
131
134
|
return (_jsxs(Box, { flexDirection: "row", children: [_jsxs(Text, { color: phaseColor, children: [phaseIcon, " "] }), _jsxs(Text, { children: [phaseInfo.label, " ", durationText, iterationsText, statusText] })] }, phaseInfo.id));
|
|
132
135
|
})) : (_jsx(Text, { children: "No phase information available" }))] }), _jsxs(SummaryBoxSection, { children: [_jsx(Text, { bold: true, children: "Changes" }), !summary.changes || !summary.changes.available ? (_jsx(Text, { children: "Changes: Not available" })) : summary.changes.totalFilesChanged === 0 || (summary.changes.files && summary.changes.files.length === 0) ? (_jsx(Text, { children: "No changes" })) : summary.changes.totalFilesChanged !== undefined ? (_jsxs(Text, { children: [summary.changes.totalFilesChanged, " file", summary.changes.totalFilesChanged !== 1 ? 's' : '', " changed"] })) : !summary.changes.files ? (_jsx(Text, { children: "Changes: Could not compute diff" })) : null, (() => {
|
|
133
136
|
const files = summary.changes?.available ? summary.changes.files : undefined;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* useAgentOrchestrator — React hook that bridges the agent orchestrator
|
|
3
|
+
* lifecycle to TUI state via callbacks.
|
|
4
|
+
*
|
|
5
|
+
* Creates the orchestrator, runs it via stream(), and interprets tool
|
|
6
|
+
* calls into structured state (active issue, queue, completed, log).
|
|
7
|
+
* Exposes an abort() function for clean shutdown on q/Esc.
|
|
8
|
+
*/
|
|
9
|
+
import type { AgentIssueState, AgentLogEntry, ReviewMode } from '../../agent/types.js';
|
|
10
|
+
export type AgentStatus = 'idle' | 'running' | 'complete' | 'error';
|
|
11
|
+
export interface UseAgentOrchestratorOptions {
|
|
12
|
+
projectRoot: string;
|
|
13
|
+
modelOverride?: string;
|
|
14
|
+
maxItems?: number;
|
|
15
|
+
maxSteps?: number;
|
|
16
|
+
labels?: string[];
|
|
17
|
+
reviewMode?: ReviewMode;
|
|
18
|
+
dryRun?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface UseAgentOrchestratorResult {
|
|
21
|
+
status: AgentStatus;
|
|
22
|
+
activeIssue: AgentIssueState | null;
|
|
23
|
+
queue: AgentIssueState[];
|
|
24
|
+
completed: AgentIssueState[];
|
|
25
|
+
logEntries: AgentLogEntry[];
|
|
26
|
+
error: string | null;
|
|
27
|
+
abort: () => void;
|
|
28
|
+
}
|
|
29
|
+
export declare function useAgentOrchestrator(options: UseAgentOrchestratorOptions): UseAgentOrchestratorResult;
|