Files
renamer/tests/contract/ai_ledger_contract_test.go
Rogee 3867736858 feat: implement AI-assisted rename prompting feature
- Added data model for AI-assisted renaming including structures for prompts, responses, and policies.
- Created implementation plan detailing the integration of Google Genkit into the CLI for renaming tasks.
- Developed quickstart guide for setting up and using the new AI rename functionality.
- Documented research decisions regarding Genkit orchestration and prompt composition.
- Established tasks for phased implementation, including setup, foundational work, and user stories.
- Implemented contract tests to ensure AI rename policies and ledger metadata are correctly applied.
- Developed integration tests for validating AI rename flows, including preview, apply, and undo functionalities.
- Added tooling to pin Genkit dependency for consistent builds.
2025-11-03 18:08:14 +08:00

109 lines
2.5 KiB
Go

package contract
import (
"bufio"
"context"
"encoding/json"
"os"
"path/filepath"
"testing"
"github.com/rogeecn/renamer/internal/ai/plan"
"github.com/rogeecn/renamer/internal/ai/prompt"
)
func TestAIApplyLedgerMetadataContract(t *testing.T) {
root := t.TempDir()
writeFile(t, filepath.Join(root, "sample.txt"))
candidate := plan.Candidate{
OriginalPath: "sample.txt",
SizeBytes: 4,
Depth: 0,
}
response := prompt.RenameResponse{
Items: []prompt.RenameItem{
{
Original: "sample.txt",
Proposed: "001_sample-final.txt",
Sequence: 1,
},
},
Model: "test-model",
PromptHash: "prompt-hash-123",
}
policy := prompt.NamingPolicyConfig{Prefix: "proj", Casing: "kebab"}
entry, err := plan.Apply(context.Background(), plan.ApplyOptions{
WorkingDir: root,
Candidates: []plan.Candidate{candidate},
Response: response,
Policies: policy,
PromptHash: response.PromptHash,
})
if err != nil {
t.Fatalf("apply: %v", err)
}
if len(entry.Operations) != 1 {
t.Fatalf("expected 1 operation, got %d", len(entry.Operations))
}
planFile := filepath.Join(root, "001_sample-final.txt")
if _, err := os.Stat(planFile); err != nil {
t.Fatalf("expected renamed file: %v", err)
}
ledgerPath := filepath.Join(root, ".renamer")
file, err := os.Open(ledgerPath)
if err != nil {
t.Fatalf("open ledger: %v", err)
}
defer file.Close()
scanner := bufio.NewScanner(file)
var lastLine string
for scanner.Scan() {
lastLine = scanner.Text()
}
if err := scanner.Err(); err != nil {
t.Fatalf("scan ledger: %v", err)
}
var recorded map[string]any
if err := json.Unmarshal([]byte(lastLine), &recorded); err != nil {
t.Fatalf("unmarshal ledger entry: %v", err)
}
metaRaw, ok := recorded["metadata"].(map[string]any)
if !ok {
t.Fatalf("expected metadata in ledger entry")
}
aiRaw, ok := metaRaw["ai"].(map[string]any)
if !ok {
t.Fatalf("expected ai metadata in ledger entry")
}
if aiRaw["model"] != "test-model" {
t.Fatalf("expected model test-model, got %v", aiRaw["model"])
}
if aiRaw["promptHash"] != "prompt-hash-123" {
t.Fatalf("expected prompt hash recorded, got %v", aiRaw["promptHash"])
}
if aiRaw["batchSize"].(float64) != 1 {
t.Fatalf("expected batch size 1, got %v", aiRaw["batchSize"])
}
}
func writeFile(t *testing.T, path string) {
t.Helper()
if err := os.MkdirAll(filepath.Dir(path), 0o755); err != nil {
t.Fatalf("mkdir %s: %v", path, err)
}
if err := os.WriteFile(path, []byte("data"), 0o644); err != nil {
t.Fatalf("write file %s: %v", path, err)
}
}