Skip to content

Commit 01c4271

Browse files
authored
fix: HttpContextProvider handle null uri field (#8197)
fix: Add null check for http-context-provider uri and add test for to check whether it works
1 parent f167868 commit 01c4271

File tree

2 files changed

+207
-1
lines changed

2 files changed

+207
-1
lines changed
Lines changed: 206 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,206 @@
1+
/**
2+
* Tests for HttpContextProvider - specifically testing the fix for v1.0.19
3+
* where missing or null uri fields in server responses caused TypeErrors.
4+
*
5+
* The fix uses conditional access (item.uri &&) to safely handle null/undefined uri fields.
6+
*/
7+
import { ContextProviderExtras } from "../../index.js";
8+
import HttpContextProvider from "./HttpContextProvider.js";
9+
10+
describe("HttpContextProvider", () => {
11+
let provider: HttpContextProvider;
12+
let mockExtras: ContextProviderExtras;
13+
14+
beforeEach(() => {
15+
provider = new HttpContextProvider({
16+
title: "Test HTTP Provider",
17+
url: "http://localhost:3000/context",
18+
});
19+
20+
mockExtras = {
21+
fullInput: "test input",
22+
fetch: jest.fn(),
23+
ide: {
24+
getCurrentFile: jest.fn().mockResolvedValue({ path: "/test/file.ts" }),
25+
getWorkspaceDirs: jest.fn().mockResolvedValue(["/test/"]),
26+
} as any,
27+
config: {} as any,
28+
embeddingsProvider: null,
29+
reranker: null,
30+
llm: {} as any,
31+
selectedCode: [],
32+
isInAgentMode: false,
33+
};
34+
});
35+
36+
describe("getContextItems", () => {
37+
it("should handle response with valid uri field", async () => {
38+
const mockResponse = {
39+
json: jest.fn().mockResolvedValue({
40+
description: "Test item",
41+
content: "Test content",
42+
name: "Test",
43+
uri: {
44+
type: "file",
45+
value: "/test/file.ts",
46+
},
47+
}),
48+
};
49+
50+
(mockExtras.fetch as jest.Mock).mockResolvedValue(mockResponse);
51+
52+
const result = await provider.getContextItems("test query", mockExtras);
53+
54+
expect(result).toHaveLength(1);
55+
expect(result[0]).toEqual({
56+
description: "Test item",
57+
content: "Test content",
58+
name: "Test",
59+
uri: {
60+
type: "file",
61+
value: "/test/file.ts",
62+
},
63+
});
64+
});
65+
66+
it("should handle response with null uri field", async () => {
67+
const mockResponse = {
68+
json: jest.fn().mockResolvedValue({
69+
description: "Test item",
70+
content: "Test content",
71+
name: "Test",
72+
uri: null,
73+
}),
74+
};
75+
76+
(mockExtras.fetch as jest.Mock).mockResolvedValue(mockResponse);
77+
78+
const result = await provider.getContextItems("test query", mockExtras);
79+
80+
expect(result).toHaveLength(1);
81+
expect(result[0]).toEqual({
82+
description: "Test item",
83+
content: "Test content",
84+
name: "Test",
85+
uri: null, // Should be null when uri is null (logical AND with null returns null)
86+
});
87+
});
88+
``;
89+
90+
it("should handle response with missing uri field", async () => {
91+
const mockResponse = {
92+
json: jest.fn().mockResolvedValue({
93+
description: "Test item",
94+
content: "Test content",
95+
name: "Test",
96+
// uri field is completely missing
97+
}),
98+
};
99+
100+
(mockExtras.fetch as jest.Mock).mockResolvedValue(mockResponse);
101+
102+
const result = await provider.getContextItems("test query", mockExtras);
103+
104+
expect(result).toHaveLength(1);
105+
expect(result[0]).toEqual({
106+
description: "Test item",
107+
content: "Test content",
108+
name: "Test",
109+
uri: undefined, // Should be undefined when uri is missing
110+
});
111+
});
112+
113+
it("should handle array response with mixed uri fields", async () => {
114+
const mockResponse = {
115+
json: jest.fn().mockResolvedValue([
116+
{
117+
description: "Item with uri",
118+
content: "Content 1",
119+
name: "Item1",
120+
uri: {
121+
type: "file",
122+
value: "/test/file1.ts",
123+
},
124+
},
125+
{
126+
description: "Item without uri",
127+
content: "Content 2",
128+
name: "Item2",
129+
// uri field missing
130+
},
131+
{
132+
description: "Item with null uri",
133+
content: "Content 3",
134+
name: "Item3",
135+
uri: null,
136+
},
137+
]),
138+
};
139+
140+
(mockExtras.fetch as jest.Mock).mockResolvedValue(mockResponse);
141+
142+
const result = await provider.getContextItems("test query", mockExtras);
143+
144+
expect(result).toHaveLength(3);
145+
expect(result[0].uri).toEqual({ type: "file", value: "/test/file1.ts" });
146+
expect(result[1].uri).toBeUndefined();
147+
expect(result[2].uri).toBeNull(); // null uri becomes null
148+
});
149+
150+
it("should use default values for missing fields", async () => {
151+
const mockResponse = {
152+
json: jest.fn().mockResolvedValue({
153+
// All fields missing except uri
154+
uri: {
155+
type: "file",
156+
value: "/test/file.ts",
157+
},
158+
}),
159+
};
160+
161+
(mockExtras.fetch as jest.Mock).mockResolvedValue(mockResponse);
162+
163+
const result = await provider.getContextItems("test query", mockExtras);
164+
165+
expect(result).toHaveLength(1);
166+
expect(result[0]).toEqual({
167+
description: "HTTP Context Item", // default value
168+
content: "", // default value
169+
name: "Test HTTP Provider", // from provider options
170+
uri: {
171+
type: "file",
172+
value: "/test/file.ts",
173+
},
174+
});
175+
});
176+
177+
it("should handle partial uri objects gracefully", async () => {
178+
const mockResponse = {
179+
json: jest.fn().mockResolvedValue({
180+
description: "Test item",
181+
content: "Test content",
182+
name: "Test",
183+
uri: {
184+
type: "file",
185+
// missing value field - our fix should handle this gracefully
186+
},
187+
}),
188+
};
189+
190+
(mockExtras.fetch as jest.Mock).mockResolvedValue(mockResponse);
191+
192+
const result = await provider.getContextItems("test query", mockExtras);
193+
194+
expect(result).toHaveLength(1);
195+
expect(result[0]).toEqual({
196+
description: "Test item",
197+
content: "Test content",
198+
name: "Test",
199+
uri: {
200+
type: "file",
201+
value: undefined, // value is undefined when missing
202+
},
203+
});
204+
});
205+
});
206+
});

core/context/providers/HttpContextProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ class HttpContextProvider extends BaseContextProvider {
7272
description: item.description ?? "HTTP Context Item",
7373
content: item.content ?? "",
7474
name: item.name ?? this.options.title ?? "HTTP",
75-
uri: {
75+
uri: item.uri && {
7676
type: item.uri.type,
7777
value: item.uri.value,
7878
},

0 commit comments

Comments
 (0)