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 props - 保持所有辅助功能(ARIA 角色、键盘导航)
- 保留样式和交互行为
- 通过移除内联邮件项渲染逻辑进行了简化
- 现在使用
MailListItem 组件,props 传递更整洁 - 降低了组件复杂度,提高了可读性
- ✅ 构建成功
- ✅ 所有功能工作正常(过滤、选择、导航)
- ✅ 保留了键盘辅助功能(回车键导航)
- ✅ 可视化选择状态工作正常
MailList.tsx 中的每一行提取为独立的 MailListItem 组件。保留选择状态、键盘导航以及现有的虚拟化行为。映射 MailList 布局
行当前是内联渲染的,选择状态保存在useSelection 中。react-window 外层元素包裹了列表,因此我将让其行渲染器指向新组件以保留虚拟化。
- 创建包含
message、selected和onSelect的MailListItem.tsx。 - 将其包裹在
React.memo中,并使用message.id+selected进行对比。 - 将
useSelection提升到MailList中并向下传递处理程序。
focus(),然后重新运行套件。MailListToolbar 组件,并为其添加一个 Storybook 故事。为你构建的智能体
将任务交给 AI 智能体,它们可以自主规划、进行代码变更、运行命令并迭代,直到工作完成。
例如,指派一个基于 CLI 的智能体在后台分类并修复错误,与另一个智能体交互以在集成浏览器中使用实时验证来实现功能,并将主页重新设计委托给云端智能体,该智能体可以打开一个供你的团队审查的拉取请求。
开始使用代理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 端点。支持并行处理最多 8 个文件,包含每请求预算、结构化日志和 OpenTelemetry 追踪。返回每项的结果。映射服务布局
现有的处理程序位于internal/http 中,处理器暴露了一个同步的 Extract。我将添加一个 ExtractCtx 变体,以便工作池可以处理取消操作,然后使用 errgroup + 加权信号量进行扇出。
internal/ 中 grep http.HandleFunc- 使用通用
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 等第三方提供商。
从不同提供商的数十种模型中进行选择,从快速补全模型到高级推理模型。或者携带你自己的密钥使用任何提供商的任何模型。
所有会话,一个视图
在多个智能体并行处理任务时保持高效。从单一视图跟踪所有智能体会话,无论它们运行在何处。
快速过滤和监控会话,或深入了解单个智能体交互,无需切换到其他工具或终端。
你的规则,你的智能体
确保智能体遵循你的实践和团队工作流程。定义自定义指令、添加智能体技能,或构建为你项目量身定制的自定义智能体。
使用 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()
使用扩展进行编码
使用扩展和模型上下文协议 (MCP) 服务器中的工具来扩展你的智能体。或者,构建你自己的扩展来赋能你团队的独特场景。
使用任何语言进行编码
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 为任何活动提供云端开发环境 —— 无论是长期项目,还是像审查拉取请求这样的短期任务。
通过丰富功能进行编码
编辑器远不止于此。无论是使用内置功能还是丰富的扩展,每个人都能找到适合自己的内容。