From cf85ab670726e35ebdb159c9e411414e79cdb13a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Nov 2026 08:53:46 +0000 Subject: [PATCH 1/2] Initial plan From 2d2968b9624e7e49152970df8ca0c0ecd5e52e62 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Nov 2026 09:09:53 +0000 Subject: [PATCH 2/2] test: preserve Z.AI Anthropic-compatible token usage totals Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- actions/setup/js/parse_token_usage.test.cjs | 34 +++++++++++++++++++++ pkg/cli/token_usage_test.go | 24 +++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/actions/setup/js/parse_token_usage.test.cjs b/actions/setup/js/parse_token_usage.test.cjs index e865384826f..d7cdf730b99 100644 --- a/actions/setup/js/parse_token_usage.test.cjs +++ b/actions/setup/js/parse_token_usage.test.cjs @@ -421,6 +421,40 @@ describe("parse_token_usage", () => { }); }); + test("preserves Z.AI Anthropic-compatible usage in the detection summary and artifact", async () => { + process.env.GH_AW_TMP_DIR = tmpDir; + process.env.GH_AW_PHASE = "detection"; + const tokenUsagePath = path.join(tmpDir, "sandbox/firewall/logs/api-proxy-logs/token-usage.jsonl"); + fs.mkdirSync(path.dirname(tokenUsagePath), { recursive: true }); + // Synthetic normalized AWF record using the session totals from gh-aw#75271. + const record = { + event: "token_usage", + provider: "anthropic", + model: "glm-5.3-flash", + streaming: true, + input_tokens: 38719, + output_tokens: 4058, + cache_read_tokens: 112640, + cache_write_tokens: 0, + }; + const content = JSON.stringify(record) + "\n"; + fs.writeFileSync(tokenUsagePath, content); + + await main(path.join(tmpDir, "missing-session-state")); + + expect(mockCore.setFailed).not.toHaveBeenCalled(); + expect(JSON.parse(originalReadFileSync(path.join(tmpDir, "agent_usage.json"), "utf8"))).toMatchObject({ + primary_model: "glm-5.3-flash", + input_tokens: 38719, + output_tokens: 4058, + cache_read_tokens: 112640, + cache_write_tokens: 0, + }); + const markdown = mockCore.summary.addRaw.mock.calls[0][0]; + expect(markdown).toMatch(/\|\s*38,719\s*\|\s*4,058\s*\|\s*112,640\s*\|\s*0\s*\|/); + expect(originalReadFileSync(tokenUsagePath, "utf8")).toBe(content); + }); + test.each([ ["a malformed provider", "claude", "not a provider"], ["another native provider", "claude", "openai"], diff --git a/pkg/cli/token_usage_test.go b/pkg/cli/token_usage_test.go index f7f73925f44..5a88051ae71 100644 --- a/pkg/cli/token_usage_test.go +++ b/pkg/cli/token_usage_test.go @@ -46,6 +46,30 @@ func TestParseTokenUsageFile(t *testing.T) { assert.Equal(t, 200, model.OutputTokens, "model output tokens") }) + t.Run("Z.AI Anthropic-compatible usage", func(t *testing.T) { + filePath := filepath.Join(testutil.TempDir(t, "token-usage-zai"), "token-usage.jsonl") + // Synthetic normalized AWF record using the session totals from gh-aw#75271. + content := `{"event":"token_usage","provider":"anthropic","model":"glm-5.3-flash","streaming":true,"input_tokens":38719,"output_tokens":4058,"cache_read_tokens":112640,"cache_write_tokens":0}` + require.NoError(t, os.WriteFile(filePath, []byte(content+"\n"), 0o644)) + + summary, err := parseTokenUsageFile(filePath) + require.NoError(t, err) + require.NotNil(t, summary) + + assert.Equal(t, 38719, summary.TotalInputTokens) + assert.Equal(t, 4058, summary.TotalOutputTokens) + assert.Equal(t, 112640, summary.TotalCacheReadTokens) + assert.Zero(t, summary.TotalCacheWriteTokens) + assert.Equal(t, 155417, summary.TotalInputTokens+summary.TotalOutputTokens+summary.TotalCacheReadTokens) + require.Contains(t, summary.ByModel, "glm-5.3-flash") + model := summary.ByModel["glm-5.3-flash"] + assert.Equal(t, "anthropic", model.Provider) + assert.Equal(t, 38719, model.InputTokens) + assert.Equal(t, 4058, model.OutputTokens) + assert.Equal(t, 112640, model.CacheReadTokens) + assert.Zero(t, model.CacheWriteTokens) + }) + t.Run("multiple entries with multiple models", func(t *testing.T) { tmpDir := testutil.TempDir(t, "token-usage") filePath := filepath.Join(tmpDir, "token-usage.jsonl")