从 Bun 到 DeepSeek:用 TypeScript 构建你的第一个 AI Agent

从 Bun 到 DeepSeek:用 TypeScript 构建你的第一个 AI Agent

🚀 AI Agent 时代已来,作为前端/全端开发者,你准备好入场了吗?本文带你从零搭建 Bun + TypeScript 环境,一步步调通 DeepSeek 大模型接口,构建属于你的第一个 AI Agent。

前言

2026 年,AI Agent 成为最火热的技术方向之一。无论是 Claude Code、Cursor 还是各种自主 Agent 框架,底层都离不开一个高性能的运行时。

Bun,这个被 Claude Code 选为底层运行时的 JS/TS 引擎,正在成为 AI Agent 开发的标配。

本文适合有一定 JS/TS 基础的开发者,你将学到:

  • 为什么 AI Agent 选择 Bun + TypeScript?
  • 如何用 Bun 调用 DeepSeek 大模型?
  • 如何从单次调用进化到多轮对话 + 流式输出 + Tool Calling?

一、为什么 AI Agent 选择 Bun + TypeScript?

1.1 Bun 是什么?

一句话:Bun 是比 Node.js 更快、开箱即用、零配置的 JS/TS 运行时 + 包管理器。

特性 Node.js Bun
启动速度 较慢 ⚡ 极快
TypeScript 支持 需要编译 ts → js ✅ 原生支持,零配置
包管理器 npm / pnpm 内置 bun install,快 10-100 倍
内置 fetch 需要 node-fetch ✅ 原生支持
环境变量 需要 dotenv ✅ 原生 --env-file

1.2 为什么 Claude Code 选择 Bun?

Claude Code 的底层运行时就是 Bun。 当你使用 Claude Code 写代码、跑测试时,背后就是 Bun 在驱动。

原因很明确:

  1. 启动快 --- Agent 需要频繁启停进程,启动速度至关重要
  2. 原生 TS --- AI Agent 项目几乎都用 TypeScript,零配置直接跑
  3. 轻量级 --- 资源占用少,适合大规模部署

1.3 为什么 AI Agent 必须用 TypeScript?

AI Agent 涉及大量数据结构(消息列表、工具调用、API 响应),JavaScript 的弱类型会让 bug 藏在系统里很久:

html 复制代码
<!-- 浏览器 input 输入框,你以为输入的是数字?其实是字符串! -->
<input type="text" id="ipt">
<script>
    const ipt = document.getElementById('ipt');
    ipt.addEventListener('change', function(event) {
       console.log(event.target.value, typeof event.target.value);
       // "123" + 1 = "1231"  而不是 124
    });
</script>

TypeScript 的静态类型检查,让你在编码阶段就能发现 80% 的错误:

typescript 复制代码
function add(a: number, b: number): number {
    return a + b;
}
add(1, "2"); // ❌ 编译报错!类型不匹配
add(1, Number("2")); // ✅ 显式类型转换

这就是为什么几乎所有主流 AI Agent 框架都选择 TypeScript。


二、环境搭建

bash 复制代码
# 安装 Bun(Windows)
powershell -c "irm bun.sh/install/windows | iex"

# 或者通过 npm/pnpm 安装
npm i -g bun
pnpm i -g bun

# 初始化项目
bun init

项目结构:

bash 复制代码
my-ai-agent/
├── .env                # 环境变量(API Key)
├── .gitignore          # 忽略 .env 和 node_modules
├── package.json
├── tsconfig.json
├── src/
│   ├── index.ts        # 入口文件
│   ├── chat.ts         # 对话逻辑
│   ├── tools/          # 工具定义
│   │   └── weather.ts
│   └── types.ts        # 类型定义
└── bun.lock

环境变量配置:

env 复制代码
# .env
DEEPSEEK_BASE_URL=https://api.deepseek.com/chat/completions
DEEPSEEK_API_KEY=sk-xxxxxxxxxxxxx

⚠️ 模型名变更提醒deepseek-chatdeepseek-reasoner 将于 2026/07/24 弃用,统一合并为 deepseek-v4-flash(通过非思考/思考模式区分)。本文已使用新模型名。

同时确保 .gitignore 中包含 .env,防止密钥泄露。

💡 Bun 小技巧 :Bun 原生支持 --env-file 参数,无需安装 dotenv:

bash 复制代码
bun run --env-file=.env index.ts

三、异步编程速览

AI Agent 的核心是异步 --- 发送请求、等待响应、处理流式数据,全部是异步操作。

Promise 三种状态

状态 含义 触发方式
pending 进行中 初始状态
fulfilled 已成功 调用 resolve(value)
rejected 已失败 调用 reject(error)

async/await:让异步代码像同步一样

javascript 复制代码
function sleep(t) {
    return new Promise((resolve) => setTimeout(resolve, t));
}

async function main() {
    console.log('--start--');
    await sleep(2000); // 暂停 2 秒,等待 Promise 完成
    console.log('--end--');
}
main();

await暂停当前 async 函数的执行,等 Promise 完成后拿到结果继续往下走。

Promise.all:并行执行多个异步任务

AI Agent 经常需要同时调用多个 Tool,用 Promise.all 可以并行执行:

javascript 复制代码
// ❌ 串行 --- 总耗时 = 2s + 3s = 5s
const weather = await getWeather('北京');
const news = await getNews('科技');

// ✅ 并行 --- 总耗时 = max(2s, 3s) = 3s
const [weather, news] = await Promise.all([
    getWeather('北京'),
    getNews('科技')
]);

💡 实战场景 :当 Agent 需要同时调用多个 Tool(查天气 + 查日程 + 搜索),Promise.all 能显著减少等待时间。


四、实战:调用 DeepSeek 大模型

4.1 方式一:Bun 内置 fetch(零依赖,推荐)

typescript 复制代码
// fetch-demo.ts
// 运行:bun run --env-file=.env fetch-demo.ts

async function chat() {
    try {
        // 1. 环境变量校验
        const baseUrl = process.env.DEEPSEEK_BASE_URL;
        const apiKey = process.env.DEEPSEEK_API_KEY;
        if (!baseUrl || !apiKey) {
            throw new Error('请检查 .env 文件中的 DEEPSEEK_BASE_URL 和 DEEPSEEK_API_KEY');
        }

        // 2. 超时控制:30 秒无响应自动取消
        const controller = new AbortController();
        const timeout = setTimeout(() => controller.abort(), 30000);

        const res = await fetch(baseUrl, {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `Bearer ${apiKey}`
            },
            body: JSON.stringify({
                model: 'deepseek-v4-flash',
                messages: [{
                    role: 'user',
                    content: '你好,介绍一下Bun'
                }]
            }),
            signal: controller.signal
        });

        clearTimeout(timeout);

        // 3. 检查 HTTP 状态码
        if (!res.ok) {
            throw new Error(`HTTP ${res.status}: ${await res.text()}`);
        }

        // 4. 防御性取值
        const data = await res.json();
        const content = data?.choices?.[0]?.message?.content;
        if (!content) {
            console.error('响应格式异常:', JSON.stringify(data, null, 2));
            return;
        }
        console.log(content);
    } catch (err: any) {
        if (err.name === 'AbortError') {
            console.error('请求超时,请检查网络或稍后重试');
        } else {
            console.error('请求失败:', err.message);
        }
    }
}

chat();

为什么推荐 fetch? 零依赖、更轻量、符合 Web 标准。

4.2 方式二:Axios(企业级方案)

如果你需要拦截器、自动重试、请求取消等高级功能,Axios 是更好的选择:

typescript 复制代码
// index.ts
import axios from "axios";
import dotenv from "dotenv";
dotenv.config();

async function chat() {
    try {
        const baseUrl = process.env.DEEPSEEK_BASE_URL;
        const apiKey = process.env.DEEPSEEK_API_KEY;
        if (!baseUrl || !apiKey) {
            throw new Error('请检查 .env 文件中的 DEEPSEEK_BASE_URL 和 DEEPSEEK_API_KEY');
        }

        const res = await axios.post(
            baseUrl,
            {
                model: 'deepseek-v4-flash',
                messages: [{
                    role: 'user',
                    content: '你好,介绍一下Bun'
                }]
            },
            {
                headers: {
                    'Content-Type': 'application/json',
                    'Authorization': `Bearer ${apiKey}`
                },
                timeout: 30000
            }
        );

        const content = res.data?.choices?.[0]?.message?.content;
        if (!content) {
            console.error('响应格式异常:', JSON.stringify(res.data, null, 2));
            return;
        }
        console.log(content);
    } catch (err: any) {
        if (err.response) {
            console.error(`HTTP ${err.response.status}:`, err.response.data);
        } else {
            console.error('请求失败:', err.message);
        }
    }
}
chat();
bash 复制代码
bun run index.ts

五、从"能调用"到"会对话":三个进阶能力

单次 API 调用只是起点,真正的 AI Agent 需要以下三个能力:

5.1 多轮对话:维护消息列表

AI 模型是无状态的,每次请求都需要带上完整的历史消息:

typescript 复制代码
const messages: Array<{role: string; content: string}> = [
    { role: 'system', content: '你是一个友好的AI助手' },
    { role: 'user', content: '你好!' },
    // 模型回复后,把回复也加入 messages
    // { role: 'assistant', content: '你好!有什么可以帮你的?' },
    // { role: 'user', content: '介绍一下Bun' },
];

每次用户发消息,把新消息追加到 messages 数组,然后把整个数组发给模型。这就是多轮对话的秘密。

5.2 流式输出(SSE)

大模型生成回复需要时间,如果等全部生成完再显示,用户体验很差。流式输出让模型边生成边输出:

typescript 复制代码
const res = await fetch(url, {
    method: 'POST',
    headers: { /* ... */ },
    body: JSON.stringify({
        model: 'deepseek-v4-flash',
        messages: messages,
        stream: true // 开启流式输出
    })
});

// 逐块读取响应
const reader = res.body?.getReader();
const decoder = new TextDecoder();
while (true) {
    const { done, value } = await reader!.read();
    if (done) break;
    const chunk = decoder.decode(value);
    const lines = chunk.split('\n').filter(line => line.startsWith('data: '));
    for (const line of lines) {
        const data = line.replace('data: ', '');
        if (data === '[DONE]') break;
        const parsed = JSON.parse(data);
        process.stdout.write(parsed.choices[0]?.delta?.content || '');
    }
}

5.3 Tool Calling:让 AI 具备"动手能力"

真正的 AI Agent 不只是聊天,它能调用工具

typescript 复制代码
const tools = [{
    type: 'function',
    function: {
        name: 'get_weather',
        description: '获取指定城市的天气',
        parameters: {
            type: 'object',
            properties: {
                city: { type: 'string', description: '城市名称' }
            }
        }
    }
}];

这就是 AI Agent 的核心循环:

复制代码
用户输入 → 模型理解意图 → 选择工具 → 执行工具 → 将结果反馈给模型 → 继续推理

六、总结

知识点 作用
Bun 高性能运行时,AI Agent 的底层引擎
TypeScript 类型约束,减少 80% 的运行时错误
async/await 异步编程基石,处理网络请求
fetch / axios 调用 LLM API 的两种方式
消息列表 多轮对话的核心数据结构
流式输出 提升用户体验的关键技术
Tool Calling 从"聊天机器人"进化为"AI Agent"

Bun + TypeScript 正在成为 AI Agent 开发的黄金组合。Claude Code 选择 Bun 作为底层运行时,已经证明了这条技术路线的正确性。

现在就开始你的第一个 AI Agent 吧!🎯


七、学习资源

🔧 运行时 & 工具

🤖 AI & LLM

📚 AI Agent 开发

📖 推荐阅读


📌 本文代码仓库gitee.com/zhou-wenqia...

觉得有帮助的话,点个赞 👍 收藏 ⭐ 支持一下!

相关推荐
贵慜_Derek1 小时前
《从零实现 Agent 系统》连载 23|Skill 体系与 Skill Creator:能力打包与迭代
人工智能·设计模式·架构
ting94520001 小时前
SocialEcho 2.0 全维度技术深度剖析:基于官方 API 的 AI 社交协作平台底层架构、引擎原理与工程落地详解
人工智能·架构
lie..1 小时前
基于大模型的智能客服系统部署与使用(二):接入前端可视化界面
人工智能·python
tedcloud1231 小时前
Understand-Anything部署教程:打造AI代码理解平台
服务器·人工智能·学习·自动化·powerpoint
醒醒该学习了!1 小时前
人工智能伦理与职业操守(理论篇)
人工智能
五号厂房1 小时前
🔥 Claude Code 源码解析(三):揭秘工具系统的精妙设计
人工智能
程序员佳佳1 小时前
我在 Windows 和低配 Linux 上做 RAG:Milvus、FAISS、向量 API 中转的中立实测
linux·人工智能·windows·gpt·aigc·milvus·faiss
AI原来如此1 小时前
Claude与ChatGPT激战正酣,国内AI中转站却突破2000家
人工智能·ai·chatgpt·大模型·编程
天丁o1 小时前
企业 AI Agent 工程化落地:从需求边界到系统集成的 6 个环节
数据库·人工智能