import {
For,
Show,
createMemo,
createSignal,
onCleanup,
onMount,
} from "solid-js";
import { useMail } from "./mail";
import { Item } from "./Item";
const ROW = 56;
const PAGE = 24;
export function MailList() {
const { items, query, load } =
useMail();
const [focus, setFocus] =
createSignal(0);
const [top, setTop] =
createSignal(0);
const visible = createMemo(() => {
const q = query().toLowerCase();
return items()
.filter((m) =>
m.subject
.toLowerCase()
.includes(q),
)
.slice(top(), top() + PAGE);
});
const onKey = (e: KeyboardEvent) => {
if (e.key === "ArrowDown") {
setFocus((i) =>
Math.min(i + 1, PAGE - 1),
);
} else if (e.key === "ArrowUp") {
setFocus((i) =>
Math.max(i - 1, 0),
);
} else if (e.key === "Enter") {
open(visible()[focus()].id);
}
};
onMount(() => {
load();
window.addEventListener(
"keydown",
onKey,
);
onCleanup(() =>
window.removeEventListener(
"keydown",
onKey,
),
);
});
return (
<Show
when={visible().length}
fallback={<Empty />}
>
<For each={visible()}>
{(m, i) => (
<Item
mail={m}
active={i() === focus()}
onOpen={open}
/>
)}
</For>
</Show>
);
}
import type { Email } from "~/types";
interface MailListItemProps {
email: Email;
isSelected: boolean;
onOpen: (id: string) => void;
}
export function MailListItem(props: MailListItemProps) {
return (
<div
role="listitem"
tabindex={0}
onClick={() => props.onOpen(props.email.id)}
onKeyDown={(ev) => ev.key === "Enter" && props.onOpen(props.email.id)}
class="mail-item"
data-selected={props.isSelected ? "true" : undefined}
aria-selected={props.isSelected ? "true" : undefined}
>
<div>
<div class="mail-item-subject truncate">{props.email.subject}</div>
<div class="mail-item-snippet truncate">{props.email.snippet}</div>
</div>
<time
class="text-xs muted"
datetime={props.email.date}
title={new Date(props.email.date).toLocaleString()}
>
{new Date(props.email.date).toLocaleDateString(undefined, {
month: "short",
day: "numeric",
})}
</time>
</div>
);
- 创建新的
MailListItem 组件,用于处理各个邮件列表项的渲染 - 从
MailList 中提取邮件项的 JSX 和逻辑到新MailListItem 组件中 - 更新
MailList 以使用新MailListItem 组件中 - 构建项目以验证更改是否能正确编译
- 测试应用程序以确保功能保持完好
- 创建了一个用于渲染各个邮件列表项的可复用组件
- 接受
email ,isSelected 和onSelect 属性 - 保留了所有无障碍功能(ARIA 角色、键盘导航)
- 保留了样式和交互行为
- 通过移除内联邮件项渲染逻辑进行了简化
- 现在使用
MailListItem 组件并进行清晰的属性传递 - 降低了组件复杂性并提高了可读性
- ✅ 构建成功
- ✅ 所有功能均正常运行(筛选、选择、导航)
- ✅ 保留了键盘无障碍功能(回车键导航)
- ✅ 视觉选择状态工作正常
MailList.tsx 中的每一行提取为独立的 MailListItem 组件。保留选择状态、键盘导航和现有的虚拟化行为。映射了 MailList 布局
目前各行是内联渲染的,且选择状态由useSelection 管理。react-window 外部元素包裹了列表,因此我将让其行渲染器指向新组件以保留虚拟化。
- 创建带有
message、selected和onSelect属性的MailListItem.tsx。 - 将其包裹在
React.memo中,并对message.id+selected使用比较器。 - 将
useSelection提升到MailList中并向下传递处理程序。
focus(),然后重新运行测试套件。MailListToolbar 组件中,并为其添加 Storybook 故事。为您构建的智能体
将任务交给能够自主规划、修改代码、运行命令并不断迭代直到工作完成的 AI 智能体。
例如,指派基于 CLI 的智能体在后台分类并修复 Bug,与另一个智能体交互以在集成浏览器中使用实时验证来实现功能,并将主页重新设计委派给云端智能体,由其打开拉取请求供您的团队审阅。
开始使用代理package http
import (
"context"
"encoding/json"
"errors"
"io"
"log/slog"
"mime/multipart"
"net/http"
"time"
"golang.org/x/sync/errgroup"
"golang.org/x/sync/semaphore"
"go.opentelemetry.io/otel"
)
type Result[T any] struct {
Name string `json:"name"`
Value T `json:"value,omitempty"`
Error string `json:"error,omitempty"`
}
type Meta struct {
Format string `json:"format"`
Width int `json:"width"`
Height int `json:"height"`
Bytes int64 `json:"bytes"`
}
const (
perRequestTimeout = 30 * time.Second
maxParallel = 8
)
func (s *Server) handleBatch(
w http.ResponseWriter,
r *http.Request,
) {
ctx, span := otel.Tracer("http").
Start(r.Context(), "batch")
defer span.End()
ctx, cancel := context.WithTimeout(
ctx, perRequestTimeout,
)
defer cancel()
r.Body = http.MaxBytesReader(
w, r.Body, s.cfg.MaxBytes,
)
if err := r.ParseMultipartForm(
s.cfg.MaxBytes,
); err != nil {
s.fail(w, http.StatusBadRequest, err)
return
}
files := pickFiles(r.MultipartForm)
if len(files) == 0 {
s.fail(w, http.StatusBadRequest,
errors.New("no files"))
return
}
out := make(
[]Result[Meta], len(files),
)
sem := semaphore.NewWeighted(maxParallel)
g, gctx := errgroup.WithContext(ctx)
for i, fh := range files {
i, fh := i, fh
if err := sem.Acquire(gctx, 1); err != nil {
break
}
g.Go(func() error {
defer sem.Release(1)
out[i] = process(gctx, s, fh)
return nil
})
}
_ = g.Wait()
s.log.LogAttrs(ctx,
slog.LevelInfo, "batch.done",
slog.Int("count", len(out)),
slog.Duration("budget",
perRequestTimeout),
)
w.Header().Set(
"Content-Type", "application/json",
)
_ = json.NewEncoder(w).Encode(out)
}
func process(
ctx context.Context,
s *Server,
fh *multipart.FileHeader,
) Result[Meta] {
res := Result[Meta]{Name: fh.Filename}
f, err := fh.Open()
if err != nil {
res.Error = err.Error()
return res
}
defer f.Close()
data, err := io.ReadAll(
io.LimitReader(f, s.cfg.MaxBytes),
)
if err != nil {
res.Error = err.Error()
return res
}
m, err := s.proc.ExtractCtx(ctx, data)
if err != nil {
res.Error = err.Error()
return res
}
res.Value = Meta{
Format: m.Format,
Width: m.Width,
Height: m.Height,
Bytes: int64(len(data)),
}
return res
}
POST /process/batch 端点。以每个请求的预算、结构化日志记录和 OpenTelemetry 跨度并行处理最多 8 个文件。返回逐项结果。映射了服务布局
现有处理程序位于internal/http 中,且处理器公开了一个同步的 Extract。我将添加一个 ExtractCtx 变体,以便工作线程池能够响应取消操作,然后通过 errgroup + 加权信号量进行扇出。
- 中使用泛型
Result[Meta]类型在batch.go中添加handleBatch。 - 使用
semaphore.NewWeighted(8)限制并发性,并将扇出包裹在errgroup中。 - 将请求包裹在 OTel 跨度和 30 秒上下文截止时间中。
- 在
server.go中连接路由并添加表测试。
go test ./internal/http -run Batch -race-race 检测无误。64 张图像批量处理(平均 1.2MB JPEG)的吞吐量端到端从 184ms 降至 31msk6 脚本。p99_ms Prometheus 直方图并将其连接到现有的 Grafana 仪表板中。任意智能体,任意模型
使用适合您工作流的智能体套件。通过 Copilot 或 Claude、OpenAI 等第三方提供商在本地或云端运行智能体。
从各大提供商的数十种模型中进行选择,从快速补全模型到高级推理模型。或者自带密钥以使用任何提供商的任何模型。
同一个 Copilot 适用于多个平台——VS Code、Copilot CLI、GitHub.com 和移动端。了解智能体如何在各个平台上工作。
所有会话,尽在单一视图
在多个智能体并行处理任务时保持高效。从单一视图跟踪所有智能体会话,无论它们在哪里运行。
快速筛选和监控会话,或深入了解单个智能体交互,无需切换到其他工具或终端。
您的规则,您的智能体
确保智能体遵循您的实践和团队工作流。定义自定义指令、添加智能体技能,或构建适合您项目的自定义智能体。
使用 MCP 服务器连接外部工具和服务,或安装智能体插件或扩展以扩展智能体的功能。
核心是世界一流的代码编辑器
十多年来,VS Code 一直是数百万开发者的首选编辑器。由 AI 驱动的内联建议、智能补全和丰富的编辑体验,让您在自己编写代码时同样功能强大。
在使用智能体和动手编码之间无缝切换,一切都在同一个编辑器中完成。
开始使用 VS Codeimport 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
TypeScript
Python
C#
C++
HTML
Java
JSON
PHP
Markdown
Powershell
YAML随时随地编码
无论您是连接到云端、远程仓库,还是通过网页版 VS Code (vscode.dev) 在浏览器中,都可以在最高效的地方进行编码。
内置源代码管理为您提供开箱即用的 Git 支持。通过扩展还可使用许多其他源代码管理提供商。
GitHub Codespaces 为任何活动提供基于云的开发环境——无论是长期项目,还是审查拉取请求等短期任务。
体验丰富的功能
编辑器的功能远不止于此。无论是使用内置功能还是丰富的扩展,总有一款适合您。