feature/gemini-web-provider #1

Merged
daniel.w merged 16 commits from feature/gemini-web-provider into master 2026-04-02 18:36:51 +00:00
1 changed files with 61 additions and 24 deletions
Showing only changes of commit 104e55d613 - Show all commits

View File

@ -132,10 +132,15 @@ func (p *PlaywrightProvider) Generate(ctx context.Context, model string, message
}); err != nil { }); err != nil {
return fmt.Errorf("failed to navigate: %w", err) return fmt.Errorf("failed to navigate: %w", err)
} }
time.Sleep(2 * time.Second)
} }
// 3. 檢查登入狀態 // 3. 等待頁面完全載入project-golem 策略)
fmt.Println("[GeminiWeb] Waiting for page to be ready...")
if err := p.waitForPageReady(); err != nil {
fmt.Printf("[GeminiWeb] Warning: %v\n", err)
}
// 4. 檢查登入狀態
fmt.Println("[GeminiWeb] Checking login status...") fmt.Println("[GeminiWeb] Checking login status...")
loggedIn := p.isLoggedIn() loggedIn := p.isLoggedIn()
if !loggedIn { if !loggedIn {
@ -151,11 +156,6 @@ func (p *PlaywrightProvider) Generate(ctx context.Context, model string, message
fmt.Println("[GeminiWeb] Logged in") fmt.Println("[GeminiWeb] Logged in")
} }
// 4. 等待頁面就緒
if err := p.waitForReady(); err != nil {
fmt.Printf("[GeminiWeb] Warning: %v\n", err)
}
// 5. 建構提示詞 // 5. 建構提示詞
prompt := buildPromptFromMessagesPlaywright(messages) prompt := buildPromptFromMessagesPlaywright(messages)
fmt.Printf("[GeminiWeb] Typing prompt (%d chars)...\n", len(prompt)) fmt.Printf("[GeminiWeb] Typing prompt (%d chars)...\n", len(prompt))
@ -201,6 +201,58 @@ func (p *PlaywrightProvider) Close() error {
return nil return nil
} }
// waitForPageReady 等待頁面完全就緒project-golem 策略)
func (p *PlaywrightProvider) waitForPageReady() error {
fmt.Println("[GeminiWeb] Checking for ready state...")
// 1. 等待停止按鈕消失(如果存在)
_, _ = p.page.WaitForSelector("button[aria-label*='Stop'], button[aria-label*='停止']", playwright.PageWaitForSelectorOptions{
State: playwright.WaitForSelectorStateDetached,
Timeout: playwright.Float(5000),
})
// 2. 等待輸入框出現(關鍵!)
inputSelectors := []string{
".ProseMirror",
"rich-textarea",
"div[role='textbox']",
"div[contenteditable='true']",
"textarea",
}
var lastErr error
for _, sel := range inputSelectors {
fmt.Printf(" Checking for: %s\n", sel)
locator := p.page.Locator(sel)
if err := locator.WaitFor(playwright.LocatorWaitForOptions{
Timeout: playwright.Float(10000),
State: playwright.WaitForSelectorStateVisible,
}); err == nil {
fmt.Printf(" ✓ Input field found: %s\n", sel)
return nil
} else {
lastErr = err
}
}
// 3. 如果都找不到,給頁面更多時間
fmt.Println("[GeminiWeb] Input not found immediately, waiting longer...")
time.Sleep(3 * time.Second)
for _, sel := range inputSelectors {
locator := p.page.Locator(sel)
if err := locator.WaitFor(playwright.LocatorWaitForOptions{
Timeout: playwright.Float(5000),
State: playwright.WaitForSelectorStateVisible,
}); err == nil {
fmt.Printf(" ✓ Input field found after wait: %s\n", sel)
return nil
}
}
return fmt.Errorf("input field not ready: %w", lastErr)
}
// isLoggedIn 檢查是否已登入 // isLoggedIn 檢查是否已登入
func (p *PlaywrightProvider) isLoggedIn() bool { func (p *PlaywrightProvider) isLoggedIn() bool {
// 嘗試找輸入框(登入狀態的主要特徵) // 嘗試找輸入框(登入狀態的主要特徵)
@ -213,29 +265,14 @@ func (p *PlaywrightProvider) isLoggedIn() bool {
} }
for _, sel := range selectors { for _, sel := range selectors {
if _, err := p.page.WaitForSelector(sel, playwright.PageWaitForSelectorOptions{ locator := p.page.Locator(sel)
Timeout: playwright.Float(3000), if count, _ := locator.Count(); count > 0 {
}); err == nil {
return true return true
} }
} }
return false return false
} }
// waitForReady 等待頁面就緒
func (p *PlaywrightProvider) waitForReady() error {
fmt.Println("[GeminiWeb] Checking if page is ready...")
// 等待停止按鈕消失(如果存在)
_, _ = p.page.WaitForSelector("button[aria-label*='Stop']", playwright.PageWaitForSelectorOptions{
State: playwright.WaitForSelectorStateDetached,
Timeout: playwright.Float(5000),
})
fmt.Println("[GeminiWeb] Page is ready")
return nil
}
// typeInput 輸入文字(使用 Playwright 的 Auto-wait // typeInput 輸入文字(使用 Playwright 的 Auto-wait
func (p *PlaywrightProvider) typeInput(text string) error { func (p *PlaywrightProvider) typeInput(text string) error {
fmt.Println("[GeminiWeb] Looking for input field...") fmt.Println("[GeminiWeb] Looking for input field...")