// Package contract is deliberately framework-free: production Wails wiring // must not change LineUp's envelope/state semantics. package contract import ( "encoding/json" "os" "path/filepath" "testing" ) type fixture struct { Contract string `json:"contract"` Cases []testCase `json:"cases"` } type testCase struct { ID string `json:"id"` Expected expected `json:"expected"` Envelopes []envelope `json:"envelopes"` Transitions []transition `json:"transitions"` } type expected struct { ItemKind string `json:"item_kind"` Fallback string `json:"fallback"` KernelToolStatus string `json:"kernel_tool_status"` } type transition struct { AfterEnvelope int `json:"after_envelope"` Kind string `json:"kind"` CallID string `json:"call_id"` } type envelope struct { Version int `json:"v"` Type string `json:"type"` Payload map[string]interface{} `json:"payload"` } func TestSharedLineUpV1GoldenContract(t *testing.T) { bytes, err := os.ReadFile(filepath.Join("..", "..", "tauri", "src", "runtime", "golden", "lineup-v1.json")) if err != nil { t.Fatalf("read shared fixture: %v", err) } var spec fixture if err := json.Unmarshal(bytes, &spec); err != nil { t.Fatalf("parse shared fixture: %v", err) } if spec.Contract != "lineup-v1-golden-1" || len(spec.Cases) != 6 { t.Fatalf("unexpected fixture declaration: %q (%d cases)", spec.Contract, len(spec.Cases)) } for _, c := range spec.Cases { t.Run(c.ID, func(t *testing.T) { toolStates := map[string]string{} kind, fallback := "", "" for index, wire := range c.Envelopes { kind, fallback = project(wire) if kind == "tool-call" { toolStates[stringValue(wire.Payload["call_id"])] = "pending" } for _, action := range c.Transitions { if action.AfterEnvelope == index && action.Kind == "submit_tool_call" && toolStates[action.CallID] == "pending" { toolStates[action.CallID] = "submitted" } } if kind == "tool-result" { callID := stringValue(wire.Payload["call_id"]) if toolStates[callID] == "submitted" { toolStates[callID] = stringValue(wire.Payload["status"]) } } } if kind != c.Expected.ItemKind || fallback != c.Expected.Fallback { t.Fatalf("got kind=%q fallback=%q; want kind=%q fallback=%q", kind, fallback, c.Expected.ItemKind, c.Expected.Fallback) } if c.Expected.KernelToolStatus != "" { ok := false for _, state := range toolStates { ok = ok || state == c.Expected.KernelToolStatus } if !ok { t.Fatalf("tool state never reached %q: %#v", c.Expected.KernelToolStatus, toolStates) } } }) } } func project(wire envelope) (kind, fallback string) { if wire.Version != 1 { return "fallback", "unsupported_version" } switch wire.Type { case "lineup.v1.tool.call": if stringValue(wire.Payload["call_id"]) == "" || stringValue(wire.Payload["tool"]) == "" { return "fallback", "invalid_payload" } return "tool-call", "" case "lineup.v1.tool.result": if stringValue(wire.Payload["call_id"]) == "" || stringValue(wire.Payload["status"]) == "" { return "fallback", "invalid_payload" } return "tool-result", "" case "lineup.v1.ui.open", "lineup.v1.ui.patch", "lineup.v1.ui.close": for _, forbidden := range []string{"bundle", "bundle_id", "bundle_url", "url", "html", "css", "javascript", "js", "script", "source"} { if _, exists := wire.Payload[forbidden]; exists { return "fallback", "invalid_payload" } } return "surface", "" case "lineup.v1.app.call": if stringValue(wire.Payload["call_id"]) == "" || stringValue(wire.Payload["capability"]) == "" || stringValue(wire.Payload["reason"]) == "" || stringValue(wire.Payload["expires_at"]) == "" { return "fallback", "invalid_payload" } if _, ok := wire.Payload["arguments"].(map[string]interface{}); !ok { return "fallback", "invalid_payload" } return "app-call", "" default: return "fallback", "unsupported_type" } } func stringValue(value interface{}) string { text, _ := value.(string) return text }