@sylphx/flow 1.8.0 → 1.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/CHANGELOG.md +72 -0
  2. package/assets/output-styles/silent.md +145 -8
  3. package/assets/rules/core.md +19 -2
  4. package/package.json +2 -12
  5. package/src/commands/flow/execute.ts +470 -0
  6. package/src/commands/flow/index.ts +11 -0
  7. package/src/commands/flow/prompt.ts +35 -0
  8. package/src/commands/flow/setup.ts +312 -0
  9. package/src/commands/flow/targets.ts +18 -0
  10. package/src/commands/flow/types.ts +47 -0
  11. package/src/commands/flow-command.ts +18 -967
  12. package/src/commands/flow-orchestrator.ts +14 -5
  13. package/src/commands/hook-command.ts +1 -1
  14. package/src/commands/init-core.ts +12 -3
  15. package/src/commands/run-command.ts +1 -1
  16. package/src/config/rules.ts +1 -1
  17. package/src/core/error-handling.ts +1 -1
  18. package/src/core/loop-controller.ts +1 -1
  19. package/src/core/state-detector.ts +1 -1
  20. package/src/core/target-manager.ts +1 -1
  21. package/src/index.ts +1 -1
  22. package/src/shared/files/index.ts +1 -1
  23. package/src/shared/processing/index.ts +1 -1
  24. package/src/targets/claude-code.ts +3 -3
  25. package/src/targets/opencode.ts +3 -3
  26. package/src/utils/agent-enhancer.ts +2 -2
  27. package/src/utils/{mcp-config.ts → config/mcp-config.ts} +4 -4
  28. package/src/utils/{paths.ts → config/paths.ts} +1 -1
  29. package/src/utils/{settings.ts → config/settings.ts} +1 -1
  30. package/src/utils/{target-config.ts → config/target-config.ts} +5 -5
  31. package/src/utils/{target-utils.ts → config/target-utils.ts} +3 -3
  32. package/src/utils/display/banner.ts +25 -0
  33. package/src/utils/display/status.ts +55 -0
  34. package/src/utils/{file-operations.ts → files/file-operations.ts} +2 -2
  35. package/src/utils/files/jsonc.ts +36 -0
  36. package/src/utils/{sync-utils.ts → files/sync-utils.ts} +3 -3
  37. package/src/utils/index.ts +42 -61
  38. package/src/utils/version.ts +47 -0
  39. package/src/components/benchmark-monitor.tsx +0 -331
  40. package/src/components/reindex-progress.tsx +0 -261
  41. package/src/composables/functional/index.ts +0 -14
  42. package/src/composables/functional/useEnvironment.ts +0 -171
  43. package/src/composables/functional/useFileSystem.ts +0 -139
  44. package/src/composables/index.ts +0 -4
  45. package/src/composables/useEnv.ts +0 -13
  46. package/src/composables/useRuntimeConfig.ts +0 -27
  47. package/src/core/ai-sdk.ts +0 -603
  48. package/src/core/app-factory.ts +0 -381
  49. package/src/core/builtin-agents.ts +0 -9
  50. package/src/core/command-system.ts +0 -550
  51. package/src/core/config-system.ts +0 -550
  52. package/src/core/connection-pool.ts +0 -390
  53. package/src/core/di-container.ts +0 -155
  54. package/src/core/headless-display.ts +0 -96
  55. package/src/core/interfaces/index.ts +0 -22
  56. package/src/core/interfaces/repository.interface.ts +0 -91
  57. package/src/core/interfaces/service.interface.ts +0 -133
  58. package/src/core/interfaces.ts +0 -96
  59. package/src/core/result.ts +0 -351
  60. package/src/core/service-config.ts +0 -252
  61. package/src/core/session-service.ts +0 -121
  62. package/src/core/storage-factory.ts +0 -115
  63. package/src/core/stream-handler.ts +0 -288
  64. package/src/core/type-utils.ts +0 -427
  65. package/src/core/unified-storage.ts +0 -456
  66. package/src/core/validation/limit.ts +0 -46
  67. package/src/core/validation/query.ts +0 -20
  68. package/src/db/auto-migrate.ts +0 -322
  69. package/src/db/base-database-client.ts +0 -144
  70. package/src/db/cache-db.ts +0 -218
  71. package/src/db/cache-schema.ts +0 -75
  72. package/src/db/database.ts +0 -70
  73. package/src/db/index.ts +0 -252
  74. package/src/db/memory-db.ts +0 -153
  75. package/src/db/memory-schema.ts +0 -29
  76. package/src/db/schema.ts +0 -289
  77. package/src/db/session-repository.ts +0 -733
  78. package/src/domains/index.ts +0 -6
  79. package/src/domains/utilities/index.ts +0 -6
  80. package/src/domains/utilities/time/index.ts +0 -5
  81. package/src/domains/utilities/time/tools.ts +0 -291
  82. package/src/services/agent-service.ts +0 -273
  83. package/src/services/evaluation-service.ts +0 -271
  84. package/src/services/functional/evaluation-logic.ts +0 -296
  85. package/src/services/functional/file-processor.ts +0 -273
  86. package/src/services/functional/index.ts +0 -12
  87. package/src/services/memory.service.ts +0 -476
  88. package/src/types/api/batch.ts +0 -108
  89. package/src/types/api/errors.ts +0 -118
  90. package/src/types/api/index.ts +0 -55
  91. package/src/types/api/requests.ts +0 -76
  92. package/src/types/api/responses.ts +0 -180
  93. package/src/types/api/websockets.ts +0 -85
  94. package/src/types/benchmark.ts +0 -49
  95. package/src/types/database.types.ts +0 -510
  96. package/src/types/memory-types.ts +0 -63
  97. package/src/utils/advanced-tokenizer.ts +0 -191
  98. package/src/utils/ai-model-fetcher.ts +0 -19
  99. package/src/utils/async-file-operations.ts +0 -516
  100. package/src/utils/audio-player.ts +0 -345
  101. package/src/utils/codebase-helpers.ts +0 -211
  102. package/src/utils/console-ui.ts +0 -79
  103. package/src/utils/database-errors.ts +0 -140
  104. package/src/utils/debug-logger.ts +0 -49
  105. package/src/utils/file-scanner.ts +0 -259
  106. package/src/utils/help.ts +0 -20
  107. package/src/utils/immutable-cache.ts +0 -106
  108. package/src/utils/jsonc.ts +0 -158
  109. package/src/utils/memory-tui.ts +0 -414
  110. package/src/utils/models-dev.ts +0 -91
  111. package/src/utils/parallel-operations.ts +0 -487
  112. package/src/utils/process-manager.ts +0 -155
  113. package/src/utils/prompts.ts +0 -120
  114. package/src/utils/search-tool-builder.ts +0 -214
  115. package/src/utils/session-manager.ts +0 -168
  116. package/src/utils/session-title.ts +0 -87
  117. package/src/utils/simplified-errors.ts +0 -410
  118. package/src/utils/template-engine.ts +0 -94
  119. package/src/utils/test-audio.ts +0 -71
  120. package/src/utils/todo-context.ts +0 -46
  121. package/src/utils/token-counter.ts +0 -288
  122. /package/src/utils/{cli-output.ts → display/cli-output.ts} +0 -0
  123. /package/src/utils/{logger.ts → display/logger.ts} +0 -0
  124. /package/src/utils/{notifications.ts → display/notifications.ts} +0 -0
  125. /package/src/utils/{secret-utils.ts → security/secret-utils.ts} +0 -0
  126. /package/src/utils/{security.ts → security/security.ts} +0 -0
@@ -1,331 +0,0 @@
1
- import path from 'node:path';
2
- import { Box, render, Text, useApp } from 'ink';
3
- import React from 'react';
4
- import type { AgentData, InitialInfo } from '../types/benchmark.js';
5
-
6
- export interface InkMonitorProps {
7
- monitor: InkMonitor;
8
- onComplete: () => void;
9
- }
10
-
11
- export class InkMonitor {
12
- private agents: Map<string, AgentData> = new Map();
13
- private isRunning = false;
14
- private workspaceDirs: string[] = [];
15
- private uiInstance?: any;
16
- private listeners = new Set<() => void>();
17
- private initialInfo: InitialInfo;
18
-
19
- constructor(initialInfo: InitialInfo) {
20
- this.initialInfo = initialInfo;
21
- this.setupSignalHandlers();
22
- }
23
-
24
- // Subscribe to changes - proper React pattern
25
- subscribe(listener: () => void) {
26
- this.listeners.add(listener);
27
- return () => {
28
- this.listeners.delete(listener);
29
- };
30
- }
31
-
32
- private triggerUpdate() {
33
- for (const listener of this.listeners) {
34
- listener();
35
- }
36
- }
37
-
38
- // Getters for React component
39
- getAgents() {
40
- return this.agents;
41
- }
42
-
43
- getWorkspaceDirs() {
44
- return this.workspaceDirs;
45
- }
46
-
47
- getInitialInfo() {
48
- return this.initialInfo;
49
- }
50
-
51
- start() {
52
- this.isRunning = true;
53
-
54
- // Force Ink to work by ensuring proper terminal detection
55
- process.stdout.isTTY = true;
56
- process.stderr.isTTY = true;
57
-
58
- const uiInstance = render(
59
- <BenchmarkMonitor
60
- monitor={this}
61
- onComplete={() => {
62
- this.stop();
63
- }}
64
- />,
65
- {
66
- // Enable Ink's full-screen mode with proper terminal control
67
- debug: false,
68
- patchConsole: true, // Let Ink control console output
69
- exitOnCtrlC: false, // We'll handle CtrlC ourselves
70
- }
71
- );
72
-
73
- this.uiInstance = uiInstance;
74
- }
75
-
76
- setWorkspaceDirs(dirs: string[]) {
77
- this.workspaceDirs = dirs;
78
- }
79
-
80
- addAgent(name: string) {
81
- this.agents.set(name, {
82
- status: 'idle',
83
- output: [],
84
- startTime: undefined,
85
- });
86
- }
87
-
88
- updateAgentStatus(name: string, status: AgentData['status']) {
89
- const agent = this.agents.get(name);
90
- if (agent) {
91
- agent.status = status;
92
- if (status === 'running' && !agent.startTime) {
93
- agent.startTime = Date.now();
94
- } else if (status === 'completed' || status === 'error') {
95
- agent.endTime = Date.now();
96
- }
97
- // Trigger UI update through subscriber pattern
98
- this.triggerUpdate();
99
- }
100
- }
101
-
102
- setAgentPid(name: string, pid: number) {
103
- const agent = this.agents.get(name);
104
- if (agent) {
105
- agent.pid = pid;
106
- this.triggerUpdate();
107
- }
108
- }
109
-
110
- addAgentOutput(name: string, output: string) {
111
- const agent = this.agents.get(name);
112
- if (agent) {
113
- // Remove ANSI escape sequences that interfere with Ink
114
- const cleanedOutput = output.replace(/\x1b\[[0-9;]*[A-Za-z]/g, '');
115
- const lines = cleanedOutput.split('\n').filter((line) => line.trim());
116
- agent.output = [...agent.output.slice(-20), ...lines]; // Keep last 20 lines
117
- // Trigger UI update through subscriber pattern
118
- this.triggerUpdate();
119
- }
120
- }
121
-
122
- stop() {
123
- this.isRunning = false;
124
- if (this.uiInstance) {
125
- this.uiInstance.unmount();
126
- this.uiInstance = undefined;
127
- }
128
- }
129
-
130
- private setupSignalHandlers() {
131
- const shutdown = async (_signal: string) => {
132
- if (!this.isRunning) {
133
- return;
134
- }
135
-
136
- this.stop();
137
- process.exit(0);
138
- };
139
-
140
- process.on('SIGINT', () => shutdown('SIGINT'));
141
- process.on('SIGTERM', () => shutdown('SIGTERM'));
142
- process.on('SIGHUP', () => shutdown('SIGHUP'));
143
- }
144
- }
145
-
146
- // React Ink component for efficient real-time monitoring
147
- const BenchmarkMonitor: React.FC<InkMonitorProps> = ({ monitor, onComplete }) => {
148
- const { exit } = useApp();
149
-
150
- // Subscribe to monitor changes using proper React state
151
- const [_updateTrigger, setUpdateTrigger] = React.useState(0);
152
- const [flashState, setFlashState] = React.useState(true);
153
-
154
- React.useEffect(() => {
155
- // Subscribe to the monitor's change notifications
156
- const unsubscribe = monitor.subscribe(() => {
157
- setUpdateTrigger((prev) => prev + 1);
158
- });
159
-
160
- return unsubscribe;
161
- }, [monitor]);
162
-
163
- // Flashing effect for running status + force frequent updates for real-time output
164
- React.useEffect(() => {
165
- const interval = setInterval(() => {
166
- setFlashState((prev) => !prev);
167
- setUpdateTrigger((prev) => prev + 1); // Force update every 800ms to refresh output display
168
- }, 800); // Flash every 800ms for slow flashing
169
-
170
- return () => clearInterval(interval);
171
- }, []);
172
-
173
- // Auto-exit when all agents complete
174
- React.useEffect(() => {
175
- const agents = monitor.getAgents();
176
- const allCompleted = Array.from(agents.values()).every(
177
- (agent) => agent.status === 'completed' || agent.status === 'error'
178
- );
179
-
180
- if (allCompleted && agents.size > 0) {
181
- onComplete();
182
- exit();
183
- }
184
- }, [monitor, onComplete, exit]);
185
-
186
- const status = React.useMemo(() => {
187
- const agents = monitor.getAgents();
188
- return Array.from(agents.entries()).map(([name, agent]) => {
189
- let runtime = 0;
190
- if (agent.startTime) {
191
- if (agent.endTime) {
192
- runtime = Math.floor((agent.endTime - agent.startTime) / 1000);
193
- } else if (agent.status === 'running') {
194
- // Don't calculate runtime dynamically - store it in the agent data
195
- runtime = agent.startTime ? Math.floor((Date.now() - agent.startTime) / 1000) : 0;
196
- }
197
- }
198
-
199
- // Determine status display with flashing green dot for running
200
- let statusDisplay = '';
201
- let statusColor = '';
202
-
203
- if (agent.status === 'running') {
204
- statusDisplay = flashState ? '●' : ' ';
205
- statusColor = 'green';
206
- } else if (agent.status === 'completed') {
207
- statusDisplay = '✓';
208
- statusColor = 'green';
209
- } else if (agent.status === 'error') {
210
- statusDisplay = '✗';
211
- statusColor = 'red';
212
- } else {
213
- statusDisplay = '◯';
214
- statusColor = 'gray';
215
- }
216
-
217
- // Show actual runtime for agents
218
- let runtimeText = '';
219
- if (agent.startTime && agent.status === 'running') {
220
- runtimeText = `${runtime}s`;
221
- } else if (agent.startTime) {
222
- runtimeText = `${runtime}s`;
223
- }
224
-
225
- // Get last output lines (show up to 5 most recent lines)
226
- let lastOutputLines: string[] = [];
227
- if (agent.output.length > 0) {
228
- // Get the last 5 lines - simpler filtering to ensure real-time output shows
229
- const recentLines = agent.output.slice(-5);
230
- lastOutputLines = recentLines
231
- .filter((line) => line && line.trim().length > 0)
232
- .map((line) => {
233
- const cleanLine = line.trim();
234
- return cleanLine.length > 150 ? `${cleanLine.substring(0, 150)}...` : cleanLine;
235
- });
236
- }
237
-
238
- // Show placeholder text only if no actual output exists
239
- if (lastOutputLines.length === 0) {
240
- if (agent.status === 'running') {
241
- lastOutputLines.push('(working...)');
242
- } else if (agent.status === 'idle') {
243
- lastOutputLines.push('(waiting to start...)');
244
- }
245
- }
246
-
247
- return {
248
- name,
249
- statusDisplay,
250
- statusColor,
251
- status: agent.status.toUpperCase(),
252
- runtime: runtimeText,
253
- lastOutput: lastOutputLines,
254
- pid: agent.pid,
255
- };
256
- });
257
- }, [monitor, flashState]);
258
-
259
- const workspaceDirs = monitor.getWorkspaceDirs();
260
- const initialInfo = monitor.getInitialInfo();
261
-
262
- // Create a mapping from agent name to workspace directory
263
- const agentWorkspaceMap = new Map<string, string>();
264
- for (const dir of workspaceDirs) {
265
- const agentName = path.basename(dir);
266
- agentWorkspaceMap.set(agentName, dir);
267
- }
268
-
269
- return (
270
- <Box flexDirection="column" padding={1}>
271
- {/* Initial Information Section */}
272
- <Box marginBottom={1} flexDirection="column">
273
- <Text bold>Agent Benchmark Monitor</Text>
274
- {initialInfo?.initialInfo && (
275
- <>
276
- <Text color="gray">Output: {initialInfo.initialInfo.outputDir}</Text>
277
- <Text color="gray">
278
- Task:{' '}
279
- {initialInfo.initialInfo.taskFile
280
- ? path.basename(initialInfo.initialInfo.taskFile)
281
- : 'Unknown'}
282
- </Text>
283
- <Text color="gray">Agents: {initialInfo.initialInfo.agentCount}</Text>
284
- <Text color="gray">
285
- Concurrency: {initialInfo.initialInfo.concurrency}, Delay:{' '}
286
- {initialInfo.initialInfo.delay}s
287
- </Text>
288
- </>
289
- )}
290
- {(!initialInfo || !initialInfo.initialInfo) && (
291
- <Text color="gray">Initializing benchmark...</Text>
292
- )}
293
- </Box>
294
-
295
- <Box flexDirection="column">
296
- {status.map((agent) => (
297
- <Box key={agent.name} marginBottom={1} flexDirection="column">
298
- <Box>
299
- <Text bold>
300
- <Text color={agent.statusColor}>{agent.statusDisplay}</Text> {agent.name}
301
- {agent.runtime ? ` ${agent.runtime}` : ''}
302
- {agent.pid ? <Text color="gray"> (pid: {agent.pid})</Text> : ''}
303
- </Text>
304
- </Box>
305
-
306
- {/* Show workspace directory under each agent */}
307
- {agentWorkspaceMap.has(agent.name) && (
308
- <Box paddingLeft={2}>
309
- <Text color="gray">{agentWorkspaceMap.get(agent.name)}</Text>
310
- </Box>
311
- )}
312
-
313
- {agent.lastOutput && agent.lastOutput.length > 0 && (
314
- <Box paddingLeft={4} flexDirection="column" paddingBottom={1} marginTop={1}>
315
- {agent.lastOutput.map((line, index) => (
316
- <Text key={index} color="gray">
317
- {line}
318
- </Text>
319
- ))}
320
- </Box>
321
- )}
322
- </Box>
323
- ))}
324
- </Box>
325
-
326
- <Box marginTop={1}>
327
- <Text color="gray">Press Ctrl+C to exit</Text>
328
- </Box>
329
- </Box>
330
- );
331
- };
@@ -1,261 +0,0 @@
1
- import { Box, render, Text, useApp } from 'ink';
2
- import React from 'react';
3
-
4
- export interface ReindexProgressData {
5
- current: number;
6
- total: number;
7
- fileName: string;
8
- status: 'processing' | 'completed' | 'skipped';
9
- phase: 'tokenizing' | 'calculating' | 'completed';
10
- mode?: 'tfidf-only' | 'semantic';
11
- stats?: {
12
- documentsProcessed: number;
13
- uniqueTerms: number;
14
- };
15
- }
16
-
17
- export class ReindexMonitor {
18
- private progress: ReindexProgressData = {
19
- current: 0,
20
- total: 0,
21
- fileName: '',
22
- status: 'processing',
23
- phase: 'tokenizing',
24
- };
25
- private uiInstance?: any;
26
- private listeners = new Set<() => void>();
27
- private startTime = Date.now();
28
- private lastPercentage = -1; // Track last rendered percentage
29
-
30
- subscribe(listener: () => void) {
31
- this.listeners.add(listener);
32
- return () => {
33
- this.listeners.delete(listener);
34
- };
35
- }
36
-
37
- private triggerUpdate() {
38
- for (const listener of this.listeners) {
39
- listener();
40
- }
41
- }
42
-
43
- getProgress() {
44
- return this.progress;
45
- }
46
-
47
- getElapsedTime() {
48
- return Math.floor((Date.now() - this.startTime) / 1000);
49
- }
50
-
51
- updateProgress(data: Partial<ReindexProgressData>) {
52
- this.progress = { ...this.progress, ...data };
53
-
54
- // Only trigger UI update when percentage changes (to reduce render overhead)
55
- const currentPercentage =
56
- this.progress.total > 0 ? Math.floor((this.progress.current / this.progress.total) * 100) : 0;
57
-
58
- // Always trigger on phase change or when percentage actually changes
59
- if (data.phase || currentPercentage !== this.lastPercentage) {
60
- this.lastPercentage = currentPercentage;
61
- this.triggerUpdate();
62
- }
63
- }
64
-
65
- start(total: number) {
66
- this.progress = {
67
- current: 0,
68
- total,
69
- fileName: '',
70
- status: 'processing',
71
- phase: 'tokenizing',
72
- };
73
- this.startTime = Date.now();
74
-
75
- // Force Ink to work by ensuring proper terminal detection
76
- process.stdout.isTTY = true;
77
- process.stderr.isTTY = true;
78
-
79
- const uiInstance = render(<ReindexProgress monitor={this} />, {
80
- debug: false,
81
- patchConsole: false, // Don't patch console to allow direct stderr output
82
- exitOnCtrlC: false,
83
- });
84
-
85
- this.uiInstance = uiInstance;
86
- }
87
-
88
- stop() {
89
- if (this.uiInstance) {
90
- this.uiInstance.unmount();
91
- this.uiInstance = undefined;
92
- }
93
- }
94
- }
95
-
96
- interface ReindexProgressProps {
97
- monitor: ReindexMonitor;
98
- }
99
-
100
- const ReindexProgress: React.FC<ReindexProgressProps> = ({ monitor }) => {
101
- const { exit } = useApp();
102
- // Use React state instead of reading from monitor directly
103
- const [progress, setProgress] = React.useState<ReindexProgressData>(monitor.getProgress());
104
- const [elapsedTime, setElapsedTime] = React.useState(0);
105
-
106
- // Subscribe to progress updates and update React state
107
- React.useEffect(() => {
108
- const unsubscribe = monitor.subscribe(() => {
109
- const newProgress = monitor.getProgress();
110
- setProgress(newProgress);
111
- setElapsedTime(monitor.getElapsedTime());
112
-
113
- // Show progress updates (Ink UI is too slow to render, so we use console.error for immediate feedback)
114
- if (newProgress.current % 20 === 0) {
115
- const percentage = Math.floor((newProgress.current / newProgress.total) * 100);
116
- console.error(`📦 ${newProgress.current}/${newProgress.total} files (${percentage}%)`);
117
- }
118
- });
119
- return unsubscribe;
120
- }, [monitor]);
121
-
122
- // Update elapsed time every second (not every 100ms)
123
- React.useEffect(() => {
124
- const interval = setInterval(() => {
125
- setElapsedTime(monitor.getElapsedTime());
126
- }, 1000); // Every 1 second instead of 100ms
127
- return () => clearInterval(interval);
128
- }, [monitor]);
129
- const percentage = progress.total > 0 ? Math.floor((progress.current / progress.total) * 100) : 0;
130
-
131
- // Calculate estimated time remaining
132
- const avgTimePerFile = progress.current > 0 ? elapsedTime / progress.current : 0;
133
- const remainingFiles = progress.total - progress.current;
134
- const estimatedRemaining = Math.ceil(avgTimePerFile * remainingFiles);
135
-
136
- // Build progress bar
137
- const barWidth = 40;
138
- const filledWidth = Math.floor((percentage / 100) * barWidth);
139
- const progressBar = '█'.repeat(filledWidth) + '░'.repeat(barWidth - filledWidth);
140
-
141
- // Auto-exit when completed
142
- React.useEffect(() => {
143
- if (progress.phase === 'completed') {
144
- setTimeout(() => {
145
- exit();
146
- }, 1000);
147
- }
148
- }, [progress.phase, exit]);
149
-
150
- return (
151
- <Box flexDirection="column" padding={1}>
152
- {/* Header */}
153
- <Box marginBottom={1}>
154
- <Text bold color="cyan">
155
- 🔤 Reindexing Codebase
156
- </Text>
157
- {progress.mode === 'tfidf-only' && (
158
- <Text color="yellow" dimColor>
159
- {' '}
160
- (TF-IDF mode - no API key)
161
- </Text>
162
- )}
163
- {progress.mode === 'semantic' && (
164
- <Text color="green" dimColor>
165
- {' '}
166
- (Semantic search enabled)
167
- </Text>
168
- )}
169
- </Box>
170
-
171
- {/* API key hint */}
172
- {progress.mode === 'tfidf-only' && progress.phase === 'tokenizing' && (
173
- <Box marginBottom={1}>
174
- <Text color="gray" dimColor>
175
- 💡 Tip: Set OPENAI_API_KEY for semantic search with embeddings
176
- </Text>
177
- </Box>
178
- )}
179
-
180
- {/* Progress bar */}
181
- <Box marginBottom={1}>
182
- <Box width={barWidth + 2} marginRight={2}>
183
- <Text color="blue">{progressBar}</Text>
184
- </Box>
185
- <Text color="cyan" bold>
186
- {percentage}%
187
- </Text>
188
- </Box>
189
-
190
- {/* Current file and stats */}
191
- <Box flexDirection="column" marginBottom={1}>
192
- <Box>
193
- <Text color="gray">Progress: </Text>
194
- <Text color="white">
195
- {progress.current}/{progress.total} files
196
- </Text>
197
- </Box>
198
-
199
- {progress.phase === 'tokenizing' && progress.fileName && (
200
- <Box>
201
- <Text color="gray">Current: </Text>
202
- <Text color="yellow">{progress.fileName}</Text>
203
- </Box>
204
- )}
205
-
206
- {progress.phase === 'calculating' && (
207
- <Box>
208
- <Text color="cyan">⚡ Calculating TF-IDF scores...</Text>
209
- </Box>
210
- )}
211
- </Box>
212
-
213
- {/* Timing info */}
214
- <Box flexDirection="column" marginBottom={1}>
215
- <Box>
216
- <Text color="gray">Elapsed: </Text>
217
- <Text color="white">{formatTime(elapsedTime)}</Text>
218
- </Box>
219
-
220
- {progress.phase === 'tokenizing' && remainingFiles > 0 && (
221
- <Box>
222
- <Text color="gray">Estimated: </Text>
223
- <Text color="white">{formatTime(estimatedRemaining)} remaining</Text>
224
- </Box>
225
- )}
226
- </Box>
227
-
228
- {/* Final stats when completed */}
229
- {progress.phase === 'completed' && progress.stats && (
230
- <Box flexDirection="column" marginTop={1}>
231
- <Text color="green" bold>
232
- ✓ Indexing Complete!
233
- </Text>
234
- <Box marginTop={1}>
235
- <Text color="gray">Documents: </Text>
236
- <Text color="white">{progress.stats.documentsProcessed}</Text>
237
- </Box>
238
- <Box>
239
- <Text color="gray">Unique terms: </Text>
240
- <Text color="white">{progress.stats.uniqueTerms.toLocaleString()}</Text>
241
- </Box>
242
- <Box>
243
- <Text color="gray">Total time: </Text>
244
- <Text color="white">{formatTime(elapsedTime)}</Text>
245
- </Box>
246
- </Box>
247
- )}
248
- </Box>
249
- );
250
- };
251
-
252
- function formatTime(seconds: number): string {
253
- if (seconds < 60) {
254
- return `${seconds}s`;
255
- }
256
- const minutes = Math.floor(seconds / 60);
257
- const secs = seconds % 60;
258
- return `${minutes}m ${secs}s`;
259
- }
260
-
261
- export { ReindexProgress };
@@ -1,14 +0,0 @@
1
- /**
2
- * Functional composables
3
- * Reusable abstractions following functional principles
4
- *
5
- * DESIGN RATIONALE:
6
- * - Pure functions where possible
7
- * - Side effects isolated and explicit
8
- * - Result/Option types for error handling
9
- * - Type-safe operations
10
- * - Composable utilities
11
- */
12
-
13
- export * from './useEnvironment.js';
14
- export * from './useFileSystem.js';