- tmux som sanningskälla (agentoberoende, överlever omstart via adoption) - API: sessions, prompt, question/answer, keys, mode, config, shares, notify, events - frågedetektor testad mot riktiga agy 1.1.9-dumpar + mock - integrationstest: 26 tester i isolerad debian-container (scripts/run-integration.sh) - e2e-verifierad mot riktig agy (trust-fråga -> svar -> prompt) - .gitea/workflows/helmd-release.yaml -> rullande helmd-latest (x64+arm64) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
127 lines
4.9 KiB
Go
127 lines
4.9 KiB
Go
package main
|
|
|
|
import "testing"
|
|
|
|
// Real captures from a live agy 1.1.9 session (2026-08-05).
|
|
|
|
const agyApproval = ` python3 -c '
|
|
import json
|
|
with open("analys.ipynb", "r", encoding="utf-8") as f:
|
|
⋯ (10 lines hidden)
|
|
Do you want to proceed?
|
|
> 1. Yes
|
|
2. Yes, and always allow in this conversation for commands that start with 'python3 -c '
|
|
import json
|
|
with open("analys.ipynb", "r", encoding="utf-8") as f:...'
|
|
3. Yes, and always allow for commands that start with 'python3 -c '
|
|
import json
|
|
with open("analys.ipynb", "r", encoding="utf-8") as f:...' (Persist to settings.json)
|
|
4. No
|
|
↑/↓ Navigate · tab Amend · ctrl+g edit/expand command
|
|
esc to cancel Gemini 3.6 Flash · high`
|
|
|
|
const agyTrust = `Accessing workspace:
|
|
/tmp/scratch/gemini-arena
|
|
Do you trust the contents of this project?
|
|
Antigravity CLI requires permission to read, edit, and execute files here.
|
|
> Yes, I trust this folder
|
|
No, exit
|
|
↑/↓ Navigate · enter Confirm
|
|
Gemini 3.6 Flash · high`
|
|
|
|
const agyIdle = ` ▄▀▀▄ Antigravity CLI 1.1.9
|
|
▀▀▀▀▀▀ brasse.bb@gmail.com (Google AI Pro)
|
|
────────────────────────────────────────────────────────────
|
|
>
|
|
────────────────────────────────────────────────────────────
|
|
? for shortcuts Gemini 3.6 Flash · high`
|
|
|
|
// Agent output containing a markdown numbered list must NOT trigger.
|
|
const agyMarkdownList = ` Here are 5 targeted CLI tools:
|
|
1. ntfy: sends push notifications to your phone.
|
|
2. tea: manages Gitea repositories from the command line.
|
|
3. skopeo: inspects registry images.
|
|
────────────────────────────────────────────────────────────
|
|
>
|
|
────────────────────────────────────────────────────────────
|
|
? for shortcuts Gemini 3.6 Flash · high`
|
|
|
|
const geminiAuthPicker = ` ╭──────────────────────────────────────────────╮
|
|
│ ? Get started │
|
|
│ │
|
|
│ How would you like to authenticate? │
|
|
│ │
|
|
│ ● 1. Sign in with Google │
|
|
│ 2. Use Gemini API Key │
|
|
│ 3. Vertex AI │
|
|
│ │
|
|
│ (Use Enter to select) │
|
|
╰──────────────────────────────────────────────╯`
|
|
|
|
func TestApprovalPrompt(t *testing.T) {
|
|
q := DetectQuestion(agyApproval)
|
|
if q == nil {
|
|
t.Fatal("expected question, got nil")
|
|
}
|
|
if !q.Numbered || len(q.Options) != 4 {
|
|
t.Fatalf("want 4 numbered options, got %+v", q.Options)
|
|
}
|
|
if q.Options[0].Label != "Yes" || q.Options[3].Label != "No" {
|
|
t.Errorf("bad labels: %+v", q.Options)
|
|
}
|
|
if q.Selected != 0 {
|
|
t.Errorf("want selected=0, got %d", q.Selected)
|
|
}
|
|
if q.Text != "Do you want to proceed?" {
|
|
t.Errorf("bad text: %q", q.Text)
|
|
}
|
|
}
|
|
|
|
func TestTrustPrompt(t *testing.T) {
|
|
q := DetectQuestion(agyTrust)
|
|
if q == nil {
|
|
t.Fatal("expected question, got nil")
|
|
}
|
|
if q.Numbered || len(q.Options) != 2 {
|
|
t.Fatalf("want 2 unnumbered options, got %+v", q.Options)
|
|
}
|
|
if q.Selected != 0 {
|
|
t.Errorf("want selected=0, got %d", q.Selected)
|
|
}
|
|
if q.Options[1].Label != "No, exit" {
|
|
t.Errorf("bad option: %+v", q.Options[1])
|
|
}
|
|
}
|
|
|
|
func TestIdleScreenNoQuestion(t *testing.T) {
|
|
if q := DetectQuestion(agyIdle); q != nil {
|
|
t.Fatalf("idle screen misdetected as question: %+v", q)
|
|
}
|
|
}
|
|
|
|
func TestMarkdownListNoQuestion(t *testing.T) {
|
|
if q := DetectQuestion(agyMarkdownList); q != nil {
|
|
t.Fatalf("markdown list misdetected as question: %+v", q)
|
|
}
|
|
}
|
|
|
|
func TestBoxedNumberedPicker(t *testing.T) {
|
|
q := DetectQuestion(geminiAuthPicker)
|
|
if q == nil {
|
|
t.Fatal("expected question, got nil")
|
|
}
|
|
if len(q.Options) != 3 || !q.Numbered {
|
|
t.Fatalf("want 3 numbered options, got %+v", q.Options)
|
|
}
|
|
}
|
|
|
|
func TestSameQuestionSameHash(t *testing.T) {
|
|
a, b := DetectQuestion(agyApproval), DetectQuestion(agyApproval)
|
|
if a.Hash != b.Hash {
|
|
t.Error("hash not stable")
|
|
}
|
|
if DetectQuestion(agyTrust).Hash == a.Hash {
|
|
t.Error("different questions share hash")
|
|
}
|
|
}
|