# tju-code-agent **Repository Path**: e4glet/tju-code-agent ## Basic Information - **Project Name**: tju-code-agent - **Description**: cli端编程智能体工具 - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-09 - **Last Updated**: 2026-08-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Tju code 编程智能体工具 由天津大学系统安全与可信计算研究中心内部自研的 coding agent 工具,参考借鉴开源工具 `pi` 的架构与执行质量设计,目标是:省 token、高缓存命中率、可靠的工具调用。 ![alt text](image-1.png) ![alt text](image-2.png) ## 三轮编程对话测试缓存命中率为97.57% ## 特性 - 双层 agent 循环(外层 turn 循环 + 内层 provider 流式读取),天然适配流式 UI。 - 统一 AI 层:OpenAI 兼容(chat/completions)与 Anthropic Messages,SSE 流式解析。 - 内建工具集:`read` / `bash` / `edit` / `write` / `grep` / `fetch` / `scan`,参数用 zod schema 校验。 - 可靠执行:工具参数 JSON 非法或输出被截断的 tool call 一律不执行并要求重发;write 原子写、read 行数截断、edit 失败附带上下文、Windows bash 进程树清理、fetch 限流/截断/超时/中止。 - 联网查询体验:`fetch` 联网时 CLI/GUI 显示【正在联网查询中】与完成状态,不直接回显网页原始 HTML;抓取内容交由 AI 提取关键信息后以摘要/回答形式呈现给用户。 - 内建安全扫描:`scan` 工具做密钥泄露检查(API key / token / 私钥等常见模式)与依赖漏洞检查(`npm audit` 联网查,离线降级内置高危名单);write/edit 后自动追加安全提示,把检查"左移"到编码阶段。 - 高可用:provider 瞬时错误(429/5xx/网络)指数退避自动重试;任一 hook 抛错不打断整轮。 - 上下文与缓存:`transformContext` 接入 `compressTranscript`,超 128K token 自动压缩(保守裁剪 + 丢旧轮),预算内不动前缀以保持缓存命中;usage 记录缓存读/写,`/status` 展示命中率。 - 端点穿插 hooks:`transformContext`(上下文压缩/截断/注入的入口)、`beforeToolCall` / `afterToolCall`、`getSteeringMessages` / `getFollowUpMessages`。 - 两种界面: - CLI `chat`:终端交互会话。 - GUI `gui`:本地 HTTP + SSE 服务器 + 浏览器界面(默认 `http://localhost:9399`),内置「对话 / 轨迹」双页签,轨迹页签可视化每次 run 的工具调用与耗时(见下文「GUI 轨迹功能」)。 ## 快速开始 要求:Node >= 20。 推荐: - Node 20-22 之间。 ### 初始化环境依赖 ```bash npm install ``` ### 界面 - `chat`:终端交互会话(默认命令)。 - `gui`:浏览器界面,默认打开 `http://localhost:9399`(`--no-open` 可禁止自动打开浏览器,`--port` 改端口)。 > 安全说明:GUI 服务绑定本机 127.0.0.1。启动时会生成一个随机会话 token 注入前端页面,所有 `/api/*` 请求需携带该 token(浏览器自动带),并校验同源 Origin,跨站网页无法伪造请求(防 CSRF / 本地 RCE)。token 会打印在启动日志中,供非浏览器客户端调用 API 时使用。 ## 操作说明 ### 方式一:用内置厂商预设(推荐) 预设已配好接口地址与默认模型,只要设置对应的 API key: | 预设 | 接口地址 | 默认模型 | API key 环境变量 | | --- | --- | --- | --- | | `deepseek` | https://api.deepseek.com | `deepseek-v4-flash` | `DEEPSEEK_API_KEY` | | `kimi` | https://api.moonshot.cn/v1 | `moonshot-v1-8k` | `MOONSHOT_API_KEY` | | `qwen` | https://dashscope.aliyuncs.com/compatible-mode/v1 | `qwen-max` | `DASHSCOPE_API_KEY` | | `glm` | https://open.bigmodel.cn/api/paas/v4 | `glm-4-plus` | `ZHIPU_API_KEY` | | `amd` | https://developer.amd.com.cn/radeon/api/v1 | `DeepSeek-V4-Flash` | `AI_API_KEY` | AMD Cloud 还可通过 `AI_API_URL` 覆盖接口地址、`AI_MODEL` 覆盖模型名。 推荐使用`deepseek v4 flash 0731`。 Windows PowerShell: ```powershell $env:DEEPSEEK_API_KEY = "sk-你的key" npm run dev:gui -- --profile deepseek # 浏览器界面 npm run dev -- --profile deepseek # 终端聊天 ``` bash: ```bash export DEEPSEEK_API_KEY=sk-你的key npm run dev:gui -- --profile deepseek ``` AMD Cloud 示例: ```powershell $env:AI_API_KEY = "你的key" npm run dev:gui -- --profile amd ``` ```bash export AI_API_KEY=你的key npm run dev -- --profile amd ``` 预设的参数都可单独覆盖,例如换更强的模型: ```bash npm run dev -- --profile deepseek --model deepseek-v4-pro ``` ### 方式二:手动指定(任意 OpenAI 兼容接口) `--api-key` / `--base-url` / `--model` 三件套直接给: ```powershell npm run dev:gui -- --api-key sk-你的key --base-url https://api.deepseek.com --model deepseek-v4-flash ``` 注意:`--base-url` 需要与 OpenAI 兼容格式匹配,程序会拼上 `/chat/completions`(如 DeepSeek 传 `https://api.deepseek.com`,Moonshot 传 `https://api.moonshot.cn/v1`)。Anthropic 接口切 `--api anthropic-messages`,走 `/v1/messages`。 #### 预设 + 自定义接口(中转站 / 私有部署) 保留厂商预设的其它默认,只替换接口地址、模型名、key: ```powershell npm run dev -- ` --profile deepseek ` --base-url https://你的网关地址 ` --model 你的模型名 ` --api-key sk-你的key ``` 同名 flag 优先于环境变量。也可以只用环境变量覆盖预设(切换 base-url 之后需重启进程才生效): | 预设 | API key | 可覆盖的 base-url 环境变量 | 模型名覆盖 | | --- | --- | --- | --- | | `deepseek` | `DEEPSEEK_API_KEY` | `DEEPSEEK_BASE_URL` | 仅 `--model` | | `kimi` | `MOONSHOT_API_KEY` | `MOONSHOT_BASE_URL` | 仅 `--model` | | `qwen` | `DASHSCOPE_API_KEY` | `DASHSCOPE_BASE_URL` | 仅 `--model` | | `glm` | `ZHIPU_API_KEY` | `ZHIPU_BASE_URL` | 仅 `--model` | | `amd` | `AI_API_KEY` | `AI_API_URL` | `AI_MODEL` | 其中:AMD 支持全环境变量覆盖(接口/模型/key),其余预设的模型名只能通过 `--model` 修改。 ### 方式三:环境变量 OpenAI 兼容接口用 `OPENAI_API_KEY` / `OPENAI_BASE_URL`,Anthropic 用 `ANTHROPIC_API_KEY` / `ANTHROPIC_BASE_URL`;厂商预设还有各自的 `<厂商>_API_KEY`(见上表)。 ### 目录访问权限 工具(read / write / edit / grep / bash)首次访问**工作目录之外**的目录时,会向你确认授权,允许后该目录及子目录在当前会话内不再询问;拒绝则本次操作被阻止(模型会收到"未授权"的提示)。`fetch` 是纯网络工具,不读本地文件系统,不受目录权限限制。 - CLI:终端里输入 `y` 允许、`n` 拒绝。 - GUI:页面弹出"允许 / 拒绝"按钮。 - 工作目录内的读写不受影响,无需确认。 ### 联网安全(fetch 的 SSRF 防护) `fetch` 默认**拒绝访问非公网地址**(环回 `127.0.0.1`/`::1`、链路本地与云元数据 `169.254.x.x`、RFC1918 内网 `10/8` `172.16/12` `192.168/16`、CGNAT、多播等),解析域名后按解析出的 IP 逐一校验,防止模型被网页内容诱导去探测本机、内网或云元数据接口(如 `169.254.169.254`)。确需访问本地或内网服务时,在调用参数里显式传 `allowPrivate: true` 放行。 ### 安全扫描 内建 `scan` 工具把安全检查"左移"到编码阶段:写代码时模型可主动调用,发现风险会在提交前被标记出来。 - **密钥扫描**:正则匹配常见敏感信息(OpenAI/Anthropic key、AWS Access Key、GitHub token、Slack token、Google API key、Stripe key、JWT、PEM 私钥、`api_key`/`secret`/`token`/`password` 赋值等),报告 `文件:行号` 与命中的类别。自动跳过 `node_modules` / `.git` / `dist` 等目录。 - **依赖漏洞检查**:调用 `npm audit --json` 联网查询依赖漏洞;离线或 npm 不可用时降级为内置已知高危包名单(lodash / minimist / glob-parent / nth-check / shell-quote)快查。 - **自动提示**:`write` / `edit` 成功后,工具结果末尾自动追加一行安全提醒,引导模型运行 `scan` 复核后再提交。 ```powershell node dist/cli.js --profile deepseek # 会话里对模型说"扫描项目安全"即可 ``` > 说明:`scan` 是内建工具,由模型在对话中触发;密钥扫描走工作目录,依赖扫描基于当前目录的 `package.json` / `package-lock.json`。 ### 思考模式 DeepSeek 等官方推荐开启思考模式,**默认开启**。开启后请求会附带 `thinking: { type: "enabled" }` 与 `reasoning_effort: "high"`,编程能力显著提升。不需要时用 `--no-thinking` 关闭。 ```powershell npm run dev -- --profile deepseek --no-thinking ``` CLI 在模型思考(未输出正文)时会显示一行灰色 `[思考中...]` 提示,不会展示思考内容;纯文本轮与 `--no-thinking` 下不出现。 ### GUI 轨迹功能 浏览器界面顶部栏有「对话 / 轨迹」两个页签,轨迹页签把每次运行(run)可视化为一组**横向轨迹条**,dsh 风格的事件溯源视图: - **实时 run 在最上方**,历史 run 按时间倒序往下排;每条轨迹条头部 = caret + 时间徽标 + 迷你时间线 + 首条用户消息摘要 + 工具数,点击头部展开/收起。 - 展开后是**台账式分轮列表**:每轮一个可折叠区块(轮头 sticky),块内每行 = 全局序号 + 类型标签(USER 绿 / ASSISTANT 蓝 / TOOL 琥珀 pill)+ 文本 + 行尾指标列(Input / Output / Think / Time)。TOOL 行内联 `→ 结果`(运行中/成功/失败三色),ASSISTANT 报错显示红色 `→ 错误详情` 整行标红,纯工具调用的 ASSISTANT 行显示 `调用 工具名(参数)`。 - **点击任意轨迹行可展开完整详情**:行下方内联面板显示该行的完整参数与完整结果(TOOL)或完整文本(USER/ASSISTANT),可滚动、可复制;同一轮内同时只展开一行。完整内容取自内存(历史 run 经事件日志按需回放),页面存储仍只保留截断摘要,不放大本地存储。 - 概览条与迷你条为 Chrome 网络面板式时间线,颜色与台账一致,一眼看出每轮/每个工具调用占用多少时间。 - **右键历史 run 的头部**会弹出上下文菜单,可「删除该 run」,确认后连同其事件日志一并删除(实时 run 无菜单)。 - 轨迹数据全部来自 SSE AgentEvent,并持久化到 `localStorage`(`tju.gui.traj`);刷新页面自动重建当前轨迹。历史 run 的事件日志落盘在 `~/.tju-code/logs`(`--log-dir` 可改,`--log-retention` 控制保留天数),刷新/重连时会回放已落盘事件,进行中的轨迹不丢失。 ### CLI 命令 终端会话内可用斜杠命令(`/help` 查看完整说明): | 命令 | 作用 | | --- | --- | | `/exit` | 退出(若正在运行先终止) | | `/clear` | 清空对话记录 | | `/abort` | 取消当前一轮 | | `/model ` | 热切换模型(下一轮生效),如 `/model deepseek-v4-pro` | | `/status` | 显示模型、thinking 开关、消息数、token 与缓存命中 | | `/help` | 完整帮助 | 运行期间按 Ctrl+C:一次取消当轮,再按一次退出。 ### 上下文与缓存 - 上下文默认预算 128K token,超出后自动 `compressTranscript`:先裁剪超大单条消息(保留头尾 + `[N tokens omitted]`)、再按**整轮成对丢弃最旧 turn**(user→assistant→toolResults 一起丢,保护首条消息,保证消息序列结构合法);预算内完全不动,保证 DeepSeek 等前缀缓存的命中。 - 预算可用 `--max-context-tokens ` 调整。 - 每个 assistant 消息的 `usage` 记录 `cacheRead`(命中)/ `cacheWrite`(写入),`/status` 展示累计命中数与命中率。 ### 构建与验证 ```bash npm run build # 产物 dist/,bin 指向 dist/cli.js npm run typecheck npm test ``` ### 使用编译产物(dist/) `npm run build` 后,`dist/` 里就是可直接发布的产物,两个入口: - **CLI(dist/cli.js)**:不经过 tsx 直接跑编译后的命令,效果与 `npm run dev` 一致: ```powershell $env:DEEPSEEK_API_KEY = "sk-你的key" node dist/cli.js --profile deepseek # 终端聊天 node dist/cli.js gui --profile deepseek # 浏览器界面 node dist/cli.js --help # 查看全部参数 ``` 想**全局安装**、在任意目录敲 `tju-code`: ```powershell npm link # 把 dist/cli.js 注册为全局命令 tju-code tju-code --profile deepseek # 不再需要时:npm unlink tju-code ``` 换机器部署时,把 `dist\` 整个拷走即可(`start` 已把 `zod`/`zod-to-json-schema` 直接打进单文件,**自包含、无需安装依赖**;`dist\cli.js` 也带 shebang,可执行)。 - **库(dist/index.js + index.d.ts)**:作为编程接口被其他项目引用。 ```js // 本地相对导入: import { createAgent, runAgentLoop, PROVIDER_PROFILES } from "./dist/index.js"; // 安装/ link 后按包名导入: // import { createAgent } from "tju-code"; ``` 导出内容以 `dist/index.d.ts` 为准(`createAgent` / `Agent` / `runAgentLoop` / 工具工厂 / `PROVIDER_PROFILES` 等)。 > 注意:`dist/` 是独立打包的单文件,别把里面单个文件拆走单独使用;整包移动即可,无需依赖 `src/`。 ## 命令与参数 ``` tju-code [command] [flags] Commands: chat 交互终端会话(默认) gui 浏览器 UI,http://localhost:9399(默认自动打开浏览器) version / help Flags: --api --profile --provider --model --api-key --base-url --no-thinking 关闭思考模式(默认开启) --max-tokens 单次输出上限 --max-context-tokens 上下文预算(默认 128000,超出自动压缩) --port (gui) --no-open ``` 环境变量:`OPENAI_API_KEY` / `OPENAI_BASE_URL` / `ANTHROPIC_API_KEY` / `ANTHROPIC_BASE_URL`,厂商预设各自的 `<厂商>_API_KEY`,以及 AMD 的 `AI_API_KEY` / `AI_API_URL` / `AI_MODEL`。 ## 架构 数据流: ``` CLI/GUI -> Agent (stateful) -> runAgentLoop -> ai layer (OpenAI/Anthropic adapter) -> EventStream ``` 三层消息模型: 1. `GroundEvent` - AI 层产物:`start` / `thinking_delta` / `text_delta` / `toolcall_*` / `done | error` 2. `Message` - 核心层持久化消息:`UserMessage` / `AssistantMessage` / `ToolResultMessage` 3. `AgentEvent` - UI 事件:`message_*` / `turn_*` / `tool_*` / `agent_*` 核心类型与契约集中在 `src/core/types.ts`,AI 层契约在 `src/ai/types.ts`。 ## 扩展点 - **添加 provider**:实现 `src/ai/types.ts` 的 `ProviderAdapter`(`api` + `stream`),在 `src/ai/index.ts` 注册。 - **自定义工具**:`src/core/types.ts` 的 `AgentTool`,用 `zod` 给出 `parameters` 即可被 `createAgent` 使用。 - **运行钩子**:见 `src/core/types.ts` 的 `AgentLoopConfig`,特别是 `transformContext`--上下文压缩/截断/注入的唯一入口(现接入 `compressTranscript`)。 ## 目录 ``` src/ ai/ 统一 AI 层(openai / anthropic / sse / utils) core/ agent 运行时(agent / agent-loop / event-stream / types / tools) gui/ HTTP + SSE 服务器与内嵌前端 cli/ chat 交互会话 config/ create-agent -> CLI 组装 ``` ## 研究机构 - 天津大学系统安全与可信计算研究中心