ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CodeBurn 的 Qwen Code CLI 集成:JSONL 会话解析、Token 成本核算与去重机制全解析

CodeBurn 的 Qwen Code CLI 集成:JSONL 会话解析、Token 成本核算与去重机制全解析 【免费下载链接】codeburnFree, local tool to track AI coding token usage and cost across 37 tools and agents (Claude Code, Cursor, Codex, Gemini and more), by model, project, and task. npx codeburn项目地址https://gitcode.com/gh_mirrors/co/codeburn点击查看免费下载CodeBurn 是一款本地运行、无需账号的 AI 编码 Token 用量与成本追踪工具它直接读取 Claude Code、Cursor、Codex、Gemini 等工具在你磁盘上留下的会话文件并按工具、模型、项目与任务维度产出账单级明细。本文聚焦其中 QwenQwen Code CLI这一集成从数据读取路径、JSONL 存储格式、解析与成本计算流水线到去重键、项目命名规则、工具调用提取等关键 Quirks以及为它补充测试与修复 Bug 的完整路径。读完本文你将能定位 Qwen 集成涉及的每一段代码理解它的行为边界并知道如何排查“工具缺失”“重复计数”“成本为 0”等典型问题。集成概览eager 加载的 31 个核心 Provider 之一Qwen 是 CodeBurn 中最早、最基础的 Provider 集成之一对应源码文件为 src/providers/qwen.ts文档索引见 docs/providers/README.md 的 Eager始终加载表格。在 src/providers/index.ts 的coreProviders数组中qwen与claude、cline、codex、copilot、gemini等 31 个 Provider 一起被静态 import 并立即注册src/providers/index.ts这意味着每次扫描会话时 Qwen 解析器必然参与发现与解析不存在懒加载失败被跳过的分支qwen出现在allProviderNames()返回的合法--provider取值集合中src/providers/index.ts你可以用codeburn --provider qwen或codeburn doctor --provider qwen单独限定到该集成作为对照antigravity、forge、cursor、warp等才走懒加载路径src/providers/index.ts。Provider 的通用契约定义在 src/providers/types.ts每个 Provider 需要实现discoverSessions()返回SessionSource[]、createSessionParser()返回逐条产出ParsedProviderCall的SessionParser以及可选的probeRoots()供codeburn doctor展示并校验探测路径。Qwen 集成的整体结构即围绕这三个方法展开。数据来源QWEN_DATA_DIR 与 ~/.qwen/projects 目录布局Qwen 的会话数据读取路径由 src/providers/qwen.ts 的getQwenProjectsDir()决定function getQwenProjectsDir(): string { return process.env[QWEN_DATA_DIR] ?? join(homedir(), .qwen, projects) }优先级为优先级取值说明1$QWEN_DATA_DIR环境变量适合自定义安装目录或 CI 环境2~/.qwen/projects默认路径即join(homedir(), .qwen, projects)目录结构为两级嵌套projectsDir/projectDir/chats/*.jsonl。discoverSessions()src/providers/qwen.ts的扫描逻辑是readdir(projectsDir)枚举所有项目目录失败如目录不存在时直接返回空数组对每个项目目录进入其chats子目录读取全部*.jsonl文件每个文件经stat确认是常规文件后包装成SessionSource含path、project、provider: qwen加入结果。值得注意的健壮性设计若某项目没有chats子目录readdir抛错该目录被continue跳过而不是让整个发现失败这与 src/providers/index.ts 的discoverOne隔离机制一脉相承——任何一个 Provider 的发现异常都不会拖垮整轮扫描异常会以codeburn: skipped qwen discovery after an error: ...的形式告警一次后跳过。probeRoots()返回[{ path: projectsDir, label: projects }]因此在codeburn doctor中可以看到实际探测的是哪个目录用于区分“Qwen 未安装”与“QWEN_DATA_DIR 配错”。存储格式逐行 JSON 的 JSONL 会话文件Qwen 会话文件是JSONLJSON Lines格式每行一个独立 JSON 对象代表一条会话事件。解析器在 src/providers/qwen.ts 用raw.split(\n)按行切分、过滤空行后逐行JSON.parse解析失败的行走continue静默跳过src/providers/qwen.ts保证单行损坏不阻塞整条会话。文件读取复用 src/fs-utils.ts 的readSessionFile()该函数对超过MAX_SESSION_FILE_BYTES128 MB的文件会跳过并告警避免超大文件拖垮内存。每条记录的类型QwenEntrysrc/providers/qwen.ts包含的关键字段字段类型用途uuidstring单轮turn唯一标识参与去重键sessionIdstring会话标识参与去重键timestampstring事件时间参与周期归集typeuser/assistant等区分用户消息与助手回合modelstring模型名缺失时回退qwen-automessage.partsQwenPart[]文本、thought、函数调用等分段usageMetadataobjecttoken 计数来源见下文QwenPartsrc/providers/qwen.ts是message.parts的单元结构text文本、thought思考标记、functionCall工具调用信封与functionResponse工具结果。解析流水线从 JSONL 到 ParsedProviderCall解析核心是createParser()返回的异步生成器src/providers/qwen.ts它对每一行执行如下分支1. 用户消息type user收集parts中非 thought 的文本拼接后截取前 500 字符存入pendingUserMessagesrc/providers/qwen.ts作为下一条助手调用的userMessage附带到产出中随后continue不产出调用。2. 助手消息type assistant且必须带usageMetadata缺少usageMetadata的记录直接跳过src/providers/qwen.ts。3. 零消耗过滤当promptTokenCount与candidatesTokenCount同时为 0 时跳过src/providers/qwen.ts避免把无 token 消耗的占位回合计入报表。4. 去重以qwen:${sessionId}:${uuid}为键查重见下文专节。5. 成本核算将usageMetadata的四项计数映射到ParsedProviderCall的标准字段usageMetadata 字段映射到 ParsedProviderCall说明promptTokenCountinputTokens输入 tokencandidatesTokenCountoutputTokens常规输出 tokenthoughtsTokenCountreasoningTokens思考 token单独计数并计入成本cachedContentTokenCountcachedInputTokens/cacheReadInputTokens缓存命中读取的 token6. 产出调用yield一个完整的ParsedProviderCall契约见 src/providers/types.ts字段包括provider: qwen、model、四类 token 计数、costUSD、tools、bashCommands、timestamp、deduplicationKey、userMessage、sessionId等。时间戳兜底回退到文件 mtimeisoTimestamp()src/providers/qwen.ts会校验记录自带的timestamp能解析为合法日期则转 ISO 格式返回缺失或不可解析时回退到会话文件的 mtimefileMtime。这样即使个别行时间戳损坏调用也能落在真实日期上而不是落入空字符串被 src/parser.ts 的周期过滤器排除。成本计算thoughts 计入输出、缓存 token 单独计价成本统一走 src/models.ts 的calculateCost()Qwen 的调用方式是const costUSD calculateCost(model, inputTokens, outputTokens reasoningTokens, 0, cachedTokens, 0)值得展开的三个细节思考 token 计入输出thoughtsTokenCount被加入outputTokens一起按输出单价计费。Qwen 官方将 thought 与候选输出分开上报但思考过程同样消耗模型输出配额因此 CodeBurn 把它并入输出成本同时保留reasoningTokens字段供报表展示思考量缓存 token 以cacheRead身份计费cachedContentTokenCount作为第 5 个参数cacheReadTokens传入按缓存读取单价计价同时写入cachedInputTokens供模型效率分析使用cacheCreationInputTokens固定为 0Qwen 不单独上报缓存写入未知模型返回 $0若模型不在定价库中calculateCost返回 0 并向 stderr 输出提示--verbose下可见此时报表中该调用成本为 0——排查“Qwen 成本全为 0”问题时先确认模型名是否已收录。去重机制qwen:sessionId:uuid与跨 Provider 的 seenKeysQwen 的去重键由三部分组成src/providers/qwen.tsconst dedupKey qwen:${entry.sessionId}:${entry.uuid} if (seenKeys.has(dedupKey)) continue seenKeys.add(dedupKey)seenKeys是一个跨 Provider、跨文件共享的Set在 src/parser.ts 等处被统一维护解析器在处理每个调用前查询、处理后写入。这套共享去重机制的意义在于同一会话文件在增量解析中被重复读到例如文件追加、缓存重建时已见键的调用不会二次计数不同 Provider 的数据若指向同一底层会话极端场景也能靠键前缀qwen:、claude:、gemini:等天然区隔该键最终落在deduplicationKey字段随会话缓存持久化见 src/parser.ts 等缓存写入点冷启动重放时同样生效。原文档特别提醒的坑部分 Qwen 构建在续接resumed会话时会重复生成 UUID。如果你的复现场景中“同一轮被计数两次”先验证sessionId:uuid在你的数据里是否真的唯一——若 UUID 重复单纯依赖该键无法去重需要在修复时补充更稳妥的判据。工具调用提取固定信封结构与工具名映射工具function call从message.parts的固定信封形状functionCall: { name, args }中提取逻辑集中在extractTools()src/providers/qwen.tsfor (const part of parts) { if (part.functionCall?.name) { const mapped toolNameMap[part.functionCall.name] ?? part.functionCall.name tools.push(mapped) if (mapped Bash part.functionCall.args typeof part.functionCall.args[command] string) { bashCommands.push(...extractBashCommands(part.functionCall.args[command] as string)) } } }工具名映射表src/providers/qwen.tsQwen 原始工具名CodeBurn 展示名read_fileReadwrite_to_fileWriteedit_fileEditexecute_commandBashsearch_filesGreplist_files/list_directoryLSbrowser_actionWebFetchweb_searchWebSearchask_followup_questionAskUserattempt_completionComplete未命中映射表的工具名原样保留toolNameMap[raw] ?? raw同时toolDisplayName()src/providers/qwen.ts在渲染层复用同一张表保证报表展示一致。两个派生行为值得注意当映射结果为Bash且args.command是字符串时会调用 src/bash-utils.ts 的extractBashCommands()进一步拆出实际执行的 shell 命令——该函数会剥离 ANSI 转义、剔除引号包裹的字符串内容并按、;、|分隔符把复合命令切成片段见 src/bash-utils.ts从而支撑“按任务/命令统计”的报表维度固定信封是脆弱点functionCall是当前 Qwen 版本的上报形状原文档明确警告——如果未来 Qwen 重构工具调用格式这里extractTools的循环会是第一个坏掉的地方。出现“工具全部缺失”类 Bug 时应优先排查该循环对parts结构的假设是否仍然成立。项目命名 Quirks来自目录名的最后一段discoverSessions()通过projectNameFromDirName()src/providers/qwen.ts从项目目录名推导项目名function projectNameFromDirName(dirName: string): string { const parts dirName.replace(/^-/, ).split(-) return parts[parts.length - 1] || dirName }规则去掉前导-后按-切分取最后一段作为项目名。这意味着项目名完全来自文件系统路径而不来自会话文件内的任何字段。由此产生的两个可推断后果同一项目放在两个不同路径下会被识别为两个项目目录名不同 → 项目名可能不同这是原文档明确记录的 Quirk带-前缀或含多个连字符的目录名只会取最后一段因此目录命名本身会影响报表中的项目聚合粒度。测试现状与修复指南截至当前仓库tests/providers/目录下已有claude.test.ts、cline.test.ts、codebuff.test.ts等 Provider 测试但没有qwen.test.tsdocs/providers/README.md 索引表中 Qwen 一行的 Test 列为 none。原文档将其标注为“已知的 good first issue”为 Qwen 添加 fixture 数据与 fixture 驱动测试让回归对所有人可见。如果你要修复 Qwen 集成中的 Bug按以下清单推进先加 fixture 与测试再改逻辑。缺少tests/providers/qwen.test.ts意味着任何行为变更都没有回归保护回归不可见症状是“工具缺失”检查extractTools()的函数调用提取循环src/providers/qwen.ts确认functionCall.name信封结构是否仍与当前 Qwen 版本匹配以及toolNameMap是否需要补充新工具名症状是“重复计数”先确认sessionId:uuid在你的复现数据中确实唯一——已知部分 Qwen 构建在续接会话时重复 UUID此时该去重键失效需要调整去重策略症状是“成本为 0”分两层排查——先确认usageMetadata四项计数是否正常落入解析结果可用codeburn doctor --provider qwen检查发现与解析健康度再确认模型名是否在 src/models.ts 的定价库中未收录的模型成本必然为 0 并伴随 stderr 提示。在 CodeBurn 中验证 Qwen 集成验证链路分为发现与解析两层codeburn doctor --provider qwen只诊断 Qwen展示probeRoots解析出的实际探测路径$QWEN_DATA_DIR或~/.qwen/projects、发现的会话数、解析健康度--json可输出机器可读结果参见 docs/cli.mdcodeburn overview --provider qwen只看 Qwen 的用量与成本汇总直接运行npx codeburn无账号、无注册见 README.md会在总览中看到 Qwen 按模型、按项目的明细行与 Claude、Codex 等其余 30 个集成并列聚合。由于 Qwen 集成是 eager 加载只要本机存在~/.qwen/projects/*/chats/*.jsonl或QWEN_DATA_DIR指向的等价目录无需任何额外配置即可被扫描若路径被改过codeburn doctor --provider qwen能立刻区分“Qwen 未安装/无数据”与“环境变量配错”两种情况。赞分享【免费下载链接】codeburnFree, local tool to track AI coding token usage and cost across 37 tools and agents (Claude Code, Cursor, Codex, Gemini and more), by model, project, and task. npx codeburn项目地址https://gitcode.com/gh_mirrors/co/codeburn点击查看免费下载相关推荐CodeBurn 集成 OpenClaudeClaude Code 分支的 JSONL 会话解析与成本核算全解析CodeBurn 集成 OpenClaudeClaude Code 分支的 JSONL 会话解析与成本核算全解析 本文聚焦 CodeBurn 对 OpenClCodeBurn 解析 DroidFactory CLI会话JSONL 数据源、会话级 Token 均摊与成本核算实现详解CodeBurn 解析 DroidFactory CLI会话JSONL 数据源、会话级 Token 均摊与成本核算实现详解 Droid 是 FactoryCodeBurn Forge 提供器集成解析SQLite 会话扫描、成本核算与去重机制CodeBurn Forge 提供器集成解析SQLite 会话扫描、成本核算与去重机制 CodeBurn 是一款免费、本地运行、用于追踪 37 种 AI 编码创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表