Skip to content

Commit b78217d

Browse files
benashbyBen Ashby
authored andcommitted
fix(qdrant): resolve URL port handling bug for HTTPS URLs (RooCodeInc#4992)
Co-authored-by: Ben Ashby <[email protected]>
2 parents 6ab652f + 9bf31d3 commit b78217d

File tree

202 files changed

+6316
-961
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

202 files changed

+6316
-961
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# JSON File Writing Must Be Atomic
2+
3+
- You MUST use `safeWriteJson(filePath: string, data: any): Promise<void>` from `src/utils/safeWriteJson.ts` instead of `JSON.stringify` with file-write operations
4+
- `safeWriteJson` will create parent directories if necessary, so do not call `mkdir` prior to `safeWriteJson`
5+
- `safeWriteJson` prevents data corruption via atomic writes with locking and streams the write to minimize memory footprint
6+
- Test files are exempt from this rule

.roo/rules-pr-reviewer/1_workflow.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@
100100
</arguments>
101101
</use_mcp_tool>
102102

103-
Examine existing PR comments to understand the current state of discussion. Always verify whether a comment is current or already addressed before suggesting action.
103+
Examine existing PR comments to understand the current state of discussion. When reading the comments and reviews, you must verify which are resolved by reading the files they refer to, since they might already be resolved. This prevents you from making redundant suggestions.
104104
</instructions>
105105
</step>
106106

.roo/rules-pr-reviewer/2_best_practices.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
- Always fetch and review the entire PR diff before commenting
33
- Check for and review any associated issue for context
44
- Check out the PR locally for better context understanding
5-
- Review existing comments to avoid duplicate feedback
5+
- Review existing comments and verify against the current code to avoid redundant feedback on already resolved issues
66
- Focus on the changes made, not unrelated code
77
- Ensure all changes are directly related to the linked issue
88
- Use a friendly, curious tone in all comments

.roo/rules-pr-reviewer/3_common_mistakes_to_avoid.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
- Using markdown headings (###, ##, #) in review comments
88
- Using excessive markdown formatting when plain text would suffice
99
- Submitting comments without user preview/approval
10-
- Ignoring existing PR comments and discussions
10+
- Ignoring existing PR comments or failing to verify if they have already been resolved by checking the code
1111
- Forgetting to check for an associated issue for additional context
1212
- Missing critical security or performance issues
1313
- Not checking for proper i18n in UI changes

.roo/rules-translate/001-general-rules.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,10 @@
6464
1. Identify where the string appears in the UI/codebase
6565
2. Understand the context and purpose of the string
6666
3. Update English translation first
67-
4. Create appropriate translations for all other supported languages
68-
5. Validate your changes with the missing translations script
67+
4. Use the `<search_files>` tool to find JSON keys that are near new keys in English translations but do not yet exist in the other language files for `<apply_diff>` SEARCH context
68+
5. Create appropriate translations for all other supported languages utilizing the `search_files` result using `<apply_diff>` without reading every file.
69+
6. Do not output the translated text into the chat, just modify the files.
70+
7. Validate your changes with the missing translations script
6971
- Flag or comment if an English source string is incomplete ("please see this...") to avoid truncated or unclear translations
7072
- For UI elements, distinguish between:
7173
- Button labels: Use short imperative commands ("Save", "Cancel")

CHANGELOG.md

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,35 @@
11
# CHANGELOG
22

3+
## [3.22.1] - 2025-06-26
4+
5+
- Add Gemini CLI provider (thanks Cline!)
6+
- Fix undefined mcp command (thanks @qdaxb!)
7+
- Use upstream_inference_cost for OpenRouter BYOK cost calculation and show cached token count (thanks @chrarnoldus!)
8+
- Update maxTokens value for qwen/qwen3-32b model on Groq (thanks @KanTakahiro!)
9+
- Standardize tooltip delays to 300ms
10+
11+
## [3.22.0] - 2025-06-25
12+
13+
- Add 1-click task sharing
14+
- Add support for loading rules from a global .roo directory (thanks @samhvw8!)
15+
- Modes selector improvements (thanks @brunobergher!)
16+
- Use safeWriteJson for all JSON file writes to avoid task history corruption (thanks @KJ7LNW!)
17+
- Improve YAML error handling when editing modes
18+
- Register importSettings as VSCode command (thanks @shivamd1810!)
19+
- Add default task names for empty tasks (thanks @daniel-lxs!)
20+
- Improve translation workflow to avoid unnecessary file reads (thanks @KJ7LNW!)
21+
- Allow write_to_file to handle newline-only and empty content (thanks @Githubguy132010!)
22+
- Address multiple memory leaks in CodeBlock component (thanks @kiwina!)
23+
- Memory cleanup (thanks @xyOz-dev!)
24+
- Fix port handling bug in code indexing for HTTPS URLs (thanks @benashby!)
25+
- Improve Bedrock error handling for throttling and streaming contexts
26+
- Handle long Claude code messages (thanks @daniel-lxs!)
27+
- Fixes to Claude Code caching and image upload
28+
- Disable reasoning budget UI controls for Claude Code provider
29+
- Remove temperature parameter for Azure OpenAI reasoning models (thanks @ExactDoug!)
30+
- Allowed commands import/export (thanks @catrielmuller!)
31+
- Add VS Code setting to disable quick fix context actions (thanks @OlegOAndreev!)
32+
333
## [3.21.5] - 2025-06-23
434

535
- Fix Qdrant URL prefix handling for QdrantClient initialization (thanks @CW-B-W!)

packages/telemetry/src/BaseTelemetryClient.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,21 @@ export abstract class BaseTelemetryClient implements TelemetryClient {
2525
: !this.subscription.events.includes(eventName)
2626
}
2727

28+
/**
29+
* Determines if a specific property should be included in telemetry events
30+
* Override in subclasses to filter specific properties
31+
*/
32+
protected isPropertyCapturable(_propertyName: string): boolean {
33+
return true
34+
}
35+
2836
protected async getEventProperties(event: TelemetryEvent): Promise<TelemetryEvent["properties"]> {
2937
let providerProperties: TelemetryEvent["properties"] = {}
3038
const provider = this.providerRef?.deref()
3139

3240
if (provider) {
3341
try {
34-
// Get the telemetry properties directly from the provider.
42+
// Get properties from the provider
3543
providerProperties = await provider.getTelemetryProperties()
3644
} catch (error) {
3745
// Log error but continue with capturing the event.
@@ -43,7 +51,10 @@ export abstract class BaseTelemetryClient implements TelemetryClient {
4351

4452
// Merge provider properties with event-specific properties.
4553
// Event properties take precedence in case of conflicts.
46-
return { ...providerProperties, ...(event.properties || {}) }
54+
const mergedProperties = { ...providerProperties, ...(event.properties || {}) }
55+
56+
// Filter out properties that shouldn't be captured by this client
57+
return Object.fromEntries(Object.entries(mergedProperties).filter(([key]) => this.isPropertyCapturable(key)))
4758
}
4859

4960
public abstract capture(event: TelemetryEvent): Promise<void>

packages/telemetry/src/PostHogTelemetryClient.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import { BaseTelemetryClient } from "./BaseTelemetryClient"
1313
export class PostHogTelemetryClient extends BaseTelemetryClient {
1414
private client: PostHog
1515
private distinctId: string = vscode.env.machineId
16+
// Git repository properties that should be filtered out
17+
private readonly gitPropertyNames = ["repositoryUrl", "repositoryName", "defaultBranch"]
1618

1719
constructor(debug = false) {
1820
super(
@@ -26,6 +28,19 @@ export class PostHogTelemetryClient extends BaseTelemetryClient {
2628
this.client = new PostHog(process.env.POSTHOG_API_KEY || "", { host: "https://us.i.posthog.com" })
2729
}
2830

31+
/**
32+
* Filter out git repository properties for PostHog telemetry
33+
* @param propertyName The property name to check
34+
* @returns Whether the property should be included in telemetry events
35+
*/
36+
protected override isPropertyCapturable(propertyName: string): boolean {
37+
// Filter out git repository properties
38+
if (this.gitPropertyNames.includes(propertyName)) {
39+
return false
40+
}
41+
return true
42+
}
43+
2944
public override async capture(event: TelemetryEvent): Promise<void> {
3045
if (!this.isTelemetryEnabled() || !this.isEventCapturable(event.event)) {
3146
if (this.debug) {

packages/telemetry/src/__tests__/PostHogTelemetryClient.test.ts

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,29 @@ describe("PostHogTelemetryClient", () => {
7070
})
7171
})
7272

73+
describe("isPropertyCapturable", () => {
74+
it("should filter out git repository properties", () => {
75+
const client = new PostHogTelemetryClient()
76+
77+
const isPropertyCapturable = getPrivateProperty<(propertyName: string) => boolean>(
78+
client,
79+
"isPropertyCapturable",
80+
).bind(client)
81+
82+
// Git properties should be filtered out
83+
expect(isPropertyCapturable("repositoryUrl")).toBe(false)
84+
expect(isPropertyCapturable("repositoryName")).toBe(false)
85+
expect(isPropertyCapturable("defaultBranch")).toBe(false)
86+
87+
// Other properties should be included
88+
expect(isPropertyCapturable("appVersion")).toBe(true)
89+
expect(isPropertyCapturable("vscodeVersion")).toBe(true)
90+
expect(isPropertyCapturable("platform")).toBe(true)
91+
expect(isPropertyCapturable("mode")).toBe(true)
92+
expect(isPropertyCapturable("customProperty")).toBe(true)
93+
})
94+
})
95+
7396
describe("getEventProperties", () => {
7497
it("should merge provider properties with event properties", async () => {
7598
const client = new PostHogTelemetryClient()
@@ -112,6 +135,54 @@ describe("PostHogTelemetryClient", () => {
112135
expect(mockProvider.getTelemetryProperties).toHaveBeenCalledTimes(1)
113136
})
114137

138+
it("should filter out git repository properties", async () => {
139+
const client = new PostHogTelemetryClient()
140+
141+
const mockProvider: TelemetryPropertiesProvider = {
142+
getTelemetryProperties: vi.fn().mockResolvedValue({
143+
appVersion: "1.0.0",
144+
vscodeVersion: "1.60.0",
145+
platform: "darwin",
146+
editorName: "vscode",
147+
language: "en",
148+
mode: "code",
149+
// Git properties that should be filtered out
150+
repositoryUrl: "https://github.com/example/repo",
151+
repositoryName: "example/repo",
152+
defaultBranch: "main",
153+
}),
154+
}
155+
156+
client.setProvider(mockProvider)
157+
158+
const getEventProperties = getPrivateProperty<
159+
(event: { event: TelemetryEventName; properties?: Record<string, any> }) => Promise<Record<string, any>>
160+
>(client, "getEventProperties").bind(client)
161+
162+
const result = await getEventProperties({
163+
event: TelemetryEventName.TASK_CREATED,
164+
properties: {
165+
customProp: "value",
166+
},
167+
})
168+
169+
// Git properties should be filtered out
170+
expect(result).not.toHaveProperty("repositoryUrl")
171+
expect(result).not.toHaveProperty("repositoryName")
172+
expect(result).not.toHaveProperty("defaultBranch")
173+
174+
// Other properties should be included
175+
expect(result).toEqual({
176+
appVersion: "1.0.0",
177+
vscodeVersion: "1.60.0",
178+
platform: "darwin",
179+
editorName: "vscode",
180+
language: "en",
181+
mode: "code",
182+
customProp: "value",
183+
})
184+
})
185+
115186
it("should handle errors from provider gracefully", async () => {
116187
const client = new PostHogTelemetryClient()
117188

@@ -211,6 +282,48 @@ describe("PostHogTelemetryClient", () => {
211282
}),
212283
})
213284
})
285+
286+
it("should filter out git repository properties when capturing events", async () => {
287+
const client = new PostHogTelemetryClient()
288+
client.updateTelemetryState(true)
289+
290+
const mockProvider: TelemetryPropertiesProvider = {
291+
getTelemetryProperties: vi.fn().mockResolvedValue({
292+
appVersion: "1.0.0",
293+
vscodeVersion: "1.60.0",
294+
platform: "darwin",
295+
editorName: "vscode",
296+
language: "en",
297+
mode: "code",
298+
// Git properties that should be filtered out
299+
repositoryUrl: "https://github.com/example/repo",
300+
repositoryName: "example/repo",
301+
defaultBranch: "main",
302+
}),
303+
}
304+
305+
client.setProvider(mockProvider)
306+
307+
await client.capture({
308+
event: TelemetryEventName.TASK_CREATED,
309+
properties: { test: "value" },
310+
})
311+
312+
expect(mockPostHogClient.capture).toHaveBeenCalledWith({
313+
distinctId: "test-machine-id",
314+
event: TelemetryEventName.TASK_CREATED,
315+
properties: expect.objectContaining({
316+
appVersion: "1.0.0",
317+
test: "value",
318+
}),
319+
})
320+
321+
// Verify git properties are not included
322+
const captureCall = mockPostHogClient.capture.mock.calls[0][0]
323+
expect(captureCall.properties).not.toHaveProperty("repositoryUrl")
324+
expect(captureCall.properties).not.toHaveProperty("repositoryName")
325+
expect(captureCall.properties).not.toHaveProperty("defaultBranch")
326+
})
214327
})
215328

216329
describe("updateTelemetryState", () => {

packages/types/src/provider-settings.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export const providerNames = [
1919
"vscode-lm",
2020
"lmstudio",
2121
"gemini",
22+
"gemini-cli",
2223
"openai-native",
2324
"mistral",
2425
"deepseek",
@@ -158,6 +159,11 @@ const geminiSchema = apiModelIdProviderModelSchema.extend({
158159
googleGeminiBaseUrl: z.string().optional(),
159160
})
160161

162+
const geminiCliSchema = apiModelIdProviderModelSchema.extend({
163+
geminiCliOAuthPath: z.string().optional(),
164+
geminiCliProjectId: z.string().optional(),
165+
})
166+
161167
const openAiNativeSchema = apiModelIdProviderModelSchema.extend({
162168
openAiNativeApiKey: z.string().optional(),
163169
openAiNativeBaseUrl: z.string().optional(),
@@ -223,6 +229,7 @@ export const providerSettingsSchemaDiscriminated = z.discriminatedUnion("apiProv
223229
vsCodeLmSchema.merge(z.object({ apiProvider: z.literal("vscode-lm") })),
224230
lmStudioSchema.merge(z.object({ apiProvider: z.literal("lmstudio") })),
225231
geminiSchema.merge(z.object({ apiProvider: z.literal("gemini") })),
232+
geminiCliSchema.merge(z.object({ apiProvider: z.literal("gemini-cli") })),
226233
openAiNativeSchema.merge(z.object({ apiProvider: z.literal("openai-native") })),
227234
mistralSchema.merge(z.object({ apiProvider: z.literal("mistral") })),
228235
deepSeekSchema.merge(z.object({ apiProvider: z.literal("deepseek") })),
@@ -250,6 +257,7 @@ export const providerSettingsSchema = z.object({
250257
...vsCodeLmSchema.shape,
251258
...lmStudioSchema.shape,
252259
...geminiSchema.shape,
260+
...geminiCliSchema.shape,
253261
...openAiNativeSchema.shape,
254262
...mistralSchema.shape,
255263
...deepSeekSchema.shape,

0 commit comments

Comments
 (0)