125 lines
3.9 KiB
Markdown
125 lines
3.9 KiB
Markdown
# Plan 04-02: Path and Model File Validation
|
|
|
|
**Wave:** 1
|
|
**Phase:** 4
|
|
**Requirements addressed:** MODL-02
|
|
|
|
---
|
|
|
|
## Objective
|
|
|
|
Add path existence validation and model file scanning integration so users receive immediate feedback when their selected model path or models directory is invalid.
|
|
|
|
---
|
|
|
|
## Read First
|
|
|
|
- `tauri-app/src-tauri/src/model_files.rs` — scan_models, pick_models_dir commands
|
|
- `tauri-app/src/features/runtime/api.ts` — invoke wrappers for Tauri commands
|
|
- `tauri-app/src/features/runtime/runtime-settings-form.ts` — RuntimeSettingsFormState, scanned models
|
|
- `tauri-app/src/features/runtime/types.ts` — RuntimeModelFile, RuntimePickDirResult
|
|
- `.planning/phases/04-model-source-validation/04-RESEARCH.md` — path validation patterns
|
|
|
|
---
|
|
|
|
## Action
|
|
|
|
1. **Add Tauri command wrappers** in `api.ts`:
|
|
|
|
```typescript
|
|
export interface ScannedModelsResult {
|
|
dir: string;
|
|
models: RuntimeModelFile[];
|
|
}
|
|
|
|
export async function scanModelsDir(dirPath: string): Promise<RuntimeModelFile[]> {
|
|
return await invoke<RuntimeModelFile[]>("scan_models", { dir: dirPath });
|
|
}
|
|
|
|
export async function pickModelsDirectory(): Promise<ScannedModelsResult> {
|
|
return await invoke<ScannedModelsResult>("pick_models_dir");
|
|
}
|
|
```
|
|
|
|
2. **Extend runtime-utils.ts with path validation**:
|
|
|
|
```typescript
|
|
import { scanModelsDir } from "./api";
|
|
|
|
export async function validateModelsDirectory(
|
|
path: string | null
|
|
): Promise<{ valid: boolean; modelCount: number; error: string | null }> {
|
|
if (!path) {
|
|
return { valid: false, modelCount: 0, error: "No models directory selected" };
|
|
}
|
|
try {
|
|
const models = await scanModelsDir(path);
|
|
return {
|
|
valid: true,
|
|
modelCount: models.length,
|
|
error: null
|
|
};
|
|
} catch (e) {
|
|
return {
|
|
valid: false,
|
|
modelCount: 0,
|
|
error: e instanceof Error ? e.message : String(e)
|
|
};
|
|
}
|
|
}
|
|
|
|
export async function validateModelFile(
|
|
path: string | null,
|
|
scannedModels: RuntimeModelFile[]
|
|
): Promise<{ valid: boolean; exists: boolean; error: string | null }> {
|
|
if (!path) {
|
|
return { valid: false, exists: false, error: "No model selected" };
|
|
}
|
|
const exists = scannedModels.some(m => m.path === path);
|
|
return {
|
|
valid: exists,
|
|
exists,
|
|
error: exists ? null : "Model file not found in current models directory"
|
|
};
|
|
}
|
|
```
|
|
|
|
3. **Add model scanning to runtime-settings-form.ts**:
|
|
|
|
- Add `scannedModels: RuntimeModelFile[]` to RuntimeSettingsFormState
|
|
- Add `scanModels(dir: string)` function that calls api.scanModelsDir
|
|
- Update `resolveDraftModelSelection` to use scanned models for validation
|
|
|
|
4. **Integrate into useRuntimeManager.ts**:
|
|
|
|
- Add `scannedModels` to draft state
|
|
- When `models_dir` field changes, trigger rescan
|
|
- When rescan completes, validate `model_path` against new scan results
|
|
- Update field validation state with path-specific errors
|
|
|
|
5. **Add validation display in UI components**:
|
|
|
|
- In runtime settings form, show validation message when models_dir is invalid
|
|
- Show "X models found" when scan succeeds
|
|
- Show "Model not in directory" when selected model is invalid after scan
|
|
|
|
---
|
|
|
|
## Acceptance Criteria
|
|
|
|
- [ ] `api.ts` exports `scanModelsDir(path)` and `pickModelsDirectory()`
|
|
- [ ] `runtime-utils.ts` exports async validators that check directory and file existence
|
|
- [ ] Changing `models_dir` triggers rescan and updates validation state
|
|
- [ ] Selected model is validated against scanned models list
|
|
- [ ] Invalid paths show clear error messages in the UI
|
|
- [ ] User can see "X models found" feedback after scanning
|
|
|
|
---
|
|
|
|
## Notes
|
|
|
|
- Reuse existing scan_models Rust command - no backend changes needed
|
|
- Keep validation async to support filesystem checks
|
|
- Show appropriate loading state during scan
|
|
- Handle scan errors gracefully (directory not found, permission denied)
|