wiggum-cli 0.7.8 → 0.8.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.
Files changed (72) hide show
  1. package/dist/tui/app.d.ts +98 -0
  2. package/dist/tui/app.d.ts.map +1 -0
  3. package/dist/tui/app.js +70 -0
  4. package/dist/tui/app.js.map +1 -0
  5. package/dist/tui/components/ChatInput.d.ts +40 -0
  6. package/dist/tui/components/ChatInput.d.ts.map +1 -0
  7. package/dist/tui/components/ChatInput.js +61 -0
  8. package/dist/tui/components/ChatInput.js.map +1 -0
  9. package/dist/tui/components/MessageList.d.ts +79 -0
  10. package/dist/tui/components/MessageList.d.ts.map +1 -0
  11. package/dist/tui/components/MessageList.js +68 -0
  12. package/dist/tui/components/MessageList.js.map +1 -0
  13. package/dist/tui/components/PhaseHeader.d.ts +36 -0
  14. package/dist/tui/components/PhaseHeader.d.ts.map +1 -0
  15. package/dist/tui/components/PhaseHeader.js +31 -0
  16. package/dist/tui/components/PhaseHeader.js.map +1 -0
  17. package/dist/tui/components/StreamingText.d.ts +47 -0
  18. package/dist/tui/components/StreamingText.d.ts.map +1 -0
  19. package/dist/tui/components/StreamingText.js +38 -0
  20. package/dist/tui/components/StreamingText.js.map +1 -0
  21. package/dist/tui/components/ToolCallCard.d.ts +65 -0
  22. package/dist/tui/components/ToolCallCard.d.ts.map +1 -0
  23. package/dist/tui/components/ToolCallCard.js +100 -0
  24. package/dist/tui/components/ToolCallCard.js.map +1 -0
  25. package/dist/tui/components/WorkingIndicator.d.ts +45 -0
  26. package/dist/tui/components/WorkingIndicator.d.ts.map +1 -0
  27. package/dist/tui/components/WorkingIndicator.js +31 -0
  28. package/dist/tui/components/WorkingIndicator.js.map +1 -0
  29. package/dist/tui/components/index.d.ts +16 -0
  30. package/dist/tui/components/index.d.ts.map +1 -0
  31. package/dist/tui/components/index.js +10 -0
  32. package/dist/tui/components/index.js.map +1 -0
  33. package/dist/tui/hooks/index.d.ts +7 -0
  34. package/dist/tui/hooks/index.d.ts.map +1 -0
  35. package/dist/tui/hooks/index.js +6 -0
  36. package/dist/tui/hooks/index.js.map +1 -0
  37. package/dist/tui/hooks/useSpecGenerator.d.ts +168 -0
  38. package/dist/tui/hooks/useSpecGenerator.d.ts.map +1 -0
  39. package/dist/tui/hooks/useSpecGenerator.js +405 -0
  40. package/dist/tui/hooks/useSpecGenerator.js.map +1 -0
  41. package/dist/tui/index.d.ts +14 -0
  42. package/dist/tui/index.d.ts.map +1 -0
  43. package/dist/tui/index.js +18 -0
  44. package/dist/tui/index.js.map +1 -0
  45. package/dist/tui/screens/InterviewScreen.d.ts +55 -0
  46. package/dist/tui/screens/InterviewScreen.d.ts.map +1 -0
  47. package/dist/tui/screens/InterviewScreen.js +84 -0
  48. package/dist/tui/screens/InterviewScreen.js.map +1 -0
  49. package/dist/tui/screens/index.d.ts +6 -0
  50. package/dist/tui/screens/index.d.ts.map +1 -0
  51. package/dist/tui/screens/index.js +5 -0
  52. package/dist/tui/screens/index.js.map +1 -0
  53. package/dist/tui/theme.d.ts +62 -0
  54. package/dist/tui/theme.d.ts.map +1 -0
  55. package/dist/tui/theme.js +58 -0
  56. package/dist/tui/theme.js.map +1 -0
  57. package/package.json +6 -1
  58. package/src/tui/app.tsx +138 -0
  59. package/src/tui/components/ChatInput.tsx +105 -0
  60. package/src/tui/components/MessageList.tsx +186 -0
  61. package/src/tui/components/PhaseHeader.tsx +63 -0
  62. package/src/tui/components/StreamingText.tsx +69 -0
  63. package/src/tui/components/ToolCallCard.tsx +215 -0
  64. package/src/tui/components/WorkingIndicator.tsx +72 -0
  65. package/src/tui/components/index.ts +21 -0
  66. package/src/tui/hooks/index.ts +13 -0
  67. package/src/tui/hooks/useSpecGenerator.ts +589 -0
  68. package/src/tui/index.ts +23 -0
  69. package/src/tui/screens/InterviewScreen.tsx +164 -0
  70. package/src/tui/screens/index.ts +6 -0
  71. package/src/tui/theme.ts +72 -0
  72. package/tsconfig.json +2 -1
@@ -0,0 +1,98 @@
1
+ /**
2
+ * Main Ink Application Entry Point
3
+ *
4
+ * The root component for the Ink-based TUI. Routes to different screens
5
+ * based on the mode/screen prop. Currently supports the interview screen
6
+ * for the /new command, with room to add more screens (init, main shell,
7
+ * monitor) as needed.
8
+ */
9
+ import React from 'react';
10
+ import { type Instance } from 'ink';
11
+ import type { AIProvider } from '../ai/providers.js';
12
+ import type { ScanResult } from '../scanner/types.js';
13
+ /**
14
+ * Props for the interview screen
15
+ */
16
+ export interface InterviewAppProps {
17
+ /** Name of the feature being specified */
18
+ featureName: string;
19
+ /** Project root directory path */
20
+ projectRoot: string;
21
+ /** AI provider to use */
22
+ provider: AIProvider;
23
+ /** Model ID to use */
24
+ model: string;
25
+ /** Optional scan result with detected tech stack */
26
+ scanResult?: ScanResult;
27
+ }
28
+ /**
29
+ * Available screen types for the App component
30
+ * Start with just 'interview', add more screens later as needed:
31
+ * - 'init' - Project initialization wizard
32
+ * - 'shell' - Main interactive shell
33
+ * - 'monitor' - Agent monitoring dashboard
34
+ */
35
+ export type AppScreen = 'interview';
36
+ /**
37
+ * Props for the main App component
38
+ */
39
+ export interface AppProps {
40
+ /** Screen to display */
41
+ screen: AppScreen;
42
+ /** Props for the interview screen (required when screen is 'interview') */
43
+ interviewProps?: InterviewAppProps;
44
+ /** Called when the screen completes successfully */
45
+ onComplete?: (result: string) => void;
46
+ /** Called when the user exits/cancels */
47
+ onExit?: () => void;
48
+ }
49
+ /**
50
+ * Main App component for the Ink-based TUI
51
+ *
52
+ * Routes to different screens based on the `screen` prop. Currently
53
+ * only supports the interview screen for spec generation. The component
54
+ * structure allows easy addition of new screens in the future.
55
+ *
56
+ * @example
57
+ * ```tsx
58
+ * // Render the interview screen
59
+ * renderApp({
60
+ * screen: 'interview',
61
+ * interviewProps: {
62
+ * featureName: 'user-auth',
63
+ * projectRoot: '/path/to/project',
64
+ * provider: 'anthropic',
65
+ * model: 'claude-sonnet-4-5-20250514',
66
+ * },
67
+ * onComplete: (spec) => {
68
+ * fs.writeFileSync('spec.md', spec);
69
+ * },
70
+ * onExit: () => {
71
+ * process.exit(0);
72
+ * },
73
+ * });
74
+ * ```
75
+ */
76
+ export declare function App({ screen, interviewProps, onComplete, onExit, }: AppProps): React.ReactElement | null;
77
+ /**
78
+ * Render the App component to the terminal
79
+ *
80
+ * Helper function that wraps Ink's render() to provide a clean API
81
+ * for starting the TUI from command handlers.
82
+ *
83
+ * @param props - App component props
84
+ * @returns Ink Instance that can be used to control/cleanup the render
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * // In a command handler
89
+ * const instance = renderApp({
90
+ * screen: 'interview',
91
+ * interviewProps: { ... },
92
+ * onComplete: (spec) => { ... },
93
+ * onExit: () => instance.unmount(),
94
+ * });
95
+ * ```
96
+ */
97
+ export declare function renderApp(props: AppProps): Instance;
98
+ //# sourceMappingURL=app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/tui/app.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAU,KAAK,QAAQ,EAAE,MAAM,KAAK,CAAC;AAC5C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAGtD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,0CAA0C;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,kCAAkC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,yBAAyB;IACzB,QAAQ,EAAE,UAAU,CAAC;IACrB,sBAAsB;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,oDAAoD;IACpD,UAAU,CAAC,EAAE,UAAU,CAAC;CACzB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,SAAS,GAAG,WAAW,CAAC;AAEpC;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,wBAAwB;IACxB,MAAM,EAAE,SAAS,CAAC;IAClB,2EAA2E;IAC3E,cAAc,CAAC,EAAE,iBAAiB,CAAC;IACnC,oDAAoD;IACpD,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACtC,yCAAyC;IACzC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,GAAG,CAAC,EAClB,MAAM,EACN,cAAc,EACd,UAAU,EACV,MAAM,GACP,EAAE,QAAQ,GAAG,KAAK,CAAC,YAAY,GAAG,IAAI,CA2BtC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,QAAQ,CAEnD"}
@@ -0,0 +1,70 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { render } from 'ink';
3
+ import { InterviewScreen } from './screens/InterviewScreen.js';
4
+ /**
5
+ * Main App component for the Ink-based TUI
6
+ *
7
+ * Routes to different screens based on the `screen` prop. Currently
8
+ * only supports the interview screen for spec generation. The component
9
+ * structure allows easy addition of new screens in the future.
10
+ *
11
+ * @example
12
+ * ```tsx
13
+ * // Render the interview screen
14
+ * renderApp({
15
+ * screen: 'interview',
16
+ * interviewProps: {
17
+ * featureName: 'user-auth',
18
+ * projectRoot: '/path/to/project',
19
+ * provider: 'anthropic',
20
+ * model: 'claude-sonnet-4-5-20250514',
21
+ * },
22
+ * onComplete: (spec) => {
23
+ * fs.writeFileSync('spec.md', spec);
24
+ * },
25
+ * onExit: () => {
26
+ * process.exit(0);
27
+ * },
28
+ * });
29
+ * ```
30
+ */
31
+ export function App({ screen, interviewProps, onComplete, onExit, }) {
32
+ // Route to the appropriate screen based on the screen prop
33
+ if (screen === 'interview' && interviewProps) {
34
+ return (_jsx(InterviewScreen, { featureName: interviewProps.featureName, projectRoot: interviewProps.projectRoot, provider: interviewProps.provider, model: interviewProps.model, scanResult: interviewProps.scanResult, onComplete: (spec) => {
35
+ onComplete?.(spec);
36
+ }, onCancel: () => {
37
+ onExit?.();
38
+ } }));
39
+ }
40
+ // Future screens would be added here:
41
+ // if (screen === 'init' && initProps) { ... }
42
+ // if (screen === 'shell' && shellProps) { ... }
43
+ // if (screen === 'monitor' && monitorProps) { ... }
44
+ // Fallback - shouldn't happen in normal usage
45
+ return null;
46
+ }
47
+ /**
48
+ * Render the App component to the terminal
49
+ *
50
+ * Helper function that wraps Ink's render() to provide a clean API
51
+ * for starting the TUI from command handlers.
52
+ *
53
+ * @param props - App component props
54
+ * @returns Ink Instance that can be used to control/cleanup the render
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * // In a command handler
59
+ * const instance = renderApp({
60
+ * screen: 'interview',
61
+ * interviewProps: { ... },
62
+ * onComplete: (spec) => { ... },
63
+ * onExit: () => instance.unmount(),
64
+ * });
65
+ * ```
66
+ */
67
+ export function renderApp(props) {
68
+ return render(_jsx(App, { ...props }));
69
+ }
70
+ //# sourceMappingURL=app.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/tui/app.tsx"],"names":[],"mappings":";AAUA,OAAO,EAAE,MAAM,EAAiB,MAAM,KAAK,CAAC;AAG5C,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAyC/D;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,GAAG,CAAC,EAClB,MAAM,EACN,cAAc,EACd,UAAU,EACV,MAAM,GACG;IACT,2DAA2D;IAC3D,IAAI,MAAM,KAAK,WAAW,IAAI,cAAc,EAAE,CAAC;QAC7C,OAAO,CACL,KAAC,eAAe,IACd,WAAW,EAAE,cAAc,CAAC,WAAW,EACvC,WAAW,EAAE,cAAc,CAAC,WAAW,EACvC,QAAQ,EAAE,cAAc,CAAC,QAAQ,EACjC,KAAK,EAAE,cAAc,CAAC,KAAK,EAC3B,UAAU,EAAE,cAAc,CAAC,UAAU,EACrC,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE;gBACnB,UAAU,EAAE,CAAC,IAAI,CAAC,CAAC;YACrB,CAAC,EACD,QAAQ,EAAE,GAAG,EAAE;gBACb,MAAM,EAAE,EAAE,CAAC;YACb,CAAC,GACD,CACH,CAAC;IACJ,CAAC;IAED,sCAAsC;IACtC,8CAA8C;IAC9C,gDAAgD;IAChD,oDAAoD;IAEpD,8CAA8C;IAC9C,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,SAAS,CAAC,KAAe;IACvC,OAAO,MAAM,CAAC,KAAC,GAAG,OAAK,KAAK,GAAI,CAAC,CAAC;AACpC,CAAC"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * ChatInput - Multi-line input with history for chat interactions
3
+ *
4
+ * Displays a prompt character followed by a text input.
5
+ * Handles submission on Enter and clears input after submit.
6
+ */
7
+ import React from 'react';
8
+ /**
9
+ * Props for the ChatInput component
10
+ */
11
+ export interface ChatInputProps {
12
+ /** Called when user presses Enter with the current input value */
13
+ onSubmit: (value: string) => void;
14
+ /** Placeholder text when empty */
15
+ placeholder?: string;
16
+ /** Whether input is disabled (e.g., during AI processing) */
17
+ disabled?: boolean;
18
+ /** Prompt character/text shown before input (default "> ") */
19
+ prompt?: string;
20
+ /** Allow empty submissions (e.g., to continue/skip phases) */
21
+ allowEmpty?: boolean;
22
+ }
23
+ /**
24
+ * ChatInput component
25
+ *
26
+ * Provides a text input with a prompt character for chat-style interactions.
27
+ * Clears input after submission. Shows dimmed appearance when disabled.
28
+ *
29
+ * @example
30
+ * ```tsx
31
+ * <ChatInput
32
+ * onSubmit={(value) => console.log('User said:', value)}
33
+ * placeholder="Type your response..."
34
+ * disabled={isProcessing}
35
+ * />
36
+ * // Renders: > Type your response...
37
+ * ```
38
+ */
39
+ export declare function ChatInput({ onSubmit, placeholder, disabled, prompt, allowEmpty, }: ChatInputProps): React.ReactElement;
40
+ //# sourceMappingURL=ChatInput.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatInput.d.ts","sourceRoot":"","sources":["../../../src/tui/components/ChatInput.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAmB,MAAM,OAAO,CAAC;AAKxC;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,kEAAkE;IAClE,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,kCAAkC;IAClC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,8DAA8D;IAC9D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,SAAS,CAAC,EACxB,QAAQ,EACR,WAAoC,EACpC,QAAgB,EAChB,MAAa,EACb,UAAkB,GACnB,EAAE,cAAc,GAAG,KAAK,CAAC,YAAY,CAsDrC"}
@@ -0,0 +1,61 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ /**
3
+ * ChatInput - Multi-line input with history for chat interactions
4
+ *
5
+ * Displays a prompt character followed by a text input.
6
+ * Handles submission on Enter and clears input after submit.
7
+ */
8
+ import { useState } from 'react';
9
+ import { Box, Text } from 'ink';
10
+ import TextInput from 'ink-text-input';
11
+ import { colors } from '../theme.js';
12
+ /**
13
+ * ChatInput component
14
+ *
15
+ * Provides a text input with a prompt character for chat-style interactions.
16
+ * Clears input after submission. Shows dimmed appearance when disabled.
17
+ *
18
+ * @example
19
+ * ```tsx
20
+ * <ChatInput
21
+ * onSubmit={(value) => console.log('User said:', value)}
22
+ * placeholder="Type your response..."
23
+ * disabled={isProcessing}
24
+ * />
25
+ * // Renders: > Type your response...
26
+ * ```
27
+ */
28
+ export function ChatInput({ onSubmit, placeholder = 'Type your message...', disabled = false, prompt = '> ', allowEmpty = false, }) {
29
+ const [value, setValue] = useState('');
30
+ /**
31
+ * Handle input submission
32
+ * Calls onSubmit with current value and clears the input
33
+ */
34
+ const handleSubmit = (submittedValue) => {
35
+ // Don't submit when disabled
36
+ if (disabled) {
37
+ return;
38
+ }
39
+ // Don't submit empty values unless allowEmpty is true
40
+ if (!submittedValue.trim() && !allowEmpty) {
41
+ return;
42
+ }
43
+ onSubmit(submittedValue);
44
+ setValue('');
45
+ };
46
+ /**
47
+ * Handle value changes
48
+ * Only update if not disabled
49
+ */
50
+ const handleChange = (newValue) => {
51
+ if (!disabled) {
52
+ setValue(newValue);
53
+ }
54
+ };
55
+ // When disabled, show a waiting message
56
+ if (disabled) {
57
+ return (_jsx(Box, { flexDirection: "row", children: _jsxs(Text, { dimColor: true, color: colors.brown, children: [prompt, "[waiting for AI...]"] }) }));
58
+ }
59
+ return (_jsxs(Box, { flexDirection: "row", children: [_jsx(Text, { color: colors.yellow, children: prompt }), _jsx(TextInput, { value: value, onChange: handleChange, onSubmit: handleSubmit, placeholder: placeholder })] }));
60
+ }
61
+ //# sourceMappingURL=ChatInput.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ChatInput.js","sourceRoot":"","sources":["../../../src/tui/components/ChatInput.tsx"],"names":[],"mappings":";AAAA;;;;;GAKG;AAEH,OAAc,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACxC,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,SAAS,MAAM,gBAAgB,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAkBrC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,SAAS,CAAC,EACxB,QAAQ,EACR,WAAW,GAAG,sBAAsB,EACpC,QAAQ,GAAG,KAAK,EAChB,MAAM,GAAG,IAAI,EACb,UAAU,GAAG,KAAK,GACH;IACf,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAEvC;;;OAGG;IACH,MAAM,YAAY,GAAG,CAAC,cAAsB,EAAQ,EAAE;QACpD,6BAA6B;QAC7B,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO;QACT,CAAC;QAED,sDAAsD;QACtD,IAAI,CAAC,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;YAC1C,OAAO;QACT,CAAC;QAED,QAAQ,CAAC,cAAc,CAAC,CAAC;QACzB,QAAQ,CAAC,EAAE,CAAC,CAAC;IACf,CAAC,CAAC;IAEF;;;OAGG;IACH,MAAM,YAAY,GAAG,CAAC,QAAgB,EAAQ,EAAE;QAC9C,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,QAAQ,CAAC,QAAQ,CAAC,CAAC;QACrB,CAAC;IACH,CAAC,CAAC;IAEF,wCAAwC;IACxC,IAAI,QAAQ,EAAE,CAAC;QACb,OAAO,CACL,KAAC,GAAG,IAAC,aAAa,EAAC,KAAK,YACtB,MAAC,IAAI,IAAC,QAAQ,QAAC,KAAK,EAAE,MAAM,CAAC,KAAK,aAC/B,MAAM,2BACF,GACH,CACP,CAAC;IACJ,CAAC;IAED,OAAO,CACL,MAAC,GAAG,IAAC,aAAa,EAAC,KAAK,aACtB,KAAC,IAAI,IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,YAAG,MAAM,GAAQ,EAC3C,KAAC,SAAS,IACR,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,YAAY,EACtB,QAAQ,EAAE,YAAY,EACtB,WAAW,EAAE,WAAW,GACxB,IACE,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,79 @@
1
+ /**
2
+ * MessageList - Scrollable conversation history display
3
+ *
4
+ * Displays the full conversation history including:
5
+ * - User messages
6
+ * - Assistant messages (with optional streaming)
7
+ * - System messages
8
+ * - Tool call cards inline with assistant messages
9
+ */
10
+ import React from 'react';
11
+ import { type ToolCallStatus } from './ToolCallCard.js';
12
+ /**
13
+ * Tool call information for assistant messages
14
+ */
15
+ export interface ToolCall {
16
+ /** Name of the tool being executed */
17
+ toolName: string;
18
+ /** Current execution status */
19
+ status: ToolCallStatus;
20
+ /** Input passed to the tool */
21
+ input: string;
22
+ /** Output when complete */
23
+ output?: string;
24
+ /** Error message if failed */
25
+ error?: string;
26
+ }
27
+ /**
28
+ * Message in the conversation history
29
+ */
30
+ export interface Message {
31
+ /** Unique identifier for the message */
32
+ id: string;
33
+ /** Who sent the message */
34
+ role: 'user' | 'assistant' | 'system';
35
+ /** Text content of the message */
36
+ content: string;
37
+ /** Tool calls included in assistant messages */
38
+ toolCalls?: ToolCall[];
39
+ /** Whether this message is currently streaming */
40
+ isStreaming?: boolean;
41
+ }
42
+ /**
43
+ * Props for the MessageList component
44
+ */
45
+ export interface MessageListProps {
46
+ /** Array of messages to display */
47
+ messages: Message[];
48
+ /** Optional max height in lines (for future scrolling support) */
49
+ maxHeight?: number;
50
+ }
51
+ /**
52
+ * MessageList component
53
+ *
54
+ * Displays the full conversation history. Each message type has
55
+ * distinct styling:
56
+ * - User messages: "You: " prefix in white
57
+ * - Assistant messages: "AI: " prefix in yellow, with inline tool cards
58
+ * - System messages: dimmed brown text
59
+ *
60
+ * For streaming messages, uses the StreamingText component to show
61
+ * the cursor indicator.
62
+ *
63
+ * @example
64
+ * ```tsx
65
+ * <MessageList
66
+ * messages={[
67
+ * { id: '1', role: 'system', content: 'Interview started' },
68
+ * { id: '2', role: 'assistant', content: 'Hello! What would you like to build?' },
69
+ * { id: '3', role: 'user', content: 'A todo app' },
70
+ * { id: '4', role: 'assistant', content: 'Let me check...',
71
+ * toolCalls: [{ toolName: 'Read File', status: 'running', input: 'package.json' }],
72
+ * isStreaming: true
73
+ * },
74
+ * ]}
75
+ * />
76
+ * ```
77
+ */
78
+ export declare function MessageList({ messages, maxHeight }: MessageListProps): React.ReactElement;
79
+ //# sourceMappingURL=MessageList.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageList.d.ts","sourceRoot":"","sources":["../../../src/tui/components/MessageList.tsx"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,OAAO,EAAgB,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAEtE;;GAEG;AACH,MAAM,WAAW,QAAQ;IACvB,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,+BAA+B;IAC/B,MAAM,EAAE,cAAc,CAAC;IACvB,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,2BAA2B;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,wCAAwC;IACxC,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,kCAAkC;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,kDAAkD;IAClD,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,mCAAmC;IACnC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAyED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,gBAAgB,GAAG,KAAK,CAAC,YAAY,CA6BzF"}
@@ -0,0 +1,68 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box, Text } from 'ink';
3
+ import { colors } from '../theme.js';
4
+ import { StreamingText } from './StreamingText.js';
5
+ import { ToolCallCard } from './ToolCallCard.js';
6
+ /**
7
+ * Renders a single user message
8
+ */
9
+ function UserMessage({ content }) {
10
+ return (_jsxs(Box, { flexDirection: "row", marginY: 1, children: [_jsxs(Text, { color: colors.white, bold: true, children: ["You:", ' '] }), _jsx(Text, { color: colors.white, children: content })] }));
11
+ }
12
+ /**
13
+ * Renders a single assistant message with optional tool calls and streaming
14
+ */
15
+ function AssistantMessage({ content, toolCalls, isStreaming, }) {
16
+ return (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [toolCalls &&
17
+ toolCalls.length > 0 &&
18
+ toolCalls.map((toolCall, index) => (_jsx(Box, { marginBottom: 1, children: _jsx(ToolCallCard, { toolName: toolCall.toolName, status: toolCall.status, input: toolCall.input, output: toolCall.output, error: toolCall.error }) }, `tool-${index}`))), _jsxs(Box, { flexDirection: "row", children: [_jsxs(Text, { color: colors.yellow, bold: true, children: ["AI:", ' '] }), isStreaming ? (_jsx(StreamingText, { text: content, isStreaming: true, color: colors.yellow })) : (_jsx(Text, { color: colors.yellow, children: content }))] })] }));
19
+ }
20
+ /**
21
+ * Renders a system message (dimmed text)
22
+ */
23
+ function SystemMessage({ content }) {
24
+ return (_jsx(Box, { flexDirection: "row", marginY: 1, children: _jsx(Text, { color: colors.brown, dimColor: true, children: content }) }));
25
+ }
26
+ /**
27
+ * MessageList component
28
+ *
29
+ * Displays the full conversation history. Each message type has
30
+ * distinct styling:
31
+ * - User messages: "You: " prefix in white
32
+ * - Assistant messages: "AI: " prefix in yellow, with inline tool cards
33
+ * - System messages: dimmed brown text
34
+ *
35
+ * For streaming messages, uses the StreamingText component to show
36
+ * the cursor indicator.
37
+ *
38
+ * @example
39
+ * ```tsx
40
+ * <MessageList
41
+ * messages={[
42
+ * { id: '1', role: 'system', content: 'Interview started' },
43
+ * { id: '2', role: 'assistant', content: 'Hello! What would you like to build?' },
44
+ * { id: '3', role: 'user', content: 'A todo app' },
45
+ * { id: '4', role: 'assistant', content: 'Let me check...',
46
+ * toolCalls: [{ toolName: 'Read File', status: 'running', input: 'package.json' }],
47
+ * isStreaming: true
48
+ * },
49
+ * ]}
50
+ * />
51
+ * ```
52
+ */
53
+ export function MessageList({ messages, maxHeight }) {
54
+ // Note: maxHeight is accepted for future scrolling support
55
+ // Currently renders all messages - parent handles any scroll-like behavior
56
+ // by controlling which messages are passed in
57
+ return (_jsx(Box, { flexDirection: "column", ...(maxHeight ? { height: maxHeight } : {}), children: messages.map((message) => {
58
+ switch (message.role) {
59
+ case 'user':
60
+ return _jsx(UserMessage, { content: message.content }, message.id);
61
+ case 'assistant':
62
+ return (_jsx(AssistantMessage, { content: message.content, toolCalls: message.toolCalls, isStreaming: message.isStreaming }, message.id));
63
+ case 'system':
64
+ return _jsx(SystemMessage, { content: message.content }, message.id);
65
+ }
66
+ }) }));
67
+ }
68
+ //# sourceMappingURL=MessageList.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MessageList.js","sourceRoot":"","sources":["../../../src/tui/components/MessageList.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * PhaseHeader - Current phase indicator for multi-step workflows
3
+ *
4
+ * Displays the current phase with a horizontal line border.
5
+ * Format: ━━━ Phase X of Y: PhaseName ━━━
6
+ */
7
+ import React from 'react';
8
+ /**
9
+ * Props for the PhaseHeader component
10
+ */
11
+ export interface PhaseHeaderProps {
12
+ /** Current phase number (1-based) */
13
+ currentPhase: number;
14
+ /** Total number of phases */
15
+ totalPhases: number;
16
+ /** Name of the current phase */
17
+ phaseName: string;
18
+ }
19
+ /**
20
+ * PhaseHeader component
21
+ *
22
+ * Shows the current phase progress with surrounding horizontal lines.
23
+ * Uses Simpson yellow for visibility.
24
+ *
25
+ * @example
26
+ * ```tsx
27
+ * <PhaseHeader
28
+ * currentPhase={2}
29
+ * totalPhases={4}
30
+ * phaseName="Understanding Requirements"
31
+ * />
32
+ * // Renders: ━━━ Phase 2 of 4: Understanding Requirements ━━━
33
+ * ```
34
+ */
35
+ export declare function PhaseHeader({ currentPhase, totalPhases, phaseName, }: PhaseHeaderProps): React.ReactElement;
36
+ //# sourceMappingURL=PhaseHeader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PhaseHeader.d.ts","sourceRoot":"","sources":["../../../src/tui/components/PhaseHeader.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,qCAAqC;IACrC,YAAY,EAAE,MAAM,CAAC;IACrB,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,gCAAgC;IAChC,SAAS,EAAE,MAAM,CAAC;CACnB;AAOD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,WAAW,CAAC,EAC1B,YAAY,EACZ,WAAW,EACX,SAAS,GACV,EAAE,gBAAgB,GAAG,KAAK,CAAC,YAAY,CAcvC"}
@@ -0,0 +1,31 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box, Text } from 'ink';
3
+ import { colors } from '../theme.js';
4
+ /**
5
+ * Heavy horizontal box drawing character (U+2501)
6
+ */
7
+ const HEAVY_HORIZONTAL = '\u2501';
8
+ /**
9
+ * PhaseHeader component
10
+ *
11
+ * Shows the current phase progress with surrounding horizontal lines.
12
+ * Uses Simpson yellow for visibility.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * <PhaseHeader
17
+ * currentPhase={2}
18
+ * totalPhases={4}
19
+ * phaseName="Understanding Requirements"
20
+ * />
21
+ * // Renders: ━━━ Phase 2 of 4: Understanding Requirements ━━━
22
+ * ```
23
+ */
24
+ export function PhaseHeader({ currentPhase, totalPhases, phaseName, }) {
25
+ // Build the phase text
26
+ const phaseText = `Phase ${currentPhase} of ${totalPhases}: ${phaseName}`;
27
+ // Create horizontal line segments (3 characters each side)
28
+ const lineSegment = HEAVY_HORIZONTAL.repeat(3);
29
+ return (_jsx(Box, { flexDirection: "row", justifyContent: "center", width: "100%", children: _jsxs(Text, { color: colors.yellow, children: [lineSegment, " ", phaseText, " ", lineSegment] }) }));
30
+ }
31
+ //# sourceMappingURL=PhaseHeader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PhaseHeader.js","sourceRoot":"","sources":["../../../src/tui/components/PhaseHeader.tsx"],"names":[],"mappings":";AAQA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAcrC;;GAEG;AACH,MAAM,gBAAgB,GAAG,QAAQ,CAAC;AAElC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,WAAW,CAAC,EAC1B,YAAY,EACZ,WAAW,EACX,SAAS,GACQ;IACjB,uBAAuB;IACvB,MAAM,SAAS,GAAG,SAAS,YAAY,OAAO,WAAW,KAAK,SAAS,EAAE,CAAC;IAE1E,2DAA2D;IAC3D,MAAM,WAAW,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IAE/C,OAAO,CACL,KAAC,GAAG,IAAC,aAAa,EAAC,KAAK,EAAC,cAAc,EAAC,QAAQ,EAAC,KAAK,EAAC,MAAM,YAC3D,MAAC,IAAI,IAAC,KAAK,EAAE,MAAM,CAAC,MAAM,aACvB,WAAW,OAAG,SAAS,OAAG,WAAW,IACjC,GACH,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * StreamingText - Renders AI response text with optional cursor
3
+ *
4
+ * Displays text as it streams in from the AI. The parent component
5
+ * is responsible for accumulating text chunks and passing them via
6
+ * the `text` prop. This component simply renders what it receives,
7
+ * optionally showing a cursor when streaming is in progress.
8
+ */
9
+ import React from 'react';
10
+ /**
11
+ * Props for the StreamingText component
12
+ */
13
+ export interface StreamingTextProps {
14
+ /** The accumulated text to display */
15
+ text: string;
16
+ /** Whether streaming is still in progress */
17
+ isStreaming: boolean;
18
+ /** Optional text color (defaults to white) */
19
+ color?: string;
20
+ /** Whether to show cursor when streaming (defaults to true) */
21
+ showCursor?: boolean;
22
+ }
23
+ /**
24
+ * StreamingText component
25
+ *
26
+ * Renders text with an optional cursor indicator when streaming.
27
+ * The cursor appears at the end of the text while `isStreaming` is true.
28
+ *
29
+ * @example
30
+ * ```tsx
31
+ * // During streaming
32
+ * <StreamingText
33
+ * text="Hello, world"
34
+ * isStreaming={true}
35
+ * />
36
+ * // Renders: "Hello, world█"
37
+ *
38
+ * // After streaming completes
39
+ * <StreamingText
40
+ * text="Hello, world!"
41
+ * isStreaming={false}
42
+ * />
43
+ * // Renders: "Hello, world!"
44
+ * ```
45
+ */
46
+ export declare function StreamingText({ text, isStreaming, color, showCursor, }: StreamingTextProps): React.ReactElement;
47
+ //# sourceMappingURL=StreamingText.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StreamingText.d.ts","sourceRoot":"","sources":["../../../src/tui/components/StreamingText.tsx"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAS1B;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,sCAAsC;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,WAAW,EAAE,OAAO,CAAC;IACrB,8CAA8C;IAC9C,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,+DAA+D;IAC/D,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,aAAa,CAAC,EAC5B,IAAI,EACJ,WAAW,EACX,KAAoB,EACpB,UAAiB,GAClB,EAAE,kBAAkB,GAAG,KAAK,CAAC,YAAY,CAQzC"}
@@ -0,0 +1,38 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Text } from 'ink';
3
+ import { colors } from '../theme.js';
4
+ /**
5
+ * Block cursor character (U+2588 - Full Block)
6
+ */
7
+ const CURSOR_CHAR = '\u2588';
8
+ /**
9
+ * StreamingText component
10
+ *
11
+ * Renders text with an optional cursor indicator when streaming.
12
+ * The cursor appears at the end of the text while `isStreaming` is true.
13
+ *
14
+ * @example
15
+ * ```tsx
16
+ * // During streaming
17
+ * <StreamingText
18
+ * text="Hello, world"
19
+ * isStreaming={true}
20
+ * />
21
+ * // Renders: "Hello, world█"
22
+ *
23
+ * // After streaming completes
24
+ * <StreamingText
25
+ * text="Hello, world!"
26
+ * isStreaming={false}
27
+ * />
28
+ * // Renders: "Hello, world!"
29
+ * ```
30
+ */
31
+ export function StreamingText({ text, isStreaming, color = colors.white, showCursor = true, }) {
32
+ // Determine if cursor should be visible
33
+ const displayCursor = isStreaming && showCursor;
34
+ // Build the display text with optional cursor
35
+ const displayText = displayCursor ? `${text}${CURSOR_CHAR}` : text;
36
+ return _jsx(Text, { color: color, children: displayText });
37
+ }
38
+ //# sourceMappingURL=StreamingText.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StreamingText.js","sourceRoot":"","sources":["../../../src/tui/components/StreamingText.tsx"],"names":[],"mappings":";AAUA,OAAO,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAC3B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC;;GAEG;AACH,MAAM,WAAW,GAAG,QAAQ,CAAC;AAgB7B;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,aAAa,CAAC,EAC5B,IAAI,EACJ,WAAW,EACX,KAAK,GAAG,MAAM,CAAC,KAAK,EACpB,UAAU,GAAG,IAAI,GACE;IACnB,wCAAwC;IACxC,MAAM,aAAa,GAAG,WAAW,IAAI,UAAU,CAAC;IAEhD,8CAA8C;IAC9C,MAAM,WAAW,GAAG,aAAa,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAEnE,OAAO,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,YAAG,WAAW,GAAQ,CAAC;AAClD,CAAC"}