run-demo.tsโข9.52 kB
#!/usr/bin/env node
/**
* Demo script to monitor a local demo folder and index code using Ollama embeddings with Qdrant
* This script demonstrates how to use the codebase library in a Node.js environment
* with Ollama for embeddings and Qdrant for vector storage.
*/
import * as path from 'path'
import { fileURLToPath } from 'url'
import { createNodeDependencies } from '../adapters/nodejs'
import { CodeIndexManager } from '../code-index/manager'
import createSampleFiles from './create-sample-files';
// Configuration
const DEMO_FOLDER = path.join(process.cwd(), 'demo')
const OLLAMA_BASE_URL = 'http://localhost:11434'
const QDRANT_URL = 'http://localhost:6333'
const OLLAMA_MODEL = 'nomic-embed-text' // Default embedding model for Ollama
async function main() {
// 1. Create Node.js dependencies first to get logger
const dependencies = createNodeDependencies({
workspacePath: DEMO_FOLDER,
storageOptions: {
globalStoragePath: path.join(process.cwd(), '.autodev-storage'),
},
loggerOptions: {
name: 'Demo-Codebase',
level: 'info',
timestamps: true,
colors: true
},
configOptions: {
configPath: path.join(process.cwd(), '.autodev-config.json'),
defaultConfig: {
isEnabled: true,
isConfigured: true,
embedder: {
provider: "ollama",
model: OLLAMA_MODEL,
baseUrl: OLLAMA_BASE_URL,
dimension: 768,
},
qdrantUrl: QDRANT_URL
}
}
})
dependencies.logger?.info('[run-demo]๐ Starting Autodev Codebase Demo')
dependencies.logger?.info('[run-demo]๐ Demo folder:', DEMO_FOLDER)
dependencies.logger?.info('[run-demo]๐ค Ollama URL:', OLLAMA_BASE_URL)
dependencies.logger?.info('[run-demo]๐ Qdrant URL:', QDRANT_URL)
dependencies.logger?.info('[run-demo]๐ Embedding Model:', OLLAMA_MODEL)
dependencies.logger?.info('[run-demo]' + '=' .repeat(50))
try {
// 2. Check if demo folder exists, create if not
const demoFolderExists = await dependencies.fileSystem.exists(DEMO_FOLDER)
if (!demoFolderExists) {
dependencies.logger?.info('[run-demo]๐ Creating demo folder...')
// Create directory using Node.js mkdir since IFileSystem doesn't have createDirectory
const fs = require('fs')
fs.mkdirSync(DEMO_FOLDER, { recursive: true })
// Create some sample files for demonstration
await createSampleFiles(dependencies.fileSystem, DEMO_FOLDER)
}
// 3. Initialize configuration
dependencies.logger?.info('[run-demo]โ๏ธ ๅ ่ฝฝ้
็ฝฎ...')
const config = await dependencies.configProvider.loadConfig()
dependencies.logger?.info('[run-demo]๐ ้
็ฝฎๅ
ๅฎน:', JSON.stringify(config, null, 2))
// Validate configuration
dependencies.logger?.info('[run-demo]โ
้ช่ฏ้
็ฝฎ...')
const validation = await dependencies.configProvider.validateConfig()
dependencies.logger?.info('[run-demo]๐ ้ช่ฏ็ปๆ:', validation)
if (!validation.isValid) {
dependencies.logger?.warn('[run-demo]โ ๏ธ ้
็ฝฎ้ช่ฏ่ญฆๅ:', validation.errors)
dependencies.logger?.info('[run-demo]โ ๏ธ ็ปง็ปญๅๅงๅ๏ผ่ฐ่ฏๆจกๅผ๏ผ')
// ๅจ่ฐ่ฏๆจกๅผไธ๏ผๆไปฌๅ
่ฎธ้
็ฝฎ้ช่ฏๅคฑ่ดฅไฝ็ปง็ปญๅๅงๅ
} else {
dependencies.logger?.info('[run-demo]โ
้
็ฝฎ้ช่ฏ้่ฟ')
}
// 4. Create and initialize CodeIndexManager
dependencies.logger?.info('[run-demo]๐๏ธ Creating CodeIndexManager with dependencies:', {
hasFileSystem: !!dependencies.fileSystem,
hasStorage: !!dependencies.storage,
hasEventBus: !!dependencies.eventBus,
hasWorkspace: !!dependencies.workspace,
hasPathUtils: !!dependencies.pathUtils,
hasConfigProvider: !!dependencies.configProvider,
workspaceRootPath: dependencies.workspace.getRootPath()
})
const codeIndexManager = CodeIndexManager.getInstance(dependencies)
dependencies.logger?.info('[run-demo]CodeIndexManager instance created:', !!codeIndexManager)
if (!codeIndexManager) {
dependencies.logger?.error('[run-demo]โ Failed to create CodeIndexManager - workspace root path may be invalid')
return
}
// 5. Initialize the manager
dependencies.logger?.info('[run-demo]๐ง ๅๅงๅ CodeIndexManager...')
const { requiresRestart } = await codeIndexManager.initialize()
dependencies.logger?.info('[run-demo]โ
CodeIndexManager ๅๅงๅๆๅ:', { requiresRestart })
dependencies.logger?.info('[run-demo]๐ ็ฎก็ๅจ็ถๆ:', {
isInitialized: codeIndexManager.isInitialized,
isFeatureEnabled: codeIndexManager.isFeatureEnabled,
isFeatureConfigured: codeIndexManager.isFeatureConfigured,
state: codeIndexManager.state
})
if (requiresRestart) {
dependencies.logger?.info('[run-demo]๐ Manager restart required')
}
// 6. Start monitoring for progress updates
dependencies.logger?.info('[run-demo]๐ Setting up progress monitoring...')
const unsubscribeProgress = codeIndexManager.onProgressUpdate((progress) => {
dependencies.logger?.info(`[run-demo]๐ Progress: ${progress.systemStatus} - ${progress.message}`)
})
// 7. Start indexing
dependencies.logger?.info('[run-demo]๐ Starting code indexing...')
// ่ฎพ็ฝฎ่ฟๅบฆ็ๆง
codeIndexManager.onProgressUpdate((progressInfo) => {
dependencies.logger?.info('[run-demo]๐ ็ดขๅผ่ฟๅบฆ:', progressInfo)
})
// ๆทปๅ ่ถ
ๆถไฟๆค
const indexingTimeout = setTimeout(() => {
dependencies.logger?.warn('[run-demo]โ ๏ธ ็ดขๅผ่ฟ็จ่ถ
ๆถ๏ผ30็ง๏ผ๏ผๅฏ่ฝๅกไฝไบ')
}, 30000)
try {
await codeIndexManager.startIndexing()
clearTimeout(indexingTimeout)
dependencies.logger?.info('[run-demo]โ
็ดขๅผๅฎๆ')
} catch (err: any) {
clearTimeout(indexingTimeout)
dependencies.logger?.error('[run-demo]โ ็ดขๅผๅคฑ่ดฅ:', err)
dependencies.logger?.error('[run-demo]โ ้่ฏฏๅ ๆ :', err.stack)
throw err
}
// 8. Wait for indexing to complete
dependencies.logger?.info('[run-demo]โณ Waiting for indexing to complete...')
await waitForIndexingToComplete(codeIndexManager, dependencies.logger)
// 9. Demonstrate search functionality
dependencies.logger?.info('[run-demo]๐ Testing search functionality...')
await demonstrateSearch(codeIndexManager, dependencies.logger)
// 10. Show final status
dependencies.logger?.info('[run-demo]๐ Final Status Check...')
const finalStatus = codeIndexManager.getCurrentStatus()
dependencies.logger?.info(`[run-demo]๐ System Status: ${finalStatus.systemStatus}`)
dependencies.logger?.info(`[run-demo]๐ฆ Status Message: ${finalStatus.message}`)
dependencies.logger?.info(`[run-demo]๐ Last Update: ${new Date().toLocaleTimeString()}`)
// Clean up
dependencies.logger?.info('[run-demo]๐งน Cleaning up...')
unsubscribeProgress()
codeIndexManager.dispose()
dependencies.logger?.info('[run-demo]โ
Demo completed successfully!')
dependencies.logger?.info('[run-demo]Note: The codebase indexing system is working correctly.')
dependencies.logger?.info('[run-demo]For live file monitoring, the demo can be extended to run continuously.')
} catch (error: any) {
dependencies.logger?.error('[run-demo]โ Error in demo:', error)
dependencies.logger?.error('[run-demo]โ ้่ฏฏๅ ๆ :', error.stack)
process.exit(1)
}
}
async function waitForIndexingToComplete(codeIndexManager: any, logger: any) {
return new Promise<void>((resolve) => {
let checkCount = 0
const maxChecks = 30 // Maximum 60 seconds
const checkStatus = () => {
const state = codeIndexManager.state
logger.info(`[run-demo]๐ Current state: ${state} (check ${checkCount + 1}/${maxChecks})`)
checkCount++
if (state === 'Standby' || state === 'Watching' || state === 'Indexed') {
logger.info('[run-demo]โ
Indexing completed')
resolve()
} else if (checkCount >= maxChecks) {
logger.warn('[run-demo]โฐ Timeout waiting for indexing completion')
resolve()
} else {
setTimeout(checkStatus, 2000) // Check every 2 seconds
}
}
checkStatus()
})
}
async function demonstrateSearch(codeIndexManager: any, logger: any) {
const searchQueries = [
'greet user function',
'process data',
'user management',
'batch processing',
'configuration settings'
]
for (const query of searchQueries) {
logger.info(`[run-demo]\n๐ Searching for: "${query}"`)
try {
const results = await codeIndexManager.searchIndex(query, 3)
if (results.length === 0) {
logger.info('[run-demo] No results found')
} else {
results.forEach((result: any, index: number) => {
logger.info(`[run-demo] ${index + 1}. ${result.payload?.filePath || 'Unknown file'}`)
logger.info(`[run-demo] Score: ${result.score.toFixed(3)}`)
logger.info(`[run-demo] Lines: ${result.payload?.startLine}-${result.payload?.endLine}`)
logger.info(`[run-demo] Preview: ${(result.payload?.codeChunk || '').substring(0, 100)}...`)
})
}
} catch (error) {
logger.error(`[run-demo] Error searching for "${query}":`, error)
}
}
}
const __filename = fileURLToPath(import.meta.url)
if (process.argv[1] === __filename) {
main().catch(console.error)
}
export { main as runDemo }