@sylphx/flow 1.8.0 → 1.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +52 -0
- package/assets/output-styles/silent.md +141 -8
- package/assets/rules/core.md +19 -2
- package/package.json +2 -12
- package/src/commands/flow/execute.ts +470 -0
- package/src/commands/flow/index.ts +11 -0
- package/src/commands/flow/prompt.ts +35 -0
- package/src/commands/flow/setup.ts +312 -0
- package/src/commands/flow/targets.ts +18 -0
- package/src/commands/flow/types.ts +47 -0
- package/src/commands/flow-command.ts +18 -967
- package/src/commands/flow-orchestrator.ts +14 -5
- package/src/commands/hook-command.ts +1 -1
- package/src/commands/init-core.ts +12 -3
- package/src/commands/run-command.ts +1 -1
- package/src/config/rules.ts +1 -1
- package/src/core/error-handling.ts +1 -1
- package/src/core/loop-controller.ts +1 -1
- package/src/core/state-detector.ts +1 -1
- package/src/core/target-manager.ts +1 -1
- package/src/index.ts +1 -1
- package/src/shared/files/index.ts +1 -1
- package/src/shared/processing/index.ts +1 -1
- package/src/targets/claude-code.ts +3 -3
- package/src/targets/opencode.ts +3 -3
- package/src/utils/agent-enhancer.ts +2 -2
- package/src/utils/{mcp-config.ts → config/mcp-config.ts} +4 -4
- package/src/utils/{paths.ts → config/paths.ts} +1 -1
- package/src/utils/{settings.ts → config/settings.ts} +1 -1
- package/src/utils/{target-config.ts → config/target-config.ts} +5 -5
- package/src/utils/{target-utils.ts → config/target-utils.ts} +3 -3
- package/src/utils/display/banner.ts +25 -0
- package/src/utils/display/status.ts +55 -0
- package/src/utils/{file-operations.ts → files/file-operations.ts} +2 -2
- package/src/utils/files/jsonc.ts +36 -0
- package/src/utils/{sync-utils.ts → files/sync-utils.ts} +3 -3
- package/src/utils/index.ts +42 -61
- package/src/utils/version.ts +47 -0
- package/src/components/benchmark-monitor.tsx +0 -331
- package/src/components/reindex-progress.tsx +0 -261
- package/src/composables/functional/index.ts +0 -14
- package/src/composables/functional/useEnvironment.ts +0 -171
- package/src/composables/functional/useFileSystem.ts +0 -139
- package/src/composables/index.ts +0 -4
- package/src/composables/useEnv.ts +0 -13
- package/src/composables/useRuntimeConfig.ts +0 -27
- package/src/core/ai-sdk.ts +0 -603
- package/src/core/app-factory.ts +0 -381
- package/src/core/builtin-agents.ts +0 -9
- package/src/core/command-system.ts +0 -550
- package/src/core/config-system.ts +0 -550
- package/src/core/connection-pool.ts +0 -390
- package/src/core/di-container.ts +0 -155
- package/src/core/headless-display.ts +0 -96
- package/src/core/interfaces/index.ts +0 -22
- package/src/core/interfaces/repository.interface.ts +0 -91
- package/src/core/interfaces/service.interface.ts +0 -133
- package/src/core/interfaces.ts +0 -96
- package/src/core/result.ts +0 -351
- package/src/core/service-config.ts +0 -252
- package/src/core/session-service.ts +0 -121
- package/src/core/storage-factory.ts +0 -115
- package/src/core/stream-handler.ts +0 -288
- package/src/core/type-utils.ts +0 -427
- package/src/core/unified-storage.ts +0 -456
- package/src/core/validation/limit.ts +0 -46
- package/src/core/validation/query.ts +0 -20
- package/src/db/auto-migrate.ts +0 -322
- package/src/db/base-database-client.ts +0 -144
- package/src/db/cache-db.ts +0 -218
- package/src/db/cache-schema.ts +0 -75
- package/src/db/database.ts +0 -70
- package/src/db/index.ts +0 -252
- package/src/db/memory-db.ts +0 -153
- package/src/db/memory-schema.ts +0 -29
- package/src/db/schema.ts +0 -289
- package/src/db/session-repository.ts +0 -733
- package/src/domains/index.ts +0 -6
- package/src/domains/utilities/index.ts +0 -6
- package/src/domains/utilities/time/index.ts +0 -5
- package/src/domains/utilities/time/tools.ts +0 -291
- package/src/services/agent-service.ts +0 -273
- package/src/services/evaluation-service.ts +0 -271
- package/src/services/functional/evaluation-logic.ts +0 -296
- package/src/services/functional/file-processor.ts +0 -273
- package/src/services/functional/index.ts +0 -12
- package/src/services/memory.service.ts +0 -476
- package/src/types/api/batch.ts +0 -108
- package/src/types/api/errors.ts +0 -118
- package/src/types/api/index.ts +0 -55
- package/src/types/api/requests.ts +0 -76
- package/src/types/api/responses.ts +0 -180
- package/src/types/api/websockets.ts +0 -85
- package/src/types/benchmark.ts +0 -49
- package/src/types/database.types.ts +0 -510
- package/src/types/memory-types.ts +0 -63
- package/src/utils/advanced-tokenizer.ts +0 -191
- package/src/utils/ai-model-fetcher.ts +0 -19
- package/src/utils/async-file-operations.ts +0 -516
- package/src/utils/audio-player.ts +0 -345
- package/src/utils/codebase-helpers.ts +0 -211
- package/src/utils/console-ui.ts +0 -79
- package/src/utils/database-errors.ts +0 -140
- package/src/utils/debug-logger.ts +0 -49
- package/src/utils/file-scanner.ts +0 -259
- package/src/utils/help.ts +0 -20
- package/src/utils/immutable-cache.ts +0 -106
- package/src/utils/jsonc.ts +0 -158
- package/src/utils/memory-tui.ts +0 -414
- package/src/utils/models-dev.ts +0 -91
- package/src/utils/parallel-operations.ts +0 -487
- package/src/utils/process-manager.ts +0 -155
- package/src/utils/prompts.ts +0 -120
- package/src/utils/search-tool-builder.ts +0 -214
- package/src/utils/session-manager.ts +0 -168
- package/src/utils/session-title.ts +0 -87
- package/src/utils/simplified-errors.ts +0 -410
- package/src/utils/template-engine.ts +0 -94
- package/src/utils/test-audio.ts +0 -71
- package/src/utils/todo-context.ts +0 -46
- package/src/utils/token-counter.ts +0 -288
- /package/src/utils/{cli-output.ts → display/cli-output.ts} +0 -0
- /package/src/utils/{logger.ts → display/logger.ts} +0 -0
- /package/src/utils/{notifications.ts → display/notifications.ts} +0 -0
- /package/src/utils/{secret-utils.ts → security/secret-utils.ts} +0 -0
- /package/src/utils/{security.ts → security/security.ts} +0 -0
|
@@ -1,345 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Cross-Platform Audio Player
|
|
3
|
-
* Detects and uses available audio players across different platforms
|
|
4
|
-
*
|
|
5
|
-
* Supported players (in priority order):
|
|
6
|
-
* - macOS: afplay (built-in)
|
|
7
|
-
* - Linux: mpg123, mpg321, play (sox), aplay, mplayer, cvlc
|
|
8
|
-
* - Windows: powershell (built-in), cmdmp3
|
|
9
|
-
* - Universal: mplayer, omxplayer (Raspberry Pi)
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
import { spawn } from 'child_process';
|
|
13
|
-
import { existsSync } from 'fs';
|
|
14
|
-
import { join } from 'path';
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Audio player configuration
|
|
18
|
-
*/
|
|
19
|
-
interface AudioPlayer {
|
|
20
|
-
name: string;
|
|
21
|
-
command: string;
|
|
22
|
-
args: (filePath: string) => string[];
|
|
23
|
-
platforms: NodeJS.Platform[];
|
|
24
|
-
checkAvailability?: () => Promise<boolean>;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Available audio players in priority order
|
|
29
|
-
*/
|
|
30
|
-
const AUDIO_PLAYERS: AudioPlayer[] = [
|
|
31
|
-
// macOS built-in
|
|
32
|
-
{
|
|
33
|
-
name: 'afplay',
|
|
34
|
-
command: 'afplay',
|
|
35
|
-
args: (file) => [file],
|
|
36
|
-
platforms: ['darwin'],
|
|
37
|
-
},
|
|
38
|
-
|
|
39
|
-
// Linux players (in priority order)
|
|
40
|
-
{
|
|
41
|
-
name: 'mpg123',
|
|
42
|
-
command: 'mpg123',
|
|
43
|
-
args: (file) => ['-q', file], // quiet mode
|
|
44
|
-
platforms: ['linux', 'freebsd', 'openbsd'],
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
name: 'mpg321',
|
|
48
|
-
command: 'mpg321',
|
|
49
|
-
args: (file) => ['-q', file], // quiet mode
|
|
50
|
-
platforms: ['linux', 'freebsd', 'openbsd'],
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
name: 'play',
|
|
54
|
-
command: 'play',
|
|
55
|
-
args: (file) => ['-q', file], // sox play command
|
|
56
|
-
platforms: ['linux', 'freebsd', 'openbsd', 'darwin'],
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
name: 'aplay',
|
|
60
|
-
command: 'aplay',
|
|
61
|
-
args: (file) => ['-q', file], // ALSA player
|
|
62
|
-
platforms: ['linux'],
|
|
63
|
-
},
|
|
64
|
-
{
|
|
65
|
-
name: 'mplayer',
|
|
66
|
-
command: 'mplayer',
|
|
67
|
-
args: (file) => ['-really-quiet', file],
|
|
68
|
-
platforms: ['linux', 'freebsd', 'openbsd', 'darwin', 'win32'],
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
name: 'cvlc',
|
|
72
|
-
command: 'cvlc',
|
|
73
|
-
args: (file) => ['--play-and-exit', '--quiet', file], // VLC command-line
|
|
74
|
-
platforms: ['linux', 'freebsd', 'openbsd', 'darwin', 'win32'],
|
|
75
|
-
},
|
|
76
|
-
{
|
|
77
|
-
name: 'omxplayer',
|
|
78
|
-
command: 'omxplayer',
|
|
79
|
-
args: (file) => ['-o', 'local', file], // Raspberry Pi
|
|
80
|
-
platforms: ['linux'],
|
|
81
|
-
},
|
|
82
|
-
|
|
83
|
-
// Windows players
|
|
84
|
-
{
|
|
85
|
-
name: 'powershell',
|
|
86
|
-
command: 'powershell',
|
|
87
|
-
args: (file) => [
|
|
88
|
-
'-NoProfile',
|
|
89
|
-
'-NonInteractive',
|
|
90
|
-
'-Command',
|
|
91
|
-
`(New-Object Media.SoundPlayer "${file}").PlaySync()`
|
|
92
|
-
],
|
|
93
|
-
platforms: ['win32'],
|
|
94
|
-
// PowerShell Media.SoundPlayer only supports WAV files
|
|
95
|
-
checkAvailability: async () => {
|
|
96
|
-
// Check if we're on Windows and file is WAV
|
|
97
|
-
return process.platform === 'win32';
|
|
98
|
-
}
|
|
99
|
-
},
|
|
100
|
-
{
|
|
101
|
-
name: 'cmdmp3',
|
|
102
|
-
command: 'cmdmp3',
|
|
103
|
-
args: (file) => [file],
|
|
104
|
-
platforms: ['win32'],
|
|
105
|
-
},
|
|
106
|
-
];
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Cached available player to avoid repeated checks
|
|
110
|
-
*/
|
|
111
|
-
let cachedPlayer: AudioPlayer | null = null;
|
|
112
|
-
let cacheChecked = false;
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Check if a command is available in PATH
|
|
116
|
-
*/
|
|
117
|
-
async function isCommandAvailable(command: string): Promise<boolean> {
|
|
118
|
-
return new Promise((resolve) => {
|
|
119
|
-
// Try to execute the command with --version or --help
|
|
120
|
-
const proc = spawn(command, ['--version'], {
|
|
121
|
-
stdio: 'ignore',
|
|
122
|
-
shell: true
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
proc.on('error', () => resolve(false));
|
|
126
|
-
proc.on('exit', (code) => {
|
|
127
|
-
// Some commands return non-zero for --version, so just check if they exist
|
|
128
|
-
resolve(true);
|
|
129
|
-
});
|
|
130
|
-
|
|
131
|
-
// Timeout after 1 second
|
|
132
|
-
setTimeout(() => {
|
|
133
|
-
proc.kill();
|
|
134
|
-
resolve(false);
|
|
135
|
-
}, 1000);
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Detect the first available audio player for current platform
|
|
141
|
-
*/
|
|
142
|
-
export async function detectAudioPlayer(): Promise<AudioPlayer | null> {
|
|
143
|
-
if (cacheChecked && cachedPlayer) {
|
|
144
|
-
return cachedPlayer;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
const currentPlatform = process.platform;
|
|
148
|
-
|
|
149
|
-
// Filter players for current platform
|
|
150
|
-
const compatiblePlayers = AUDIO_PLAYERS.filter(
|
|
151
|
-
(player) => player.platforms.includes(currentPlatform)
|
|
152
|
-
);
|
|
153
|
-
|
|
154
|
-
// Check each player in priority order
|
|
155
|
-
for (const player of compatiblePlayers) {
|
|
156
|
-
// Custom availability check if provided
|
|
157
|
-
if (player.checkAvailability) {
|
|
158
|
-
const isAvailable = await player.checkAvailability();
|
|
159
|
-
if (!isAvailable) continue;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Check if command is available
|
|
163
|
-
const isAvailable = await isCommandAvailable(player.command);
|
|
164
|
-
if (isAvailable) {
|
|
165
|
-
cachedPlayer = player;
|
|
166
|
-
cacheChecked = true;
|
|
167
|
-
return player;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
cacheChecked = true;
|
|
172
|
-
return null;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/**
|
|
176
|
-
* Play audio file using the best available player
|
|
177
|
-
* @param filePath Absolute path to audio file
|
|
178
|
-
* @param options Playback options
|
|
179
|
-
* @returns Promise that resolves when playback completes or rejects on error
|
|
180
|
-
*/
|
|
181
|
-
export async function playSound(
|
|
182
|
-
filePath: string,
|
|
183
|
-
options?: {
|
|
184
|
-
volume?: number; // 0-100 (not supported by all players)
|
|
185
|
-
background?: boolean; // Play in background (default: true)
|
|
186
|
-
timeout?: number; // Max playback duration in ms (default: 5000)
|
|
187
|
-
}
|
|
188
|
-
): Promise<void> {
|
|
189
|
-
const {
|
|
190
|
-
background = true,
|
|
191
|
-
timeout = 5000
|
|
192
|
-
} = options || {};
|
|
193
|
-
|
|
194
|
-
// Check if file exists
|
|
195
|
-
if (!existsSync(filePath)) {
|
|
196
|
-
throw new Error(`Audio file not found: ${filePath}`);
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// Detect available player
|
|
200
|
-
const player = await detectAudioPlayer();
|
|
201
|
-
if (!player) {
|
|
202
|
-
throw new Error('No audio player available on this system');
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
return new Promise((resolve, reject) => {
|
|
206
|
-
const args = player.args(filePath);
|
|
207
|
-
const proc = spawn(player.command, args, {
|
|
208
|
-
stdio: 'ignore',
|
|
209
|
-
detached: background,
|
|
210
|
-
});
|
|
211
|
-
|
|
212
|
-
// If background mode, unref and resolve immediately
|
|
213
|
-
if (background) {
|
|
214
|
-
proc.unref();
|
|
215
|
-
resolve();
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Otherwise wait for completion
|
|
220
|
-
let timeoutId: NodeJS.Timeout | null = null;
|
|
221
|
-
|
|
222
|
-
proc.on('error', (error) => {
|
|
223
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
224
|
-
reject(new Error(`Audio player error: ${error.message}`));
|
|
225
|
-
});
|
|
226
|
-
|
|
227
|
-
proc.on('exit', (code) => {
|
|
228
|
-
if (timeoutId) clearTimeout(timeoutId);
|
|
229
|
-
if (code === 0) {
|
|
230
|
-
resolve();
|
|
231
|
-
} else {
|
|
232
|
-
reject(new Error(`Audio player exited with code ${code}`));
|
|
233
|
-
}
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
// Timeout protection
|
|
237
|
-
if (timeout > 0) {
|
|
238
|
-
timeoutId = setTimeout(() => {
|
|
239
|
-
proc.kill();
|
|
240
|
-
reject(new Error(`Audio playback timeout after ${timeout}ms`));
|
|
241
|
-
}, timeout);
|
|
242
|
-
}
|
|
243
|
-
});
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Get information about the detected audio player
|
|
248
|
-
*/
|
|
249
|
-
export async function getAudioPlayerInfo(): Promise<{
|
|
250
|
-
available: boolean;
|
|
251
|
-
player: string | null;
|
|
252
|
-
platform: string;
|
|
253
|
-
}> {
|
|
254
|
-
const player = await detectAudioPlayer();
|
|
255
|
-
|
|
256
|
-
return {
|
|
257
|
-
available: player !== null,
|
|
258
|
-
player: player?.name || null,
|
|
259
|
-
platform: process.platform
|
|
260
|
-
};
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/**
|
|
264
|
-
* Built-in system sounds for different platforms
|
|
265
|
-
*/
|
|
266
|
-
export const SYSTEM_SOUNDS = {
|
|
267
|
-
// macOS system sounds
|
|
268
|
-
darwin: {
|
|
269
|
-
glass: '/System/Library/Sounds/Glass.aiff',
|
|
270
|
-
hero: '/System/Library/Sounds/Hero.aiff',
|
|
271
|
-
pop: '/System/Library/Sounds/Pop.aiff',
|
|
272
|
-
ping: '/System/Library/Sounds/Ping.aiff',
|
|
273
|
-
purr: '/System/Library/Sounds/Purr.aiff',
|
|
274
|
-
submarine: '/System/Library/Sounds/Submarine.aiff',
|
|
275
|
-
blow: '/System/Library/Sounds/Blow.aiff',
|
|
276
|
-
bottle: '/System/Library/Sounds/Bottle.aiff',
|
|
277
|
-
frog: '/System/Library/Sounds/Frog.aiff',
|
|
278
|
-
funk: '/System/Library/Sounds/Funk.aiff',
|
|
279
|
-
morse: '/System/Library/Sounds/Morse.aiff',
|
|
280
|
-
},
|
|
281
|
-
// Linux typical locations (may vary)
|
|
282
|
-
linux: {
|
|
283
|
-
complete: '/usr/share/sounds/freedesktop/stereo/complete.oga',
|
|
284
|
-
message: '/usr/share/sounds/freedesktop/stereo/message.oga',
|
|
285
|
-
bell: '/usr/share/sounds/freedesktop/stereo/bell.oga',
|
|
286
|
-
dialog: '/usr/share/sounds/freedesktop/stereo/dialog-information.oga',
|
|
287
|
-
},
|
|
288
|
-
// Windows - would need .wav files
|
|
289
|
-
win32: {
|
|
290
|
-
// Windows Media directory sounds
|
|
291
|
-
notify: 'C:\\Windows\\Media\\Windows Notify.wav',
|
|
292
|
-
ding: 'C:\\Windows\\Media\\Windows Ding.wav',
|
|
293
|
-
chord: 'C:\\Windows\\Media\\chord.wav',
|
|
294
|
-
}
|
|
295
|
-
} as const;
|
|
296
|
-
|
|
297
|
-
/**
|
|
298
|
-
* Get default system sound for current platform
|
|
299
|
-
*/
|
|
300
|
-
export function getDefaultSystemSound(): string | null {
|
|
301
|
-
const platform = process.platform;
|
|
302
|
-
|
|
303
|
-
if (platform === 'darwin') {
|
|
304
|
-
return SYSTEM_SOUNDS.darwin.glass;
|
|
305
|
-
} else if (platform === 'linux') {
|
|
306
|
-
// Check which sound exists
|
|
307
|
-
const sounds = Object.values(SYSTEM_SOUNDS.linux);
|
|
308
|
-
for (const sound of sounds) {
|
|
309
|
-
if (existsSync(sound)) {
|
|
310
|
-
return sound;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
} else if (platform === 'win32') {
|
|
314
|
-
// Check which sound exists
|
|
315
|
-
const sounds = Object.values(SYSTEM_SOUNDS.win32);
|
|
316
|
-
for (const sound of sounds) {
|
|
317
|
-
if (existsSync(sound)) {
|
|
318
|
-
return sound;
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
return null;
|
|
324
|
-
}
|
|
325
|
-
|
|
326
|
-
/**
|
|
327
|
-
* Play system notification sound
|
|
328
|
-
*/
|
|
329
|
-
export async function playNotificationSound(): Promise<void> {
|
|
330
|
-
const soundPath = getDefaultSystemSound();
|
|
331
|
-
|
|
332
|
-
if (!soundPath) {
|
|
333
|
-
// No system sound available, just return silently
|
|
334
|
-
return;
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
try {
|
|
338
|
-
await playSound(soundPath, { background: true, timeout: 3000 });
|
|
339
|
-
} catch (error) {
|
|
340
|
-
// Fail silently - don't crash on sound playback errors
|
|
341
|
-
if (process.env.DEBUG) {
|
|
342
|
-
console.error('[Audio] Failed to play notification sound:', error);
|
|
343
|
-
}
|
|
344
|
-
}
|
|
345
|
-
}
|
|
@@ -1,211 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Codebase indexing helper functions
|
|
3
|
-
* Utility functions for file scanning and language detection
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import fs from 'node:fs';
|
|
7
|
-
import path from 'node:path';
|
|
8
|
-
import ignore, { type Ignore } from 'ignore';
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Detect programming language from file extension
|
|
12
|
-
*/
|
|
13
|
-
export function detectLanguage(filePath: string): string | undefined {
|
|
14
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
15
|
-
const languageMap: Record<string, string> = {
|
|
16
|
-
'.ts': 'TypeScript',
|
|
17
|
-
'.tsx': 'TSX',
|
|
18
|
-
'.js': 'JavaScript',
|
|
19
|
-
'.jsx': 'JSX',
|
|
20
|
-
'.py': 'Python',
|
|
21
|
-
'.java': 'Java',
|
|
22
|
-
'.go': 'Go',
|
|
23
|
-
'.rs': 'Rust',
|
|
24
|
-
'.c': 'C',
|
|
25
|
-
'.cpp': 'C++',
|
|
26
|
-
'.cs': 'C#',
|
|
27
|
-
'.rb': 'Ruby',
|
|
28
|
-
'.php': 'PHP',
|
|
29
|
-
'.swift': 'Swift',
|
|
30
|
-
'.kt': 'Kotlin',
|
|
31
|
-
'.md': 'Markdown',
|
|
32
|
-
'.json': 'JSON',
|
|
33
|
-
'.yaml': 'YAML',
|
|
34
|
-
'.yml': 'YAML',
|
|
35
|
-
'.toml': 'TOML',
|
|
36
|
-
'.sql': 'SQL',
|
|
37
|
-
'.sh': 'Shell',
|
|
38
|
-
'.bash': 'Bash',
|
|
39
|
-
};
|
|
40
|
-
return languageMap[ext];
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Check if file is text-based (not binary)
|
|
45
|
-
*/
|
|
46
|
-
export function isTextFile(filePath: string): boolean {
|
|
47
|
-
const textExtensions = new Set([
|
|
48
|
-
'.ts',
|
|
49
|
-
'.tsx',
|
|
50
|
-
'.js',
|
|
51
|
-
'.jsx',
|
|
52
|
-
'.py',
|
|
53
|
-
'.java',
|
|
54
|
-
'.go',
|
|
55
|
-
'.rs',
|
|
56
|
-
'.c',
|
|
57
|
-
'.cpp',
|
|
58
|
-
'.h',
|
|
59
|
-
'.hpp',
|
|
60
|
-
'.cs',
|
|
61
|
-
'.rb',
|
|
62
|
-
'.php',
|
|
63
|
-
'.swift',
|
|
64
|
-
'.kt',
|
|
65
|
-
'.md',
|
|
66
|
-
'.txt',
|
|
67
|
-
'.json',
|
|
68
|
-
'.yaml',
|
|
69
|
-
'.yml',
|
|
70
|
-
'.toml',
|
|
71
|
-
'.xml',
|
|
72
|
-
'.sql',
|
|
73
|
-
'.sh',
|
|
74
|
-
'.bash',
|
|
75
|
-
'.zsh',
|
|
76
|
-
'.fish',
|
|
77
|
-
'.dockerfile',
|
|
78
|
-
'.gitignore',
|
|
79
|
-
'.env',
|
|
80
|
-
'.env.example',
|
|
81
|
-
'.env.local',
|
|
82
|
-
'.env.development',
|
|
83
|
-
'.env.production',
|
|
84
|
-
]);
|
|
85
|
-
|
|
86
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
87
|
-
return textExtensions.has(ext) || !ext; // Files without extension might be text
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Load .gitignore file and create ignore filter
|
|
92
|
-
*/
|
|
93
|
-
export function loadGitignore(codebaseRoot: string): Ignore {
|
|
94
|
-
const ig = ignore();
|
|
95
|
-
|
|
96
|
-
// Add default ignore patterns
|
|
97
|
-
ig.add([
|
|
98
|
-
'node_modules',
|
|
99
|
-
'.git',
|
|
100
|
-
'.svn',
|
|
101
|
-
'.hg',
|
|
102
|
-
'.DS_Store',
|
|
103
|
-
'.idea',
|
|
104
|
-
'.vscode',
|
|
105
|
-
'*.suo',
|
|
106
|
-
'*.ntvs*',
|
|
107
|
-
'*.njsproj',
|
|
108
|
-
'*.sln',
|
|
109
|
-
'*.swp',
|
|
110
|
-
'.sylphx-flow',
|
|
111
|
-
'.cache',
|
|
112
|
-
'dist',
|
|
113
|
-
'build',
|
|
114
|
-
'coverage',
|
|
115
|
-
'.nyc_output',
|
|
116
|
-
]);
|
|
117
|
-
|
|
118
|
-
const gitignorePath = path.join(codebaseRoot, '.gitignore');
|
|
119
|
-
|
|
120
|
-
if (fs.existsSync(gitignorePath)) {
|
|
121
|
-
try {
|
|
122
|
-
const content = fs.readFileSync(gitignorePath, 'utf8');
|
|
123
|
-
ig.add(content);
|
|
124
|
-
} catch (error) {
|
|
125
|
-
console.warn(`[WARN] Failed to read .gitignore: ${error}`);
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return ig;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Scan directory recursively for files
|
|
134
|
-
*/
|
|
135
|
-
export interface ScanOptions {
|
|
136
|
-
ignoreFilter?: Ignore;
|
|
137
|
-
codebaseRoot?: string;
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
export interface ScanResult {
|
|
141
|
-
path: string;
|
|
142
|
-
absolutePath: string;
|
|
143
|
-
content: string;
|
|
144
|
-
size: number;
|
|
145
|
-
mtime: number;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Scan files in directory with .gitignore support
|
|
150
|
-
*/
|
|
151
|
-
export function scanFiles(dir: string, options: ScanOptions = {}): ScanResult[] {
|
|
152
|
-
const results: ScanResult[] = [];
|
|
153
|
-
const ignoreFilter = options.ignoreFilter;
|
|
154
|
-
const codebaseRoot = options.codebaseRoot || dir;
|
|
155
|
-
|
|
156
|
-
function scan(currentDir: string) {
|
|
157
|
-
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
158
|
-
|
|
159
|
-
for (const entry of entries) {
|
|
160
|
-
const fullPath = path.join(currentDir, entry.name);
|
|
161
|
-
const relativePath = path.relative(codebaseRoot, fullPath);
|
|
162
|
-
|
|
163
|
-
// Skip ignored files
|
|
164
|
-
if (ignoreFilter?.ignores(relativePath)) {
|
|
165
|
-
continue;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
if (entry.isDirectory()) {
|
|
169
|
-
scan(fullPath);
|
|
170
|
-
} else if (entry.isFile()) {
|
|
171
|
-
try {
|
|
172
|
-
const stats = fs.statSync(fullPath);
|
|
173
|
-
const _ext = path.extname(fullPath);
|
|
174
|
-
|
|
175
|
-
// Only process text files
|
|
176
|
-
if (!isTextFile(fullPath)) {
|
|
177
|
-
continue;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const content = fs.readFileSync(fullPath, 'utf8');
|
|
181
|
-
|
|
182
|
-
results.push({
|
|
183
|
-
path: relativePath,
|
|
184
|
-
absolutePath: fullPath,
|
|
185
|
-
content,
|
|
186
|
-
size: stats.size,
|
|
187
|
-
mtime: stats.mtimeMs,
|
|
188
|
-
});
|
|
189
|
-
} catch (error) {
|
|
190
|
-
console.warn(`[WARN] Failed to read file: ${relativePath}`, error);
|
|
191
|
-
}
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
scan(dir);
|
|
197
|
-
return results;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
/**
|
|
201
|
-
* Calculate simple hash for file content (for change detection)
|
|
202
|
-
*/
|
|
203
|
-
export function simpleHash(content: string): string {
|
|
204
|
-
let hash = 0;
|
|
205
|
-
for (let i = 0; i < content.length; i++) {
|
|
206
|
-
const char = content.charCodeAt(i);
|
|
207
|
-
hash = (hash << 5) - hash + char;
|
|
208
|
-
hash &= hash; // Convert to 32-bit integer
|
|
209
|
-
}
|
|
210
|
-
return hash.toString(36);
|
|
211
|
-
}
|
package/src/utils/console-ui.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Modern console UI utilities
|
|
3
|
-
* Progressive output with beautiful formatting
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import chalk from 'chalk';
|
|
7
|
-
|
|
8
|
-
export const ui = {
|
|
9
|
-
// Headers
|
|
10
|
-
header: (text: string) => {
|
|
11
|
-
console.log('');
|
|
12
|
-
console.log(chalk.cyan.bold(`▸ ${text}`));
|
|
13
|
-
},
|
|
14
|
-
|
|
15
|
-
subheader: (text: string) => {
|
|
16
|
-
console.log(chalk.gray(` ${text}`));
|
|
17
|
-
},
|
|
18
|
-
|
|
19
|
-
// Status messages
|
|
20
|
-
success: (text: string) => {
|
|
21
|
-
console.log(chalk.green(`✓ ${text}`));
|
|
22
|
-
},
|
|
23
|
-
|
|
24
|
-
error: (text: string) => {
|
|
25
|
-
console.log(chalk.red(`✗ ${text}`));
|
|
26
|
-
},
|
|
27
|
-
|
|
28
|
-
warning: (text: string) => {
|
|
29
|
-
console.log(chalk.yellow(`⚠ ${text}`));
|
|
30
|
-
},
|
|
31
|
-
|
|
32
|
-
info: (text: string) => {
|
|
33
|
-
console.log(chalk.cyan(`ℹ ${text}`));
|
|
34
|
-
},
|
|
35
|
-
|
|
36
|
-
// Progress
|
|
37
|
-
step: (text: string) => {
|
|
38
|
-
console.log(chalk.gray(` • ${text}`));
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
loading: (text: string) => {
|
|
42
|
-
console.log(chalk.cyan(`⏳ ${text}`));
|
|
43
|
-
},
|
|
44
|
-
|
|
45
|
-
// Fields
|
|
46
|
-
field: (label: string, value: string, secret = false) => {
|
|
47
|
-
const displayValue = secret ? '•'.repeat(Math.min(8, value.length)) : value;
|
|
48
|
-
console.log(` ${chalk.gray(label)}: ${chalk.white(displayValue)}`);
|
|
49
|
-
},
|
|
50
|
-
|
|
51
|
-
// Dividers
|
|
52
|
-
divider: () => {
|
|
53
|
-
console.log(chalk.gray(' ─'.repeat(40)));
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
spacer: () => {
|
|
57
|
-
console.log('');
|
|
58
|
-
},
|
|
59
|
-
|
|
60
|
-
// Lists
|
|
61
|
-
list: (items: string[]) => {
|
|
62
|
-
items.forEach((item) => {
|
|
63
|
-
console.log(chalk.gray(` • ${item}`));
|
|
64
|
-
});
|
|
65
|
-
},
|
|
66
|
-
|
|
67
|
-
// Input prompt (for simple inputs)
|
|
68
|
-
prompt: (label: string, required = false) => {
|
|
69
|
-
const indicator = required ? chalk.red('*') : '';
|
|
70
|
-
return `${chalk.cyan('❯')} ${label}${indicator}: `;
|
|
71
|
-
},
|
|
72
|
-
|
|
73
|
-
// Section
|
|
74
|
-
section: (title: string, content: () => void) => {
|
|
75
|
-
console.log('');
|
|
76
|
-
console.log(chalk.cyan.bold(`▸ ${title}`));
|
|
77
|
-
content();
|
|
78
|
-
},
|
|
79
|
-
};
|