现已发布!阅读有关一月份的新功能和修复。

开源 AI 代码编辑器

下载 Visual Studio Code

使用 VS Code,即表示您同意其许可隐私声明

交互式英雄区域,展示 Visual Studio Code 界面,包含代理会话、示例选项卡和 Copilot 聊天;使用导航键探索编辑器内容。
代理会话
本地聊天代理 重构 MailList 组件结构 GitHub Copilot 云代理 将 MailListItem 提取到独立组件中 10 分钟 #1
+42 -24
GitHub Copilot CLI 代理 开始 CLI 代理会话
MailList.tsx MailListItem.tsx 提取 MailListItem 到独立组件
import { For, createSignal, createMemo } from "solid-js";
import { useNavigate, useParams } from "@tanstack/solid-router";
import { getEmailsForMailbox } from "~/data/emails";
import { MailListItem } from "~/components/MailListItem";

export function MailList() {
  const params = useParams({ strict: false }) as {
    mailbox?: string;
    id?: string;
  };
  const navigate = useNavigate();
  const [query, setQuery] = createSignal("");
  const mailbox = () => params.mailbox || "inbox";
  const list = createMemo(() => {
    const q = query().toLowerCase();
    return getEmailsForMailbox(mailbox()).filter(
      (e) =>
        !q ||
        e.subject.toLowerCase().includes(q) ||
        e.snippet.toLowerCase().includes(q)
    );
  });
  function open(id: string) {
    navigate({
      to: "/mail/$mailbox/$id",
      params: { mailbox: mailbox(), id },
      search: (prev) => prev,
    });
  }

  return (
    <For each={list()}>
      {(e) => (
        <div
          role="listitem"
          tabindex={0}
          onClick={() => open(e.id)}
          onKeyDown={(ev) => ev.key === "Enter" && open(e.id)}
          class="mail-item"
          data-selected={params.id === e.id ? "true" : undefined}
          aria-selected={params.id === e.id ? "true" : undefined}
        >
          <div>
            <div class="mail-item-subject truncate">{e.subject}</div>
            <div class="mail-item-snippet truncate">{e.snippet}</div>
          </div>
          <time
            class="text-xs muted"
            datetime={e.date}
            title={new Date(e.date).toLocaleString()}
          >
            {new Date(e.date).toLocaleDateString(undefined, {
              month: "short",
              day: "numeric",
            })}
          </time>
        </div>
        <MailListItem
          email={e}
          isSelected={params.id === e.id}
          onOpen={open}
        />
      )}
    </For>
  );
}
聊天
请更新 MailList 组件,将邮件列表项抽象到其自己的独立组件中 GitHub Copilot 云代理 委托给云代理 代理将异步处理,以创建包含您请求更改的拉取请求。请更新 MailList 组件,将单个邮件列表项抽象到其自己的组件中 kenzi.lawson avatar kenzi.lawson选择了“委托” GitHub Copilot 云代理 [WIP] 重构 MailList 以抽象邮件列表项 - Copilot 云代理已开始处理“请更新 Ma...”的工作,并在工作进展中更新此拉取请求。请更新 MailList 组件,将单个邮件列表项抽象到其自己的组件中 使用 VS Code 通过 GitHub Pull Request 扩展创建。✨ 让 Copilot 编码代理为您设置好一切——当为您的仓库设置好后,编码代理工作更快,质量更高。 GitHub Copilot 云代理已开始处理您的请求。请在相关聊天和拉取请求中跟进其进度。 MailList.tsx
描述接下来要构建的内容
代理 Claude Opus 4.5

为任何团队提供的任何模型

从多个开箱即用的模型中进行选择,或携带您自己的密钥以访问来自您首选模型和托管提供商的模型。

代理 GPT-5.2
自动 变量 GPT-5 mini 0x Claude Opus 4.5 3x Claude Sonnet 4.5 1x Gemini 3 Pro (预览) 1x GPT-5.1-Codex 1x GPT-5.1-Codex-Max 1x GPT-5.2 1x 管理模型...

您代码库的专家

您的代码库已在本地和远程建立索引,以便理解哪些内容相关,从而实现快速、上下文感知的交互。

main.rs
代码库中在哪里配置数据库连接字符串?
代理 Claude Sonnet 4.5

以团队工作方式工作的 AI

使用自定义代理、自定义指令和可重用提示文件来个性化交互,以适应您的工作流程和工具。

交互式的 VS Code 编辑器模型,选项卡中打开了提示文件;使用标准键盘导航来探索选项卡栏和编辑器内容。
Compact.chatmode.md AGENTS.md docs.instructions.md
---
                        description: 'Generate compact responses, focusing on brevity and clarity.'
                        tools: ['search', 'fetch', 'githubRepo', 'usages', 'vscodeAPI', 'problems', 'changes', 'testFailure', 'todos']
                        ---
                        You are a chat mode that provides extremely concise and clear responses. 
                        Your replies should be brief, to the point, and free of unnecessary details. 
                        Focus on delivering the essential information in a straightforward manner.
                        When responding, you must adhere to the following guidelines:
                        - Use short sentences and simple language.
                        - Prioritize clarity over completeness.
                        - Do not provide explanations or justifications unless explicitly asked.
                        - Do not provide any updates as you are working on the task –– only respond when the task is complete.
                        

在 VS Code 中免费使用 AI 功能

无需试用。无需信用卡。只需您的 GitHub 帐户。

免费试用

代理模式

处理复杂的、多步骤的任务。代理模式会读取您的代码库、建议跨文件的编辑、运行终端命令,并响应编译或测试失败——所有这些都在一个循环中,直到工作完成。通过 VS Code 扩展和模型上下文协议 (MCP) 服务器,进一步完善代理模式以适应您团队的工作流程。

使用代理模式构建
带有 VS Code 选项卡、侧边栏和聊天交互的交互式代理模式演练;使用标准键盘导航探索每个窗格。
batch.go processor.go image_processor_test.go health.go main.go
package http

import (
    "io"
    "log/slog"
    "mime/multipart"
    "net/http"
    "strings"
)

type BatchItemResult struct {
    Name string `json:"name"`
    Metadata *struct {
        Format string `json:"format"`
        Width  int    `json:"width"`
        Height int    `json:"height"`
        Bytes  int    `json:"bytes"`
    } `json:"metadata,omitempty"`
    Error string `json:"error,omitempty"`
}

type BatchResponse struct {
    Results []*BatchItemResult `json:"results"`
    Count   int                `json:"count"`
    Success int                `json:"success"`
    Failed  int                `json:"failed"`
}

// handleProcessBatch processes multiple uploaded images (multipart/form-data) under the field name "files".
// It returns metadata for each image or an error per item without failing the whole batch unless the request is malformed.
func (s *Server) handleProcessBatch(w http.ResponseWriter, r *http.Request) {
    // Enforce max body size overall.
    r.Body = http.MaxBytesReader(w, r.Body, s.cfg.MaxUploadBytes)
    if ct := r.Header.Get("Content-Type"); !strings.HasPrefix(ct, "multipart/form-data") {
        s.writeJSON(w, http.StatusBadRequest, map[string]string{"error": "content type must be multipart/form-data"})
        return
    }
    if err := r.ParseMultipartForm(s.cfg.MaxUploadBytes); err != nil {
        status := http.StatusBadRequest
        if strings.Contains(err.Error(), "request body too large") {
            status = http.StatusRequestEntityTooLarge
        }
        s.writeJSON(w, status, map[string]string{"error": "invalid multipart form: " + err.Error()})
        return
    }

    // Accept files under the key "files". If absent, attempt to fallback to any file parts.
    var fileHeaders []*multipart.FileHeader
    if r.MultipartForm != nil && len(r.MultipartForm.File["files"]) > 0 {
        fileHeaders = r.MultipartForm.File["files"]
    } else if r.MultipartForm != nil {
        // Fallback: gather all files across keys.
        for _, fhs := range r.MultipartForm.File {
            fileHeaders = append(fileHeaders, fhs...)
        }
    }

    if len(fileHeaders) == 0 {
        s.writeJSON(w, http.StatusBadRequest, map[string]string{"error": "no files provided (expect key 'files')"})
        return
    }

    resp := &BatchResponse{Results: make([]*BatchItemResult, 0, len(fileHeaders))}

    for _, fh := range fileHeaders {
        item := &BatchItemResult{Name: fh.Filename}
        f, err := fh.Open()
        if err != nil {
            item.Error = "open file: " + err.Error()
            resp.Results = append(resp.Results, item)
            resp.Failed++
            continue
        }
        data, err := io.ReadAll(f)
        _ = f.Close()
        if err != nil {
            item.Error = "read file: " + err.Error()
            resp.Results = append(resp.Results, item)
            resp.Failed++
            continue
        }
        meta, err := s.proc.ExtractMetadata(data)
        if err != nil {
            item.Error = err.Error()
            resp.Results = append(resp.Results, item)
            resp.Failed++
            continue
        }
        // Copy into anonymous struct to decouple from internal type if it changes.
        item.Metadata = &struct {
            Format string `json:"format"`
            Width  int    `json:"width"`
            Height int    `json:"height"`
            Bytes  int    `json:"bytes"`
        }{Format: meta.Format, Width: meta.Width, Height: meta.Height, Bytes: meta.Bytes}
        resp.Results = append(resp.Results, item)
        resp.Success++
    }

    resp.Count = len(resp.Results)
    s.log.LogAttrs(r.Context(), slog.LevelInfo, "batch processed", slog.Int("count", resp.Count), slog.Int("success", resp.Success), slog.Int("failed", resp.Failed))
    s.writeJSON(w, http.StatusOK, resp)
}
Copilot Claude Code - VSCode · AI 代码编辑器 Claude 代码 Codex - VSCode · AI 代码编辑器 Codex Cline - VSCode · AI 代码编辑器 Cline Gemini - VSCode · AI 代码编辑器 Gemini 聊天
我正在构建一个图像处理服务。你能创建一个新的端点来实现对批量图像处理的支持吗?
创建一个待办事项列表 我从创建待办事项列表开始,管理任务,例如读取现有服务器和处理器代码,设计批处理端点合约,并在一个新文件中实现一个带有处理程序的逻辑。我想将处理程序连接到服务器路由,也许为批处理端点添加一个最小的测试,尽管那是可选的。我也会计划稍后运行测试并构建所有内容。我们开始吧!
创建用于实现批量图像处理端点的结构化待办事项列表。 创建了 7 个待办事项 在添加批处理端点之前,读取核心文件以了解当前的服务器和图像处理实现。 读取server.go 读取processor.go 读取logging.go 读取health.go
改进文件处理... 我可能会修改 server.go,但他们要求一个新文件。因此,我需要创建一个路由,我们称之为 /process/batch。我将强制执行最大请求体大小,并确保内容类型是 multipart/form-data。接下来,我将解析表单并遍历 form.File["files"]。 对于每个 FileHeader,我将打开它并读取字节,然后调用 ExtractMetadata 来收集结果。最后,我将返回一个带有结果的结构化 JSON 响应,并处理无文件和最大批次限制的边缘情况。 我认为这可能不是绝对必要的,但我正在考虑通过使用 sync.WaitGroup 来顺序处理每个文件,同时限制并发性来做一些小的改进。这将使初始提交更简单。我需要添加代码文件并导入 internal/image 引用别名。 接下来,我将查看 tests/image_processor_test.go 中现有的测试以了解风格,并确定我是否应该为批处理处理程序创建一个新的测试文件。我将阅读该文件,然后更新待办事项状态,将任务一和二标记为已完成。
在添加批处理端点之前读取现有测试以模仿样式,然后将继续进行设计和实现。 读取image_processor_test.go
准备进行 HTTP 测试 我需要运行一个 HTTP 测试,但我注意到当前的测试包在 'tests' 中,而不是在主模块中。为了进行 HTTP 测试,我需要设置一些东西,比如 config、processor、logger 和 server,以及发送一个 multipart 请求。我的下一步是检查 config.go 中的配置,以了解我需要包含哪些必需的字段。让我们深入了解一下!
读取配置以在 HTTP 测试中构建服务器。 读取config.go
管理更新和补丁 我需要使用 manage_todo_list 来保持一切井井有条,确保我没有遗漏任何任务。完成后,我就可以应用补丁了。这涉及添加一个新文件并修改 server.go。我想确保在这个过程中一切都清晰准确,以避免任何错误。让我们继续前进!
开始 (3/7) 设计批处理合约
实施更新和测试 我将设计合约标记为完成,然后我需要实施更新。我将继续管理待办事项列表并应用补丁以添加一个文件并更新 server.go。看起来我可能需要在 server.go 中添加一个 POST /process/batch 的路由,并在 internal/http/batch.go 中实现一个新文件。编写代码后,我将添加一个测试文件,使用 go test 运行测试,并使用 run_in_terminal 命令。让我们开始吧!
完成 (3/7) 设计批处理合约 应用补丁以添加批处理处理程序、路由和测试。 server.go+1 -0 batch.go+106 -0 batch_endpoint_test.go+123 -0 实现了一个新的批处理图像处理端点 更改/添加的文件
  • server.go: 注册了新路由 POST /process/batch。
  • batch.go: 新的处理程序 handleProcessBatch
    • 接受 multipart/form-data。
    • 读取 files 键下的多个文件(如果 files 缺失,则回退到任何文件部分)。
    • 为每个文件返回成功/错误,而不会使整个批次失败。
    • 聚合计数:count、success、failed。
  • batch_endpoint_test.go: 测试正常路径(1 个有效 + 1 个无效文件)和缺少文件错误情况。
建议的后续步骤(可选)
  • 为每个批次添加可配置的最大文件数(例如,通过配置)。
  • 使用受限内存的流处理(process + discard)以处理非常大的图像。
  • 使用工作池和上下文取消的并行处理(可选)。
  • 在解码前添加每文件的尺寸验证。
  • 支持基于 JSON 的批处理(URL 或 base64),以支持非 multipart 客户端。
如果您需要任何这些增强功能或偏爱不同的请求/响应格式,请告诉我。
batch.go
描述接下来要构建的内容
代理 Gemini 3 Pro (预览)

下一个编辑建议

当您编码时,VS Code 会预测您的下一步操作。使用 Tab 键直接在编辑器中接受 AI 驱动的建议。它会根据您正在进行的编辑智能推荐要更改的内容——以及在哪里更改。

使用 AI 驱动的建议进行编码
main.py
import numpy as np
import pandas as pd

iris_data = pd.read_csv("iris_dataset.csv")

def describe(species: str) -> pd.Series:
7
subset = data[data["species"] == species]           subset = iris_data[iris_data["species"] == species] if subset.empty: raise ValueError(f"{species} missing from sample") return subset[["petal", "sepal"]].agg(["mean", "std"]).loc["mean"] def summary():
13
for species in np.sort(data["species"].unique()):      for species in np.sort(iris_data["species"].unique()): try: stats = describe(species) except ValueError: print(f"{species}: no records") continue print(f"{species}: petal={stats['petal']:.2f} sepal={stats['sepal']:.2f}") if __name__ == "__main__": summary()

用任何语言编码

VS Code 支持几乎所有主要的编程语言。一些语言(如 JavaScript、TypeScript、CSS 和 HTML)随附在编辑器中,但其他语言的扩展可以在 VS Code 市场中找到。

JavaScript iconJavaScript
TypeScript iconTypeScript
Python iconPython
C# iconC#
C++ iconC++
HTML iconHTML
Java iconJava
JSON iconJSON
PHP iconPHP
Markdown iconMarkdown
Powershell iconPowershell
YAML iconYAML

完全可定制

自定义您的 VS Code UI 和布局,使其适合您的编码风格。

颜色主题允许您根据自己的偏好和工作环境修改 VS Code 用户界面的颜色。

设置同步使您能够通过设置同步功能在您的 VS Code 实例之间共享您的用户设置。

配置文件允许您创建自定义设置集,并快速在它们之间切换或与他人共享。

Selecting the GitHub Dark theme with a quick pick Selecting the GitHub Dark theme with a quick pick

随时随地编写代码

无论您是连接到云、远程存储库,还是在浏览器中使用 VS Code for the Web (vscode.dev),都可以在最有效率的地方编写代码。

内置源代码管理开箱即用地为您提供 Git 支持。许多其他源代码管理提供商可通过扩展获得。

GitHub Codespaces 为任何活动提供云驱动的开发环境——无论是长期项目,还是像审查拉取请求这样的短期任务。

vscode.dev in an Edge browser tab vscode.dev in an Edge browser tab

通过丰富功能进行编码

编辑器还有更多内容。无论是使用内置功能还是丰富的扩展,总有适合每个人的东西。

© . This site is unofficial and not affiliated with Microsoft.