当前位置: 首页 > news >正文

共享库和适配层都要有镜像测试

背景

如果你最近也在折腾 AI 编程,那这类问题你大概率已经碰到过了:任务不是一上来就挂,而是跑到一半断掉。

这事儿放到普通 HTTP 请求里,很多时候就是重发一下,顶多补个指数退避。可是 Agent CLI 不一样。Claude Code、Codex 这类工具通常是流式执行的,输出是一段一段往外推,过程中还会绑定 thread、session 或 resume token。换句话说,它不是“这一请求失败了没有”,而是:

  • 前面已经吐出来的内容还算不算数
  • 当前上下文还能不能接着跑
  • 这次失败该不该自动恢复
  • 如果要恢复,多久再试,试的时候发什么,原上下文还要不要复用

很多团队第一次做这里,都会下意识写一个最朴素的版本:报错了就再试一次。你说得非常正确,这个想法很自然,可是真进项目里,问题就一个接一个冒出来了。

  • 有些错误明明是暂时故障,却被当成最终失败
  • 有些错误根本不值得重试,却被系统反复重放
  • 有 thread 的请求和没有 thread 的请求,被一把梭地一视同仁
  • 退避策略没边界,后台请求自己把自己打爆

HagiCode 在接多种 Agent CLI 的过程中,也踩过这些坑。尤其是 Codex 这一侧,最初暴露出来的问题就是某类 reconnect 报文没有被识别成可重试终态,结果原本已有的恢复机制根本没机会生效。说白了,不是系统没有自动重试,而是系统没把“这次值得重试”认出来。

所以这篇文章想讲的核心点很明确:自动重试不是一个按钮,而是一套分层设计。

关于 HagiCode

本文分享的方案,来自我们在 项目里的真实实践。HagiCode 要做的事情,不是把某一个模型接上就完事,而是把多种 Agent CLI 的流式消息、工具调用、失败恢复、会话上下文,统一成一套能长期维护的执行模型。

我平时最关心的事情之一,就是怎么让 AI 编程这件事真正落到工程现场。写 Demo 不难,难的是把 Demo 变成团队真的愿意长期使用的东西。HagiCode 之所以认真做自动重试,不是因为这个功能看起来高级,而是因为长链路、流式、可续跑的 CLI 执行如果接不稳,用户看到的就不是智能助手,而是一个动不动半路掉线的命令包装器。

如果你想先看看项目入口,这里先放两个:

再往前走一步讲,HagiCode 现在也已经上架 Steam 了,有 Steam 的朋友可以先加个愿望单:


为什么 Agent CLI 的自动重试比普通重试更难

这个问题提得很实在,我们直接上结论:Agent CLI 的自动重试,难点不在“隔几秒再试一次”,而在“还能不能在原上下文里继续”。

你可以把它理解成一次长对话。普通 API 重试,更像电话占线再拨一遍;而 Agent CLI 重试,更像对方刚讲到一半信号断了,你得先判断要不要回拨,回拨以后要不要从头说,对方还记不记得刚刚聊到哪。谁说这两者是一回事呢?它们压根不是一个工程问题。

具体看,有四个难点最典型。

1. 它是流式的

一旦输出已经发给用户,你就不能像处理普通请求那样,把失败偷偷吞掉然后悄悄重来。因为前面那部分内容已经被看到了,再次重放时如果策略不对,前端很容易看到重复文本、错乱状态,工具调用生命周期也会一起乱套。这波不是玄学,是工程。

2. 它通常绑定会话上下文

Codex 这类 provider 会绑定 thread,Claude Code 一类实现也会有 continuation target 或等价的续跑上下文。真正能自动重试的前提,不只是“这个错误长得像暂时故障”,还包括“这次执行还有没有继续下去的载体”。

3. 它不是所有错误都值得重试

网络抖动、SSE idle timeout、上游临时故障,这些通常可以试一试。可如果你遇到的是认证失败、上下文已经丢了,或者 provider 根本没有 resume 能力,那继续重试多数不是恢复,而是在制造噪音。

4. 它需要边界

无限自动重试几乎总是错的。技术趋势可以热闹一阵子,工程规律往往会稳定很多年,其中一条就是:失败恢复一定要有边界。系统必须知道自己最多试几次、每次隔多久、什么时候该停手承认这回真不行了。

也正因为这几个特点,HagiCode 最后没有把自动重试写成某个 provider 里的几行 try/catch,而是把它提炼成一层共享能力。说到底,工程问题还是要回到工程方法里解决。

HagiCode 的做法:把重试从 Provider 里拿出来

HagiCode 当前这套真实实现,可以压缩成一句话:

共享层统一管理重试流程,具体 Provider 只负责回答两个问题:这个终态值不值得重试?当前上下文还能不能继续?

这件事不复杂,可是很关键。因为一旦把职责切开,Claude Code、Codex,甚至其他 Agent CLI 都能复用同一个骨架。模型会说,工具会变,工作流会升级,但工程上的基本盘一直都在那里。

第一层:用统一协调器管理重试循环

项目中的核心实现片段大概是下面这样:

  internal static class ProviderErrorAutoRetryCoordinator
  {
  public static async IAsyncEnumerable<CliMessage> ExecuteAsync(
  string prompt,
  ProviderErrorAutoRetrySettings? settings,
  Func<string, IAsyncEnumerable<CliMessage>> executeAttemptAsync,
  Func<bool> canRetryInSameContext,
  Func<TimeSpan, CancellationToken, Task> delayAsync,
  Func<CliMessage, bool> isRetryableTerminalMessage,
  [EnumeratorCancellation] CancellationToken cancellationToken)
  {
  var normalizedSettings = ProviderErrorAutoRetrySettings.Normalize(settings);
  var retrySchedule = normalizedSettings.Enabled
  ? normalizedSettings.GetRetrySchedule()
  : [];
   
  for (var attempt = 0; ; attempt++)
  {
  var attemptPrompt = attempt == 0
  ? prompt
  : ProviderErrorAutoRetrySettings.ContinuationPrompt;
   
  CliMessage? terminalFailure = null;
   
  await foreach (var message in executeAttemptAsync(attemptPrompt)
  .WithCancellation(cancellationToken))
  {
  if (isRetryableTerminalMessage(message))
  {
  terminalFailure = message;
  break;
  }
   
  yield return message;
  }
   
  if (terminalFailure is null)
  {
  yield break;
  }
   
  if (attempt >= retrySchedule.Count || !canRetryInSameContext())
  {
  yield return terminalFailure;
  yield break;
  }
   
  await delayAsync(retrySchedule[attempt], cancellationToken);
  }
  }
  }

这段代码干的事情,其实非常朴素,但很有力。

  • 中间失败先不直接透传,协调器先判断能不能恢复
  • 只有重试预算耗尽,最终失败才真正回到上层
  • 第二轮开始不再发送原始 prompt,而是统一发送 continuation prompt

这也就是为什么我前面一直强调,自动重试不是简单的“再请求一次”。它不是在补一个异常分支,而是在管理一条执行生命周其。听起来有点像产品经理,但工程上确实如此。

第二层:把重试策略快照化

另一个很容易被忽略的问题是:谁来决定这次请求是否开启自动重试?

HagiCode 的答案是,不要依赖某个“此刻的全局配置”,而是把策略做成 snapshot,跟着这次请求一起走。这样一来,会话排队、消息持久化、执行转发、provider 适配,都不会把策略弄丢。一次成功不叫体系,持续成功才叫体系。

核心结构可以简化成这样:

  public sealed record ProviderErrorAutoRetrySnapshot
  {
  public const string DefaultStrategy = "default";
   
  public bool Enabled { get; init; }
   
  public string Strategy { get; init; } = DefaultStrategy;
   
  public static ProviderErrorAutoRetrySnapshot Normalize(bool? enabled, string? strategy)
  {
  return new ProviderErrorAutoRetrySnapshot
  {
  Enabled = enabled ?? true,
  Strategy = string.IsNullOrWhiteSpace(strategy)
  ? DefaultStrategy
  : strategy.Trim()
  };
  }
  }

然后在执行侧再映射成 provider 真正消费的设置对象。这个做法的价值很直接:

  • 业务层决定“该不该重试”
  • 运行时决定“怎么重试”

两边各管一摊,互相不打架。很多问题不是不能做,只是没把代价算明白。把策略快照化,本质上就是在提前把代价算清楚。

第三层:Provider 只做终态判定和上下文判定

到了具体的 Claude Code 或 Codex provider,这里的职责反而很薄。你可以把它理解成增强,不要把它误会成代替。

以 Codex 为例,它最终接入共享协调器时,本质上只需要提供三样东西:

  await foreach (var message in ProviderErrorAutoRetryCoordinator.ExecuteAsync(
  prompt,
  options.ProviderErrorAutoRetry,
  retryPrompt => ExecuteCodexAttemptAsync(...),
  () => !string.IsNullOrWhiteSpace(resolvedThreadId),
  DelayAsync,
  IsRetryableTerminalFailure,
  cancellationToken))
  {
  yield return message;
  }

你会发现,真正属于 Provider 自己的判断只有两个:

  • IsRetryableTerminalFailure
  • canRetryInSameContext

Codex 看的是 thread 还能不能续上,Claude Code 看的是 continuation target 还在不在。退避策略、重试次数、后续 prompt,这些通通不该让 Provider 自己重新发明一遍。

这一层拆出来以后,HagiCode 接更多 CLI 的成本就低很多了。你不用复制一整套重试状态机,只要把“这个 provider 的边界条件”接进来就行。写得快,不等于写得稳;接得住,不等于接得好;能跑起来,也不等于能长期维护。

一个很容易做错的点:别把所有报错都当可重试

这次分析里,我觉得最值得单拎出来讲的,不是“怎么实现重试”,而是“怎么避免错误重试”。

最开始的问题切入口,是 Codex 少识别了一条 reconnect 报文。按直觉,很多人会选一个最小修法:往白名单里再加一条字符串前缀。这个思路不能说错,只是它更像 Demo 时期的解法,不太像长期维护的解法。

从当前 HagiCode 的落地来看,系统已经往更稳的方向走了一步。它不再只盯着某个字面字符串,而是把可恢复的终态统一交给共享协调器处理。这样做的好处很明显:

  • 不容易因为某条文案的小改动就彻底失效
  • 测试覆盖可以围绕“终态 envelope”展开,而不是单条硬编码文本
  • 同一个 provider 的重试逻辑会更一致

当然,这里要立一个边界:更通用,不等于更宽松。只要当前上下文不能继续,哪怕报错看起来很像暂时故障,也不应该盲目 replay。

这点很关键。真正让人安心的,不是它偶尔灵一次,而是它大多数时候都靠谱。如果一个流程只能靠高手维持,那它离普及还差得远。

实践里最值得保留的三条经验

文章写到这里,差不多可以往实践层收一收了。如果你准备在自己的项目里实现类似能力,我最建议先守住下面三条。

1. 重试预算必须有边界

HagiCode 当前默认的退避节奏是:

  • 10 秒
  • 20 秒
  • 60 秒

这个节奏不一定适合所有系统,但“有边界”这件事必须保留。要不然,自动重试很快就会从恢复机制变成事故放大器。别急着把名字起得太大,先看看这东西能不能在团队里活过两个迭代。

2. continuation prompt 要统一

项目里使用的是固定 continuation prompt,让后续 attempt 明确走“继续当前上下文”的路径,而不是重新发起一轮完整请求。这个能力不花哨,可是你真做项目时离不开。很多能力看起来像魔法,拆开以后不过是一套被打磨过的工程流程。

3. 共享库和适配层都要有镜像测试

这点我很想多说一句。很多团队会在共享运行时里写一层测试,然后觉得差不多了。其实不够。

HagiCode 这边之所以让我比较放心,是因为两层都补了测试:

  • 共享 Provider 测“是否真的发生了自动续跑”
  • 适配层测“最终错误和流式消息有没有被整理坏”

我这次也额外补跑了两组相关测试,结果都是 31 个用例全部通过。这个结果本身说明不了设计一定完美,可它至少能说明一件事:当前这套自动重试不是纸面方案,而是已经被代码和测试共同约束住的能力。Talk is cheap. Show me the code. 放到这里,恰好合适。

总结

如果把整篇文章压缩成一句话,那就是:

Claude Code、Codex 等 Agent CLI 的自动重试,最好不要做成某个 Provider 内部的局部技巧,而应该做成共享协调器 + 策略快照 + 上下文判定 + 镜像测试的组合。

这样做带来的收益,其实非常实在:

  • 逻辑只写一遍,多个 Provider 都能复用
  • 请求是否允许重试,可以稳定地跟着执行链路走
  • 有上下文时继续跑,没上下文时及时停手
  • 前端最终看到的是稳定的完成态或失败态,而不是一堆半途而废的中间噪音

这套方案,是 HagiCode 在真实接入多种 Agent CLI 的过程中一点点打磨出来的。谁说 AI 辅助编程就不是新时代的结对编程呢?模型帮你起步、补全、发散,可真正决定体验上限的,往往还是上下文、流程和约束。

如果本文对你有帮助,也欢迎顺手看看 HagiCode 的公开入口:

 


https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220628
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220606
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220583
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220560
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220538
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220514
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220492
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220470
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220448
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220425
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220403
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220380
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220358
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222835
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222742
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222670
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222587
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222507
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222432
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222354
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222274
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222194
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222109
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222050
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221982
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221919
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221857
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221805
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221757
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221704
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221654
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221603
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221546
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221491
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221436
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221365
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221305
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221243
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220963
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220923
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220884
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220844
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220810
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220778
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220754
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220731
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220709
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220687
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220664
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220642
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220620
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220598
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220575
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220553
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220529
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220507
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220484
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220462
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220439
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220417
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220395
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220373
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220350
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222855
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222761
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222685
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222605
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222522
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222445
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222371
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222289
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222212
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222130
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222062
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222000
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221930
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221867
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221816
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221766
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221716
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221665
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221612
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221556
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221503
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221448
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221382
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221319
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221256
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220972
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220931
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220891
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220851
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220816
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220784
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220758
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220736
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220713
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220691
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220669
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220646
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220624
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220602
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220580
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220557
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220535
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220511
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220488
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220466
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220444
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220422
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220399
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220377
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220354
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222905
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222805
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222726
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222648
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222567
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222487
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222414
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222332
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222253
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222173
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222096
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222038
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221966
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221903
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221845
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221793
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221743
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221691
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221641
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221584
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221534
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221479
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221425
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221353
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221293
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220998
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220951
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220912
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220874
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220834
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220803
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220772
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220748
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220726
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220704
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220682
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220659
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220637
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220615
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220592
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220570
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220547
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220523
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220500
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220478
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220456
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220434
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220412
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220389
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220367
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222827
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222736
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222660
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222581
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222501
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222425
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222345
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222265
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222185
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222105
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222045
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221980
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221913
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221852
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221801
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221750
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221700
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221648
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221595
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221542
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221487
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221432
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221357
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221301
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221240
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220958
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220917
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220879
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220841
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220808
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220776
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220752
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220729
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220707
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220685
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220662
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220640
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220618
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220595
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220573
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220550
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220526
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220504
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220482
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220460
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220437
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220415
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220392
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220370
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220348
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222909
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222811
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222729
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222655
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222571
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222494
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222419
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222337
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222259
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222181
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222099
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222041
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221968
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221909
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221846
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221795
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221744
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221695
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221644
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221587
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221535
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221482
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221428
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221355
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221294
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221000
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220954
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220914
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220875
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220837
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220805
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220773
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220750
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220727
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220705
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220683
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220660
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220638
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220616
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220593
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220571
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220548
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220524
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220502
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220480
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220457
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220435
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220413
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220390
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220368
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222845
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222752
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222678
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222596
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222514
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222439
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222360
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222282
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222203
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222118
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222058
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221989
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221922
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221862
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221811
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221760
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221710
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221658
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221605
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221551
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221499
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221444
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221377
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221313
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221249
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220967
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220926
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220887
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220847
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220814
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220782
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220756
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220733
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220711
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220689
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220667
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220644
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220622
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220600
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220577
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220555
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220532
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220509
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220486
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220464
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220442
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220420
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220397
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220375
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220352
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222874
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222782
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222704
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222625
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222542
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222466
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222389
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222311
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222232
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222151
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222079
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6222017
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221951
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221883
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221829
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221780
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221729
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221677
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221625
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221572
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221518
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221465
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221394
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221336
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6221269
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220985
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220940
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220901
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220862
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220826
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220793
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220764
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220742
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220719
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220697
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220675
https://2shou.guilinlife.com/index.php?m=wap&a=show&catid=302&id=6220652

http://www.jsqmd.com/news/838357/

相关文章:

  • 终端AI助手Chaterm:无缝集成开发工作流的命令行聊天工具
  • B站视频解析API高性能技术实现方案与架构解析
  • 基于RT-Thread与Zephyr协议栈的BlueNRG-2蓝牙芯片启动全流程解析
  • RK3568开发板TFTP网络启动:告别烧录,实现内核与设备树秒级更新
  • NotebookLM笔记无法复制?谷歌工程师内部流出的3种合规导出路径,第2种已被悄悄封禁
  • 【AI Agent未来十年演进路线图】:20位顶级实验室负责人闭门预测+3大技术奇点时间表
  • 学生党福音:手把手教你零成本搞定GitHub Copilot学生认证(附PyCharm配置全流程)
  • FastAPI集成JSON-RPC:混合协议API设计与工程实践
  • 修音翻车现场实录:用Melodyne选择工具时,这3个坑我劝你别踩
  • 2026都江堰口碑超棒的除甲醛企业大推荐,让你放心呼吸清新空气! - 得意的笑125
  • 物理生物学研究报告【20260005】
  • 深入AMD Ryzen硬件层:三阶调试实战指南
  • 通过curl命令调试与验证大模型API连接状态
  • 2026年|留子必备:英文降AI率指南,3招告别Turnitin标蓝,AI率80%降至10% - 降AI实验室
  • 符号回归与压缩感知融合的智能建模框架SISSO深度解析
  • Air780EHM实战:LuatOS内存占用拆解
  • Pearcleaner:macOS应用清理的终极解决方案,彻底释放磁盘空间
  • 智能音乐管家:3分钟掌握Xiaomusic的5大核心玩法
  • 点支承幕墙玻璃破裂故障分析
  • 开源笔记工具MindPocket:本地优先的Markdown知识管理方案
  • SISSO 3.5:机器学习中可解释符号回归的终极解决方案
  • usb 串行口驱动庖丁解牛4: 数据收发的实现
  • MOOTDX:解锁量化投资的免费通达信数据接口,5分钟构建专业金融数据平台
  • Kubernetes轻量级服务网格Cetus:核心流量治理与Sidecar代理实践
  • 圣多美投资入籍项目评选标准权威发布:睿港国际移民真正符合金字塔顶端的严苛要求! - 博客万
  • AI智能体沙盒环境AgentBox:安全隔离与容器化部署实践
  • MySQL 库的操作
  • 从蓝牙4.2到5.4:广播包格式的‘进化史’与向后兼容那些坑
  • AChat开源项目:快速构建本地大模型Web聊天界面的轻量级脚手架
  • 5分钟掌握猫抓扩展:浏览器视频下载终极指南