使用 Google Antigravity 进行构建

1. 简介

在此 Codelab 中,您将了解 Google Antigravity,这是一个旨在帮助您在智能体时代进行开发的智能体式开发平台。Antigravity 是 AI 智能体的中央指挥中心,提供统一的平台来启动、监控和编排其活动。

在此 Codelab 中,我们将使用 Antigravity 构建实际应用。我们将从简单的网页研究转向生成全栈应用和企业级单元测试。

前提条件:

  • 已安装并配置 Antigravity 和 Antigravity IDE。
  • 对 Google Antigravity 有基本的了解。建议您先完成 Codelab:Google Antigravity 使用入门。

2. 关于应用场景

既然您已对 Antigravity 有了基本的了解,不妨深入了解几个使用场景,看看它在实际应用中是如何发挥作用的。请注意,Antigravity 是一个以智能体为主的平台。这意味着,在大多数情况下,我们只是向代理发出指令,然后代理会自行完成任务,在需要时请求权限,生成制品,并在任务完成后通知我们。因此,我们无法在以下每个应用场景中生成代理对话的每个输出。我们将分享相关说明和一些必要的结果预期屏幕截图,但您的结果可能会略有不同。

我们将介绍的应用场景包括:自动执行与外部网站相关的一些任务、为项目生成和验证单元测试用例,以及完整的网站开发。出发吧。

3. 新闻集锦

这是一个简单的使用情形,但您可以基于此情形使用 Web 浏览器访问网站、提取信息、执行一些操作,然后将数据返回给用户。

在这种情况下,我们将访问 Google 新闻网站并从中提取一些信息。不过,您可以轻松选择一个网站进行实验,看看效果如何。

我们将假设有一个根文件夹,我们将在该文件夹下创建此 Codelab 中将要看到的各种项目。我们机器上的此根文件夹名为 agy2-pprojects。

首先,在上述文件夹中创建一个名为 news-highlights 的文件夹,以便从头开始。

启动 Antigravity 并创建一个新项目。将 news-highlights 文件夹添加到其中。

在新导入的 news-highlights 工作区中发起新对话:

58c4419125240f8f.png

然后,说出以下指令:“访问 news.google.com,获取当前的热点新闻。”

69859175cdace3c2.png

这会启动代理流程,并确定需要访问 news.google.com 网站并征求您的许可。系统可能会多次提示您读取网址,您可以选择授予其此项目的权限等。

85f14eddde22704c.png

您应密切关注“思考过程”,了解智能体如何完成任务。代理的执行示例如下所示:

7be51d200fb1296f.png

尝试以下任务

  • 了解这一点后,请选择一个可访问的网站,并指定您希望代理前往该网站获取/总结一些数据。考虑一些您知道包含信息中心和图表的网站,并让 Gemini 从中选择一些值。
  • 不妨试试以下提示:Visit https://docs.cloud.google.com/release-notes and get me a summary of the release notes, categorized by product.

4. 使用 Python + Flask 生成动态网站

现在,我们来生成一个完整的 Web 应用。我们将要创建的 Web 应用是一个网站,其中包含有关为期 1 天的技术活动的资讯,该活动全天都有多位演讲者进行演讲。

再次创建一个名为 conference-website 的新文件夹。确保您已在 Antigravity Agent 界面中创建新项目,并将 conference-website 文件夹添加到该项目中。

您可以先给出以下提示,开始对话:

I would like to generate a website that is a 1-day technical conference informational site.

The website should have the following functionality:
        1. A home page that shows the current date, location, schedule and time table.
        2. The 1-day event is a list of 8 talks in total.
        3. Each talk has 1 or 2 max. speakers. 
        4. A talk has an ID, Title, Speakers, Category (1 or 2), Description and time of the talk.
        5. Each speaker has a First Name, Last Name and LinkedIn url.
        6. Allow for users to search by category, speaker, title.
        7. Give a lunch break of 60 minutes.
        8. Use dummy data for events and speakers, come up with a schedule, the event is about Google Cloud Technologies.
        9. Tech Stack: Python and Flask framework on server side. Front-end is basic HTML, CSS and JavaScript. 
        10. Test out the site on your own for all functionality and provide a detailed README on how to setup, run and make any further changes. 
11. Launch the web application for me to review. 

Antigravity 会先分析请求,然后制定实施方案。它会创建一个名为 implementation_plan.md 的关键制品,供您查看它打算如何创建并满足您在提示中指定的要求。以下是输出示例:

8f516fd94f4ad57.png

在点击“继续”之前,请先查看实施方案。您可以点击上方的 implementation_plan.md 文件链接,也可以通过切换右上角的辅助窗格来打开该文件。这样一来,系统就会显示制品视图,您可以看到,实施计划目前已可供您查看。

e12b6e1270405137.png

下面显示了为我们的跑步活动生成的示例实施计划:

5069ec7ab1ae6310.png

您可以在方案中提供自己的意见,然后再次提示代理。或者,您也可以暂时接受实施方案,然后点击对话界面中的继续按钮继续操作。

代理会继续生成源代码文件,您还会注意到,它会更新另一个名为“任务”的制品。这是为实现最终结果而需要执行的操作或任务的列表。

您可以随时点击“任务”,甚至可以访问制品列表来查看任务。以下是房源信息的示例:

caf136694efc222f.png

在最后一项任务中,当 Antigravity 尝试运行并验证应用时,它会设置 Python 环境,并需要您授予权限才能设置环境、安装依赖项等。请根据需要授予权限。

验证成功后,系统会突出显示详细信息,并提供另一件制品“演练”,其中详细介绍了已完成的功能、技术堆栈、验证结果和说明。

d0f61eb85d348030.png

演练示例如下所示:

fb18995f34c286ae.png

当我们访问该网址时,最终网站如下所示:

2b2ee3149d59da7a.png

如果您想查看生成的代码,可以点击右上角的 Open IDE。系统将打开 Antigravity IDE,您可以使用该 IDE 查看生成的代码。示例屏幕截图如下所示:

12798431169dd8cf.png

尝试以下任务

  • 向应用添加您需要的其他功能。向代理提供详细信息,并注意它如何通过先修改任务列表,然后修改实施方案等方式来完成任务。
  • 向活动日程中添加其他数据。例如 Add two more talks to the schedule。
  • 让智能体为应用生成 README 或更多文档。

5. 生成简单的效率提升应用

现在,我们将生成一个简单的番茄工作法计时器 Web 应用。

创建 pomodoro-timer 文件夹确保您位于 Agent Manager 中,并且已导入并选择 pomodoro-timer 工作区。从以下提示开始:

Create a productivity app that features a Pomodoro timer. Give a calm and aesthetic look to the application.

请注意,它会先创建实施计划和任务列表,然后再执行这些任务。请继续关注此流程,在某些情况下,系统可能会提示您进行审核。

下面展示了包含导览消息和任务的运行示例:

df0db367ba475db2.png

最终的应用如下图所示,效果相当不错。

ef8ac58d0677e56.png

尝试以下任务

  • 向应用添加一些图片。例如,向应用添加一个计时器图片。
  • 尝试生成您想要的任何申请的几个变体。尝试不同的样式和图片,要求进行更改等。

6. 生成单元测试、模拟桩和验证测试

我们将在此处尝试的最后一个使用情形是,为我们拥有的特定代码文件生成单元测试,并让代理执行这些测试并验证它们。

为此,我们将创建一个包含单个 Python 文件的工作区,如下所示:

from typing import Dict

# --- Custom Exceptions ---
class InventoryShortageError(Exception):
    """Raised when there is not enough item stock."""
    pass

class PaymentFailedError(Exception):
    """Raised when the payment gateway rejects the transaction."""
    pass

class InvalidOrderError(Exception):
    """Raised when the order violates business rules."""
    pass

# --- External Service Interfaces (To be Mocked) ---
class InventoryService:
    def get_stock(self, product_id: str) -> int:
        """Connects to DB to check stock."""
        raise NotImplementedError("Real connection required")

    def decrement_stock(self, product_id: str, quantity: int):
        """Connects to DB to reduce stock."""
        raise NotImplementedError("Real connection required")

class PaymentGateway:
    def charge(self, amount: float, currency: str) -> bool:
        """Connects to Stripe/PayPal."""
        raise NotImplementedError("Real connection required")

# --- Main Business Logic ---
class Order:
    def __init__(self, 
                 inventory_service: InventoryService, 
                 payment_gateway: PaymentGateway,
                 customer_email: str,
                 is_vip: bool = False):
        
        self.inventory = inventory_service
        self.payment = payment_gateway
        self.customer_email = customer_email
        self.is_vip = is_vip
        self.items: Dict[str, Dict] = {} # {product_id: {'price': float, 'qty': int}}
        self.is_paid = False
        self.status = "DRAFT"

    def add_item(self, product_id: str, price: float, quantity: int = 1):
        """Adds items to the cart. Rejects invalid prices or quantities."""
        if price < 0:
            raise ValueError("Price cannot be negative")
        if quantity <= 0:
            raise ValueError("Quantity must be greater than zero")

        if product_id in self.items:
            self.items[product_id]['qty'] += quantity
        else:
            self.items[product_id] = {'price': price, 'qty': quantity}

    def remove_item(self, product_id: str):
        """Removes an item entirely from the cart."""
        if product_id in self.items:
            del self.items[product_id]

    @property
    def total_price(self) -> float:
        """Calculates raw total before discounts."""
        return sum(item['price'] * item['qty'] for item in self.items.values())

    def apply_discount(self) -> float:
        """
        Applies business logic:
        1. VIPs get flat 20% off.
        2. Regulars get 10% off if total > 100.
        3. No discount otherwise.
        """
        total = self.total_price
        
        if self.is_vip:
            return round(total * 0.8, 2)
        elif total > 100:
            return round(total * 0.9, 2)
        
        return round(total, 2)

    def checkout(self):
        """
        Orchestrates the checkout process:
        1. Validates cart is not empty.
        2. Checks stock for all items.
        3. Calculates final price.
        4. Charges payment.
        5. Updates inventory.
        """
        if not self.items:
            raise InvalidOrderError("Cannot checkout an empty cart")

        # 1. Check Inventory Logic
        for product_id, data in self.items.items():
            available_stock = self.inventory.get_stock(product_id)
            if available_stock < data['qty']:
                raise InventoryShortageError(f"Not enough stock for {product_id}")

        # 2. Calculate Final Price
        final_amount = self.apply_discount()

        # 3. Process Payment
        try:
            success = self.payment.charge(final_amount, "USD")
            if not success:
                raise PaymentFailedError("Transaction declined by gateway")
        except Exception as e:
            # Catching generic network errors from the gateway
            raise PaymentFailedError(f"Payment gateway error: {str(e)}")

        # 4. Decrement Stock (Only occurs if payment succeeded)
        for product_id, data in self.items.items():
            self.inventory.decrement_stock(product_id, data['qty'])

        self.is_paid = True
        self.status = "COMPLETED"
        
        return {"status": "success", "charged_amount": final_amount}

确保您已在本地的新文件夹中准备好上述 Python 文件 (order_service.py),并且已在 Antigravity 中打开该项目以进行对话。

这是一个简单的 Order 服务,在 checkout 函数中具有以下关键功能:

  1. 验证购物车是否不为空。
  2. 检查所有商品的库存。
  3. 计算最终价格。
  4. 扣款。
  5. 更新商品目录。

我们将为代理分配生成单元测试用例、提供模拟实现和执行测试的任务,以确保测试成功。

我们将打开特定的工作区文件夹,您会注意到,我们现在也可以使用 @ 符号来引用文件。例如,我们可以开始输入 @order,系统应该会显示 order_service.py 文件。

c4331bee03c5512c.png

我们可以布置一项任务,帮助我们了解此文件。输入以下提示:

Explain the @order_service.py file

系统会显示一些有关此文件的说明:

269ff8450d813970.png

我们可以通过提示让它生成更好的可视化图表:

Can you visually show this class for better understanding

Antigravity 会提及任务已完成,并已生成包含可视化的制品:

ea389f494786a9ad.png

我们可以查看可视化图表,如下所示:

70e6822a86f74de9.png

以及以下内容:

3ebd94221655a03f.png

下一步是生成单元测试,并让代理进行测试。我输入了以下提示:

generate unit tests for this module and test it out with mock implementations.

它完成了任务,生成了测试,运行了测试,还修复了一个 bug。以下是其输出:

788cd07aadd09a4b.png

它生成的文件之一也是测试文件。其屏幕截图如下所示:

7a79d27eb34f0530.png

尝试以下任务

使用您自己的代码,看看您可以让智能体执行哪些操作,从添加更多功能到重构部分代码,应有尽有。

7. 恭喜

恭喜!您已成功使用 Google Antigravity 完成以下操作:

  • 自主研究网络。
  • 构建和迭代全栈 Web 应用。
  • 使用模拟对象编写和验证复杂的单元测试。

现在,您可以让 Antigravity 替您完成项目中的繁重工作了。

参考文档