Initial commit
This commit is contained in:
91
scripts/README.md
Normal file
91
scripts/README.md
Normal file
@@ -0,0 +1,91 @@
|
||||
# Google Gemini File Search CLI Scripts
|
||||
|
||||
This directory contains CLI tools for managing Google Gemini File Search stores and documents.
|
||||
|
||||
## Available Scripts
|
||||
|
||||
### ✅ create-store.ts
|
||||
Create a new file search store.
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
ts-node create-store.ts --name "My Knowledge Base" --project "customer-support" --environment "production"
|
||||
```
|
||||
|
||||
**Status:** Complete
|
||||
|
||||
### 🚧 upload-batch.ts (TO BE IMPLEMENTED)
|
||||
Batch upload documents to a file search store with progress tracking.
|
||||
|
||||
**Planned Features:**
|
||||
- Concurrent uploads with configurable batch size
|
||||
- Progress bar with ETA
|
||||
- Automatic chunking configuration per file type
|
||||
- Metadata extraction from file path/name
|
||||
- Cost estimation before upload
|
||||
- Operation polling until indexing complete
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
ts-node upload-batch.ts --store "fileSearchStores/abc123" --directory "./docs" --concurrent 5
|
||||
```
|
||||
|
||||
### 🚧 query-store.ts (TO BE IMPLEMENTED)
|
||||
Interactive query tool with citation display.
|
||||
|
||||
**Planned Features:**
|
||||
- Interactive REPL for queries
|
||||
- Citation rendering with source links
|
||||
- Metadata filtering options
|
||||
- Model selection (Flash vs Pro)
|
||||
- Export query results
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
ts-node query-store.ts --store "fileSearchStores/abc123"
|
||||
```
|
||||
|
||||
### 🚧 cleanup.ts (TO BE IMPLEMENTED)
|
||||
Delete stores and documents (with safety prompts).
|
||||
|
||||
**Planned Features:**
|
||||
- List all stores with document counts
|
||||
- Delete specific store or all stores
|
||||
- Force delete confirmation prompts
|
||||
- Dry-run mode
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
ts-node cleanup.ts --store "fileSearchStores/abc123" --force
|
||||
ts-node cleanup.ts --all --dry-run
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
npm install @google/genai
|
||||
|
||||
# Set API key
|
||||
export GOOGLE_API_KEY="your-api-key-here"
|
||||
```
|
||||
|
||||
## Development Status
|
||||
|
||||
**Completed:** 1/4 scripts (25%)
|
||||
|
||||
**Next Steps:**
|
||||
1. Implement upload-batch.ts
|
||||
2. Implement query-store.ts
|
||||
3. Implement cleanup.ts
|
||||
4. Add package.json with dependencies and scripts
|
||||
5. Test all scripts end-to-end
|
||||
|
||||
## Notes
|
||||
|
||||
These scripts demonstrate best practices from SKILL.md:
|
||||
- Operation polling until done: true
|
||||
- Storage quota calculation (3x multiplier)
|
||||
- Recommended chunking configurations
|
||||
- Metadata schema patterns
|
||||
- Force delete for non-empty stores
|
||||
124
scripts/create-store.ts
Normal file
124
scripts/create-store.ts
Normal file
@@ -0,0 +1,124 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Create a new Google Gemini File Search Store
|
||||
*
|
||||
* Usage:
|
||||
* ts-node create-store.ts --name "My Knowledge Base" --project "customer-support"
|
||||
* node create-store.js --name "My Knowledge Base"
|
||||
*/
|
||||
|
||||
import { GoogleGenAI } from '@google/genai'
|
||||
|
||||
interface CreateStoreOptions {
|
||||
name: string
|
||||
project?: string
|
||||
environment?: string
|
||||
}
|
||||
|
||||
async function createFileSearchStore(options: CreateStoreOptions) {
|
||||
// Validate API key
|
||||
const apiKey = process.env.GOOGLE_API_KEY
|
||||
if (!apiKey) {
|
||||
console.error('❌ Error: GOOGLE_API_KEY environment variable is required')
|
||||
console.error(' Create an API key at: https://aistudio.google.com/apikey')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
// Initialize client
|
||||
console.log('Initializing Google Gemini client...')
|
||||
const ai = new GoogleGenAI({ apiKey })
|
||||
|
||||
try {
|
||||
// Check if store already exists
|
||||
console.log(`\nChecking for existing store: "${options.name}"...`)
|
||||
let existingStore = null
|
||||
let pageToken: string | null = null
|
||||
|
||||
do {
|
||||
const page = await ai.fileSearchStores.list({ pageToken: pageToken || undefined })
|
||||
existingStore = page.fileSearchStores?.find(
|
||||
s => s.displayName === options.name
|
||||
)
|
||||
pageToken = page.nextPageToken || null
|
||||
} while (!existingStore && pageToken)
|
||||
|
||||
if (existingStore) {
|
||||
console.log('⚠️ Store already exists:')
|
||||
console.log(` Name: ${existingStore.name}`)
|
||||
console.log(` Display Name: ${existingStore.displayName}`)
|
||||
console.log(` Created: ${existingStore.createTime}`)
|
||||
console.log('\n Use this store name for uploads and queries.')
|
||||
return
|
||||
}
|
||||
|
||||
// Create new store
|
||||
console.log('Creating new file search store...')
|
||||
const customMetadata: Record<string, string> = {}
|
||||
if (options.project) {
|
||||
customMetadata.project = options.project
|
||||
}
|
||||
if (options.environment) {
|
||||
customMetadata.environment = options.environment
|
||||
}
|
||||
|
||||
const fileStore = await ai.fileSearchStores.create({
|
||||
config: {
|
||||
displayName: options.name,
|
||||
...(Object.keys(customMetadata).length > 0 && { customMetadata })
|
||||
}
|
||||
})
|
||||
|
||||
console.log('\n✅ Store created successfully!')
|
||||
console.log(` Name: ${fileStore.name}`)
|
||||
console.log(` Display Name: ${fileStore.displayName}`)
|
||||
console.log(` Created: ${fileStore.createTime}`)
|
||||
console.log('\n Use this store name for uploads and queries:')
|
||||
console.log(` export FILE_SEARCH_STORE="${fileStore.name}"`)
|
||||
|
||||
} catch (error) {
|
||||
console.error('\n❌ Error creating store:', error)
|
||||
if (error instanceof Error) {
|
||||
console.error(` ${error.message}`)
|
||||
}
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// Parse command-line arguments
|
||||
function parseArgs(): CreateStoreOptions {
|
||||
const args = process.argv.slice(2)
|
||||
const options: Partial<CreateStoreOptions> = {}
|
||||
|
||||
for (let i = 0; i < args.length; i++) {
|
||||
if (args[i] === '--name' && args[i + 1]) {
|
||||
options.name = args[i + 1]
|
||||
i++
|
||||
} else if (args[i] === '--project' && args[i + 1]) {
|
||||
options.project = args[i + 1]
|
||||
i++
|
||||
} else if (args[i] === '--environment' && args[i + 1]) {
|
||||
options.environment = args[i + 1]
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
if (!options.name) {
|
||||
console.error('Usage: ts-node create-store.ts --name "Store Name" [--project "project"] [--environment "env"]')
|
||||
console.error('\nExample:')
|
||||
console.error(' ts-node create-store.ts --name "Customer Support KB" --project "support" --environment "production"')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
return options as CreateStoreOptions
|
||||
}
|
||||
|
||||
// Main execution
|
||||
if (require.main === module) {
|
||||
const options = parseArgs()
|
||||
createFileSearchStore(options).catch(error => {
|
||||
console.error('Unexpected error:', error)
|
||||
process.exit(1)
|
||||
})
|
||||
}
|
||||
|
||||
export { createFileSearchStore, CreateStoreOptions }
|
||||
Reference in New Issue
Block a user