(buf)
| 925 | * usage is not counted again. |
| 926 | */ |
| 927 | export function parseGeneratorMetadata(buf) { |
| 928 | const fields = parseFields(buf); |
| 929 | const metaEntries = getAllFields(fields, 1).filter(f => f.wireType === 2); |
| 930 | if (metaEntries.length === 0) return null; |
| 931 | |
| 932 | let inputTokens = 0, outputTokens = 0, cacheReadTokens = 0, cacheWriteTokens = 0; |
| 933 | let found = false; |
| 934 | |
| 935 | for (const entry of metaEntries) { |
| 936 | const gm = parseFields(entry.value); |
| 937 | const chatModelField = getField(gm, 1, 2); // chat_model |
| 938 | if (!chatModelField) continue; |
| 939 | const cm = parseFields(chatModelField.value); |
| 940 | const usageField = getField(cm, 4, 2); // usage |
| 941 | if (!usageField) continue; |
| 942 | const us = parseFields(usageField.value); |
| 943 | const readUint = (fn) => { |
| 944 | const f = getField(us, fn, 0); |
| 945 | return f ? Number(f.value) : 0; |
| 946 | }; |
| 947 | const inT = readUint(2); |
| 948 | const outT = readUint(3); |
| 949 | const cacheW = readUint(4); |
| 950 | const cacheR = readUint(5); |
| 951 | if (inT || outT || cacheW || cacheR) { |
| 952 | inputTokens += inT; |
| 953 | outputTokens += outT; |
| 954 | cacheWriteTokens += cacheW; |
| 955 | cacheReadTokens += cacheR; |
| 956 | found = true; |
| 957 | } |
| 958 | } |
| 959 | if (!found) return null; |
| 960 | return { |
| 961 | inputTokens, |
| 962 | outputTokens, |
| 963 | cacheReadTokens, |
| 964 | cacheWriteTokens, |
| 965 | entryCount: metaEntries.length, |
| 966 | }; |
| 967 | } |
| 968 | |
| 969 | // ─── Cascade response parsers ────────────────────────────── |
| 970 |
no test coverage detected