给你的 code agent 搓一个错误检测机制

前言

众所周知,code agent 是无法判断出生成的代码是否正确的。也就是只有生成环节,没有验证环节,所以需要我们一点点做 debug,这也是很多人最开始不看好 ai 的原因。

但反过来想,是不是解决了验证环节,ai 的体验就会获得大幅提升呢。

锁定问题

要想解决验证环节,可以先思考我们是如何做 debug 的。

对于前端,一般而言都是先安装依赖,看看代码有没有爆红。然后运行,看项目是否能正常启动,最后打开页面和控制台,点一点看哪里有问题。

拆解来看,其实分为了几个问题:

  • 是否能正常安装依赖
  • 代码是否直接在编辑器就出现了错误(静态检测/开发时错误)
  • 项目是否能正常启动(构建时错误)
  • 控制台是否报错(运行时错误)

所以,我们的目标是依次解决这些问题。

解决方案

能否正常安装依赖

这一步其实相对简单,运行 npm i 就行了。需要注意的点有:

  1. npm 安装依赖存在不少问题,它使用扁平化所有依赖,并逐个进行下载的做法,这可能会导致幽灵依赖 (能引用到没安装 package.json 的部分包),安装缓慢 (内存存储双爆炸),依赖冲突 (子依赖使用了不同版本)等问题。为了解决这些问题,pnpm 出现了,目前大部分前端项目都会优先考虑使用 pnpm
  2. 关于锁文件的问题

真正决定安装版本的是锁文件 ,其生成依赖于 package.json。但不要手动修改锁文件。

安装会有很多种情况

情况1:当有锁文件,且与 package.json 中包一致时,执行安装,会完全按照锁文件进行安装,这是最常见且最安全的情况。

情况2:当有锁文件,且与 package.json 中包不一致(比如手动在 package.json 中更新了包),执行安装,锁文件会更新有变化的部分。锁文件更新后,后续再进行安装就会进入到情况1

情况3:当没有锁文件,执行安装依赖时,会按 package.json 里的依赖

  • 精确版本号时,会选择精确版本("axios": "1.5.0" 会安装 1.5.0)
  • 有 ^ 时,允许小版本自动更新("axios": "^1.5.0" 会选择最新且小于 2.0.0 的版本)
  • 有 ~ 时,允许小特性自动更新("axios": "~1.5.0" 会安装最新且小于 1.6.0 的版本)

根据这些规则,会选择出所有适合的包,生成锁文件,接着进入情况1,使后续该项目使用的包稳定,不会出现突然升级的问题。

暂时无法在昆仑万维文档外展示此内容

最佳实践:安装/更新新依赖,最好还是走命令行

less 复制代码
npm i xxx // 安装
npm i xxx@latest // 更新最新版,也可以指定版本如 xxx@1.0.0

这样能自动同时更新 package.json 和锁文件,且不影响其他包。

退而求其次,是手动修改 package.json,随后再进行 npm i 重新安装,这样也能让锁文件进行更新,

如果单独修改 package.json 文件,可能是无效的,比如:package.json 中 "axios": "^1.5.0",lock 中 1.5.2,此时你将 package.json 的 ^1.5.0 改为 ^1.5.1,由于 lock 中的 1.5.2 仍符合^1.5.1,所以是无事发生,不会产生任何更新。

是否直接在编辑器就出现了错误

ai 的很多错误,其实在前端通常都能很直接的看到,如下:

这里的报错其实有两个原因:eslint 报错与 ts 报错

我们可以通过这两个命令扫描出对应的错误:

css 复制代码
npx eslint ./
npx tsc --noEmit -p tsconfig.app.json --strict

我们可以在对应的文件中,配置对应的规则集,eslint 的配置位于 eslint.config.js 中;ts 的配置位于 tsconfig.app.json。

严格的规则,有助于 ai 生成产物的稳定,更不容易出现白屏报错等问题,但相对的时间会更长,因为要解决更多 error。宽松的规则,则对应 token 的减少,时间更快。

在我们的项目中,使用了默认的规则集,基本上就够用了,不过有几个模型经常报错、但不影响主流程的,我们还是降低为了 warn,从而规避修复所需要花费的成本。

perl 复制代码
"@typescript-eslint/no-unused-vars": "warn", // 未使用变量降为 warn
"@typescript-eslint/no-empty-object-type": "warn", // 空对象类型降为 warn
"@typescript-eslint/no-explicit-any": "warn", // any 类型降为 warn,这个可能还有待商榷,过多的使用 any 本质上就是忽略报错

项目是否能正常启动

在大部分情况下,如果前两个步骤是正确的,最后一步 build 大概率不会有问题。即使有问题,模型也能在 build 后也能看到构建报错,从而直接进行修复。

如果想要验证也简单,跑一个构建命令就行了

arduino 复制代码
npm run build

控制台是否报错

前面三个环节,都可以用命令行进行验证和 debug,也就是 agent 有办法感知到。但控制台的报错,属于运行时错误,很难报给 agent,所以我们需要设计一套上报机制来解决这个问题。

也就是这个需求 【Websites】增加手动Debug模式,简单来说,就是控制台的所有报错都暴露出来发给 agent

要实现这点,关键在于拦截所有报错,我们来看常见的报错,逐个进行解决。

  1. 普通 js 同步报错,也是最常见的一种,语法问题等引起

解法:可以用 window.onerror 进行回调处理

  1. promise reject 未处理报错,类似 try catch 问题

解法:可以使用 window.addEventListener("unhandledrejection", event => {}) 来做回调处理

  1. 接口报错 / 资源加载失败

虽然严格意义上,不算代码的问题,但是也有必要让 agent 感知到

解法:通信使用 axios 包,并且在其响应拦截器中做处理,如果不是 200,则进行 error 回调

主要的报错就这三种,我们可以基于此封装一套错误抛出的机制。不过 github 实际上有现成的更完备的库,可以考虑直接使用 Sentry 来做这件事。sentry 本身是用于错误上报的,不过我们可以将其拦截掉,在 callback 中只执行我们的逻辑即可。

js 复制代码
  Sentry.init({
    dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0', // 使用假 DSN 来启用错误捕获功能
    enabled: true, // 启用 Sentry
    attachStacktrace: true, // 附加堆栈跟踪
    
    // 在发送前处理错误
    beforeSend(event, hint) {
      const error = hint.originalException || hint.syntheticException
      dosomething(error, event)
      // 返回 null 阻止实际上报到 Sentry
      return null
    },
  })

当你的模版中接入了这套流程后,你就可以将错误向 agent 抛出了,比如说:

  1. skywork 中,产物是在 iframe 里,那么我们可以利用 postMessage 将错误反馈到主应用,从而在输入框中引用到错误并发送给 agent

  2. 如果产物完全独立,可以考虑将错误打到接口中,之后的通信让 agent 先去访问这些错误,修复后再做操作

总结

所以最终这个机制有以下几个部分构成:

  1. 安装、更新依赖时走命令行(且最好使用 pnpm 而非 npm)
less 复制代码
npm i xxx // 安装
npm i xxx@latest // 更新最新版,也可以指定版本如 xxx@1.0.0
  1. build 前先扫描错误并修复(要使用 typescript 而非 js,要接入 eslint)
css 复制代码
npx eslint ./
npx tsc --noEmit -p tsconfig.app.json --strict
  1. 跑 build 看有没有问题
arduino 复制代码
npm run build
  1. 在模版中接入运行时错误监控,并将监控的结果传递给 agent
js 复制代码
  Sentry.init({
    dsn: 'https://examplePublicKey@o0.ingest.sentry.io/0', // 使用假 DSN 来启用错误捕获功能
    enabled: true, // 启用 Sentry
    attachStacktrace: true, // 附加堆栈跟踪
    
    // 在发送前处理错误
    beforeSend(event, hint) {
      const error = hint.originalException || hint.syntheticException
      dosomething(error, event) // 自定义实现
      // 返回 null 阻止实际上报到 Sentry
      return null
    },
  })
  
相关推荐
mCell15 小时前
如何零成本搭建个人站点
前端·程序员·github
mCell16 小时前
为什么 Memo Code 先做 CLI:以及终端输入框到底有多难搞
前端·设计模式·agent
恋猫de小郭16 小时前
AI 在提高你工作效率的同时,也一直在增加你的疲惫和焦虑
前端·人工智能·ai编程
少云清16 小时前
【安全测试】2_客户端脚本安全测试 _XSS和CSRF
前端·xss·csrf
银烛木17 小时前
黑马程序员前端h5+css3
前端·css·css3
m0_6070766017 小时前
CSS3 转换,快手前端面试经验,隔壁都馋哭了
前端·面试·css3
听海边涛声17 小时前
CSS3 图片模糊处理
前端·css·css3
IT、木易17 小时前
css3 backdrop-filter 在移动端 Safari 上导致渲染性能急剧下降的优化方案有哪些?
前端·css3·safari
0思必得017 小时前
[Web自动化] Selenium无头模式
前端·爬虫·selenium·自动化·web自动化
anOnion17 小时前
构建无障碍组件之Dialog Pattern
前端·html·交互设计