Skip to content

Commit 1476bd0

Browse files
test(sync): compare copilot ide shadow parity
VS Code Copilot and Visual Studio Copilot are already opted into shadow comparison on this branch, but provider method tests alone do not prove the migration path still matches the legacy parser output consumed by sync. Cover the workspace-backed VS Code JSONL source and Visual Studio virtual trace source through ObserveProviderSource so reviewers can see provider observation, data-version planning, and legacy parser parity in one place. Validation: go test -tags "fts5" ./internal/parser ./internal/sync -run 'TestObserveProviderSourceMatches(VSCodeCopilot|VisualStudioCopilot)LegacyParser|TestCopilotIDEProvider|Test(VSCodeCopilotProvider|VisualStudioCopilotProvider)' -count=1; go test -tags "fts5" ./internal/parser ./internal/sync -count=1; go fmt ./...; go vet ./...; ./custom-gcl run --config .golangci.nilaway.yml ./internal/parser/... ./internal/sync/...; git diff --check
1 parent 805a91d commit 1476bd0

1 file changed

Lines changed: 137 additions & 0 deletions

File tree

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
package sync
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"path/filepath"
7+
"strings"
8+
"testing"
9+
10+
"github.com/stretchr/testify/assert"
11+
"github.com/stretchr/testify/require"
12+
13+
"go.kenn.io/agentsview/internal/parser"
14+
)
15+
16+
func TestObserveProviderSourceMatchesVSCodeCopilotLegacyParser(t *testing.T) {
17+
root := t.TempDir()
18+
sessionID := "vscode-shadow"
19+
hashDir := filepath.Join(root, "workspaceStorage", "workspace-hash")
20+
chatDir := filepath.Join(hashDir, "chatSessions")
21+
sourcePath := filepath.Join(chatDir, sessionID+".jsonl")
22+
writeProviderShadowSourceFile(
23+
t,
24+
filepath.Join(hashDir, "workspace.json"),
25+
`{"folder":"file:///Users/alice/code/copilot-app"}`,
26+
)
27+
writeProviderShadowSourceFile(t, sourcePath, vscodeCopilotShadowFixture(sessionID))
28+
29+
provider, ok := parser.NewProvider(parser.AgentVSCodeCopilot, parser.ProviderConfig{
30+
Roots: []string{root},
31+
Machine: "devbox",
32+
})
33+
require.True(t, ok)
34+
sources, err := provider.Discover(context.Background())
35+
require.NoError(t, err)
36+
require.Len(t, sources, 1)
37+
38+
legacySession, legacyMessages, err := parser.ParseVSCodeCopilotSession(
39+
sourcePath, "copilot-app", "devbox",
40+
)
41+
require.NoError(t, err)
42+
require.NotNil(t, legacySession)
43+
44+
observation, err := ObserveProviderSource(context.Background(), provider, ProviderObserveRequest{
45+
Source: sources[0],
46+
Machine: "devbox",
47+
})
48+
require.NoError(t, err)
49+
require.Len(t, observation.Results, 1)
50+
legacySession.File.Hash = observation.Fingerprint.Hash
51+
52+
assert.Equal(t, *legacySession, observation.Results[0].Session)
53+
assert.Equal(t, legacyMessages, observation.Results[0].Messages)
54+
assert.Equal(t, []string{legacySession.ID}, observation.Planned.DataVersionSessionIDs())
55+
assert.Empty(t, observation.Planned.Diagnostics)
56+
}
57+
58+
func TestObserveProviderSourceMatchesVisualStudioCopilotLegacyParser(t *testing.T) {
59+
root := t.TempDir()
60+
conversationID := "4a8f63f6-7626-4416-a874-fc7bd2c3f005"
61+
tracePath := filepath.Join(
62+
root,
63+
"20260612T194439_257709a3_VSGitHubCopilot_traces.jsonl",
64+
)
65+
writeProviderShadowSourceFile(
66+
t,
67+
tracePath,
68+
visualStudioCopilotShadowFixture(conversationID),
69+
)
70+
virtualPath := parser.VisualStudioCopilotVirtualPath(tracePath, conversationID)
71+
72+
provider, ok := parser.NewProvider(parser.AgentVSCopilot, parser.ProviderConfig{
73+
Roots: []string{root},
74+
Machine: "devbox",
75+
})
76+
require.True(t, ok)
77+
sources, err := provider.Discover(context.Background())
78+
require.NoError(t, err)
79+
require.Len(t, sources, 1)
80+
81+
legacySession, legacyMessages, err := parser.ParseVisualStudioCopilotSession(
82+
virtualPath, "visualstudio", "devbox",
83+
)
84+
require.NoError(t, err)
85+
require.NotNil(t, legacySession)
86+
87+
observation, err := ObserveProviderSource(context.Background(), provider, ProviderObserveRequest{
88+
Source: sources[0],
89+
Machine: "devbox",
90+
})
91+
require.NoError(t, err)
92+
require.Len(t, observation.Results, 1)
93+
legacySession.File.Hash = observation.Fingerprint.Hash
94+
95+
assert.Equal(t, *legacySession, observation.Results[0].Session)
96+
assert.Equal(t, legacyMessages, observation.Results[0].Messages)
97+
assert.Equal(t, []string{legacySession.ID}, observation.Planned.DataVersionSessionIDs())
98+
assert.Empty(t, observation.Planned.Diagnostics)
99+
}
100+
101+
func vscodeCopilotShadowFixture(sessionID string) string {
102+
return strings.Join([]string{
103+
`{"kind":0,"v":{"version":3,"sessionId":"` + sessionID + `","creationDate":1770650022790,"requests":[]}}`,
104+
`{"kind":2,"k":["requests"],"v":[{"requestId":"req1","timestamp":1770650031889,"message":{"text":"Hello VS Code","parts":[]},"response":[{"value":"Hi from VS Code"}],"modelId":"copilot/gpt-4o"}]}`,
105+
}, "\n") + "\n"
106+
}
107+
108+
func visualStudioCopilotShadowFixture(conversationID string) string {
109+
return visualStudioCopilotShadowTraceLineJSON(conversationID,
110+
"chat gpt-5.5", "1781293600000000000", "1781293610000000000",
111+
map[string]string{
112+
"gen_ai.operation.name": "chat",
113+
"gen_ai.input.messages": `[{"role":"user","parts":[{"type":"text","content":"Update the XAML."}]}]`,
114+
}) + "\n"
115+
}
116+
117+
func visualStudioCopilotShadowTraceLineJSON(
118+
conversationID, name, start, end string,
119+
attrs map[string]string,
120+
) string {
121+
allAttrs := []string{
122+
`{"key":"gen_ai.conversation.id","value":{"stringValue":"` +
123+
conversationID + `"}}`,
124+
}
125+
for key, value := range attrs {
126+
encoded, _ := json.Marshal(value)
127+
allAttrs = append(allAttrs,
128+
`{"key":"`+key+`","value":{"stringValue":`+
129+
string(encoded)+`}}`,
130+
)
131+
}
132+
return `{"resourceSpans":[{"scopeSpans":[{"spans":[{"traceId":"trace","spanId":"span","name":"` +
133+
name + `","startTimeUnixNano":"` + start +
134+
`","endTimeUnixNano":"` + end +
135+
`","attributes":[` + strings.Join(allAttrs, ",") +
136+
`] }]}]}]}`
137+
}

0 commit comments

Comments
 (0)