Skip to content

Commit c9cd0ca

Browse files
committed
Updated README and CHANGELOG with recent modifications by Alorse
2 parents d4d97f3 + 0d1ad6d commit c9cd0ca

File tree

6 files changed

+384
-27
lines changed

6 files changed

+384
-27
lines changed

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,20 @@
2323

2424
## [3.21.1] - 2025-06-19
2525

26+
- Add LaTeX math equation rendering in chat window
27+
- Add toggle for excluding MCP server tools from the prompt (thanks @Rexarrior!)
28+
- Add symlink support to list_files tool
29+
- Fix marketplace blanking after populating
30+
- Fix recursive directory scanning in @ mention "Add Folder" functionality (thanks @village-way!)
31+
- Resolve phantom subtask display on cancel during API retry
32+
- Correct Gemini 2.5 Flash pricing (thanks @daniel-lxs!)
33+
- Resolve marketplace timeout issues and display installed MCPs (thanks @daniel-lxs!)
34+
- Onboarding tweaks to emphasize modes (thanks @brunobergher!)
35+
- Rename 'Boomerang Tasks' to 'Task Orchestration' for clarity
36+
- Remove command execution from attempt_completion
37+
- Fix markdown for links followed by punctuation (thanks @xyOz-dev!)
38+
39+
## [3.21.1] - 2025-06-19
2640
- Modified chat component to improve API model name display.
2741
- Implemented on-demand configuration fetching and caching.
2842
- Updated UI styling for consistency and enhanced visual design.

src/api/providers/fetchers/__tests__/ollama.test.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,31 @@ describe("Ollama Fetcher", () => {
3131
description: "Family: qwen3, Context: 40960, Size: 32.8B",
3232
})
3333
})
34+
35+
it("should handle models with null families field", () => {
36+
const modelDataWithNullFamilies = {
37+
...ollamaModelsData["qwen3-2to16:latest"],
38+
details: {
39+
...ollamaModelsData["qwen3-2to16:latest"].details,
40+
families: null,
41+
},
42+
}
43+
44+
const parsedModel = parseOllamaModel(modelDataWithNullFamilies as any)
45+
46+
expect(parsedModel).toEqual({
47+
maxTokens: 40960,
48+
contextWindow: 40960,
49+
supportsImages: false,
50+
supportsComputerUse: false,
51+
supportsPromptCache: true,
52+
inputPrice: 0,
53+
outputPrice: 0,
54+
cacheWritesPrice: 0,
55+
cacheReadsPrice: 0,
56+
description: "Family: qwen3, Context: 40960, Size: 32.8B",
57+
})
58+
})
3459
})
3560

3661
describe("getOllamaModels", () => {
@@ -129,5 +154,69 @@ describe("Ollama Fetcher", () => {
129154

130155
consoleInfoSpy.mockRestore() // Restore original console.info
131156
})
157+
158+
it("should handle models with null families field in API response", async () => {
159+
const baseUrl = "http://localhost:11434"
160+
const modelName = "test-model:latest"
161+
162+
const mockApiTagsResponse = {
163+
models: [
164+
{
165+
name: modelName,
166+
model: modelName,
167+
modified_at: "2025-06-03T09:23:22.610222878-04:00",
168+
size: 14333928010,
169+
digest: "6a5f0c01d2c96c687d79e32fdd25b87087feb376bf9838f854d10be8cf3c10a5",
170+
details: {
171+
family: "llama",
172+
families: null, // This is the case we're testing
173+
format: "gguf",
174+
parameter_size: "23.6B",
175+
parent_model: "",
176+
quantization_level: "Q4_K_M",
177+
},
178+
},
179+
],
180+
}
181+
const mockApiShowResponse = {
182+
license: "Mock License",
183+
modelfile: "FROM /path/to/blob\nTEMPLATE {{ .Prompt }}",
184+
parameters: "num_ctx 4096\nstop_token <eos>",
185+
template: "{{ .System }}USER: {{ .Prompt }}ASSISTANT:",
186+
modified_at: "2025-06-03T09:23:22.610222878-04:00",
187+
details: {
188+
parent_model: "",
189+
format: "gguf",
190+
family: "llama",
191+
families: null, // This is the case we're testing
192+
parameter_size: "23.6B",
193+
quantization_level: "Q4_K_M",
194+
},
195+
model_info: {
196+
"ollama.context_length": 4096,
197+
"some.other.info": "value",
198+
},
199+
capabilities: ["completion"],
200+
}
201+
202+
mockedAxios.get.mockResolvedValueOnce({ data: mockApiTagsResponse })
203+
mockedAxios.post.mockResolvedValueOnce({ data: mockApiShowResponse })
204+
205+
const result = await getOllamaModels(baseUrl)
206+
207+
expect(mockedAxios.get).toHaveBeenCalledTimes(1)
208+
expect(mockedAxios.get).toHaveBeenCalledWith(`${baseUrl}/api/tags`)
209+
210+
expect(mockedAxios.post).toHaveBeenCalledTimes(1)
211+
expect(mockedAxios.post).toHaveBeenCalledWith(`${baseUrl}/api/show`, { model: modelName })
212+
213+
expect(typeof result).toBe("object")
214+
expect(result).not.toBeInstanceOf(Array)
215+
expect(Object.keys(result).length).toBe(1)
216+
expect(result[modelName]).toBeDefined()
217+
218+
// Verify the model was parsed correctly despite null families
219+
expect(result[modelName].description).toBe("Family: llama, Context: 4096, Size: 23.6B")
220+
})
132221
})
133222
})

src/api/providers/fetchers/ollama.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,26 @@ import { z } from "zod"
44

55
const OllamaModelDetailsSchema = z.object({
66
family: z.string(),
7-
families: z.array(z.string()),
8-
format: z.string(),
7+
families: z.array(z.string()).nullable().optional(),
8+
format: z.string().optional(),
99
parameter_size: z.string(),
10-
parent_model: z.string(),
11-
quantization_level: z.string(),
10+
parent_model: z.string().optional(),
11+
quantization_level: z.string().optional(),
1212
})
1313

1414
const OllamaModelSchema = z.object({
1515
details: OllamaModelDetailsSchema,
16-
digest: z.string(),
16+
digest: z.string().optional(),
1717
model: z.string(),
18-
modified_at: z.string(),
18+
modified_at: z.string().optional(),
1919
name: z.string(),
20-
size: z.number(),
20+
size: z.number().optional(),
2121
})
2222

2323
const OllamaModelInfoResponseSchema = z.object({
24-
modelfile: z.string(),
25-
parameters: z.string(),
26-
template: z.string(),
24+
modelfile: z.string().optional(),
25+
parameters: z.string().optional(),
26+
template: z.string().optional(),
2727
details: OllamaModelDetailsSchema,
2828
model_info: z.record(z.string(), z.any()),
2929
capabilities: z.array(z.string()).optional(),

src/integrations/editor/DiffViewProvider.ts

Lines changed: 34 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { Task } from "../../core/task/Task"
1515
import { DecorationController } from "./DecorationController"
1616

1717
export const DIFF_VIEW_URI_SCHEME = "cline-diff"
18+
export const DIFF_VIEW_LABEL_CHANGES = "Original ↔ Roo's Changes"
1819

1920
// TODO: https://github.com/cline/cline/pull/3354
2021
export class DiffViewProvider {
@@ -384,12 +385,25 @@ export class DiffViewProvider {
384385
private async closeAllDiffViews(): Promise<void> {
385386
const closeOps = vscode.window.tabGroups.all
386387
.flatMap((group) => group.tabs)
387-
.filter(
388-
(tab) =>
388+
.filter((tab) => {
389+
// Check for standard diff views with our URI scheme
390+
if (
389391
tab.input instanceof vscode.TabInputTextDiff &&
390392
tab.input.original.scheme === DIFF_VIEW_URI_SCHEME &&
391-
!tab.isDirty,
392-
)
393+
!tab.isDirty
394+
) {
395+
return true
396+
}
397+
398+
// Also check by tab label for our specific diff views
399+
// This catches cases where the diff view might be created differently
400+
// when files are pre-opened as text documents
401+
if (tab.label.includes(DIFF_VIEW_LABEL_CHANGES) && !tab.isDirty) {
402+
return true
403+
}
404+
405+
return false
406+
})
393407
.map((tab) =>
394408
vscode.window.tabGroups.close(tab).then(
395409
() => undefined,
@@ -487,17 +501,22 @@ export class DiffViewProvider {
487501
}),
488502
)
489503

490-
// Execute the diff command
491-
vscode.commands
492-
.executeCommand(
493-
"vscode.diff",
494-
vscode.Uri.parse(`${DIFF_VIEW_URI_SCHEME}:${fileName}`).with({
495-
query: Buffer.from(this.originalContent ?? "").toString("base64"),
496-
}),
497-
uri,
498-
`${fileName}: ${fileExists ? "Original ↔ Roo's Changes" : "New File"} (Editable)`,
499-
{ preserveFocus: true },
500-
)
504+
// Pre-open the file as a text document to ensure it doesn't open in preview mode
505+
// This fixes issues with files that have custom editor associations (like markdown preview)
506+
vscode.window
507+
.showTextDocument(uri, { preview: false, viewColumn: vscode.ViewColumn.Active })
508+
.then(() => {
509+
// Execute the diff command after ensuring the file is open as text
510+
return vscode.commands.executeCommand(
511+
"vscode.diff",
512+
vscode.Uri.parse(`${DIFF_VIEW_URI_SCHEME}:${fileName}`).with({
513+
query: Buffer.from(this.originalContent ?? "").toString("base64"),
514+
}),
515+
uri,
516+
`${fileName}: ${fileExists ? `${DIFF_VIEW_LABEL_CHANGES}` : "New File"} (Editable)`,
517+
{ preserveFocus: true },
518+
)
519+
})
501520
.then(
502521
() => {
503522
// Command executed successfully, now wait for the editor to appear

0 commit comments

Comments
 (0)