Skip to content

Commit 51c92d5

Browse files
authored
Merge branch 'Zoo-Code-Org:main' into main
2 parents fa6a59f + 6470431 commit 51c92d5

109 files changed

Lines changed: 4914 additions & 1080 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"zoo-code": patch
3+
---
4+
5+
Terminate the running command when a task is cancelled or torn down (#245). Pressing cancel (✕) now aborts the underlying terminal process instead of leaving it running while the terminal stays stuck "busy" until a manual kill.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"zoo-code": patch
3+
---
4+
5+
Detect when the "Google Cloud Credentials" Vertex field has been given a filesystem path instead of the raw JSON contents of a service-account key file. The runtime now skips JSON.parse for path-shaped input, logs a single specific console warning naming the sibling "Google Cloud Key File Path" field and `GOOGLE_APPLICATION_CREDENTIALS` env var, and the settings UI shows an inline warning under the field while the input still looks like a path. Auth behavior is unchanged for correctly-configured users.

.roo/commands/release.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ mode: code
2424

2525
4. Summarize the changes. If the user did not specify a release type, ask whether this should be a major, minor, or patch release.
2626

27+
- Before choosing the target release version, treat the nightly pre-release lane as separate from the stable lane.
28+
- Zoo Code nightlies should stay on `major.ODD_NUMBER.patch` and use a large patch number for CI-generated pre-releases.
29+
- Stable releases should stay on `major.EVEN_NUMBER.patch`.
30+
- When preparing a stable release after an odd-minor pre-release line, advance to the next even minor instead of reusing the odd-minor pre-release lane.
31+
2732
5. Review and update the Marketplace-facing root `README.md`.
2833

2934
- Treat root `README.md` as the source of truth for Marketplace content.

apps/vscode-e2e/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
"@roo-code/types": "workspace:^",
1818
"@copilotkit/aimock": "1.15.1",
1919
"@types/mocha": "^10.0.10",
20-
"@types/node": "20.x",
20+
"@types/node": "^20.19.25",
2121
"@types/vscode": "^1.95.0",
2222
"@vscode/test-cli": "^0.0.11",
2323
"@vscode/test-electron": "^2.4.0",

package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"@types/glob": "^9.0.0",
3535
"@types/node": "^24.1.0",
3636
"@vscode/vsce": "3.3.2",
37-
"esbuild": "^0.25.0",
37+
"esbuild": "0.28.0",
3838
"eslint": "^9.27.0",
3939
"glob": "^11.1.0",
4040
"husky": "^9.1.7",
@@ -60,7 +60,9 @@
6060
],
6161
"overrides": {
6262
"tar-fs": ">=3.1.1",
63-
"esbuild": ">=0.25.0",
63+
"esbuild": "0.28.0",
64+
"rollup": "4.60.4",
65+
"vite": "8.0.14",
6466
"undici": ">=5.29.0",
6567
"form-data": ">=4.0.4",
6668
"bluebird": ">=3.7.2",
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// npx vitest run packages/core/src/message-utils/__tests__/safeJsonParse.spec.ts
2+
3+
import { safeJsonParse } from "../safeJsonParse.js"
4+
5+
describe("safeJsonParse", () => {
6+
let consoleErrorSpy: ReturnType<typeof vi.spyOn>
7+
8+
beforeEach(() => {
9+
consoleErrorSpy = vi.spyOn(console, "error").mockImplementation(() => {})
10+
})
11+
12+
afterEach(() => {
13+
consoleErrorSpy.mockRestore()
14+
})
15+
16+
it("returns the parsed value for valid JSON", () => {
17+
expect(safeJsonParse<{ a: number }>('{"a":1}')).toEqual({ a: 1 })
18+
expect(consoleErrorSpy).not.toHaveBeenCalled()
19+
})
20+
21+
it("returns the default value for null, undefined, or empty input", () => {
22+
expect(safeJsonParse<string>(null, "fallback")).toBe("fallback")
23+
expect(safeJsonParse<string>(undefined, "fallback")).toBe("fallback")
24+
expect(safeJsonParse<string>("", "fallback")).toBe("fallback")
25+
expect(consoleErrorSpy).not.toHaveBeenCalled()
26+
})
27+
28+
it("returns the default value and logs the generic message when no context is given (backward compatible)", () => {
29+
const result = safeJsonParse<{ a: number }>("not json", undefined)
30+
expect(result).toBeUndefined()
31+
expect(consoleErrorSpy).toHaveBeenCalledTimes(1)
32+
const message = consoleErrorSpy.mock.calls[0]?.[0]
33+
expect(message).toBe("Error parsing JSON:")
34+
})
35+
36+
it("includes the context label in the error log when provided", () => {
37+
const result = safeJsonParse<{ a: number }>("not json", undefined, "foo")
38+
expect(result).toBeUndefined()
39+
expect(consoleErrorSpy).toHaveBeenCalledTimes(1)
40+
const message = consoleErrorSpy.mock.calls[0]?.[0]
41+
expect(message).toBe("Error parsing JSON (foo):")
42+
})
43+
})

packages/core/src/message-utils/safeJsonParse.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,16 @@
33
*
44
* @param jsonString The string to parse
55
* @param defaultValue Value to return if parsing fails
6+
* @param context Optional label included in the error log so callers can be
7+
* identified when something other than valid JSON is supplied (e.g. a user
8+
* pasting a file path into a JSON field).
69
* @returns Parsed JSON object or defaultValue if parsing fails
710
*/
8-
export function safeJsonParse<T>(jsonString: string | null | undefined, defaultValue?: T): T | undefined {
11+
export function safeJsonParse<T>(
12+
jsonString: string | null | undefined,
13+
defaultValue?: T,
14+
context?: string,
15+
): T | undefined {
916
if (!jsonString) {
1017
return defaultValue
1118
}
@@ -14,7 +21,7 @@ export function safeJsonParse<T>(jsonString: string | null | undefined, defaultV
1421
return JSON.parse(jsonString) as T
1522
} catch (error) {
1623
// Log the error to the console for debugging.
17-
console.error("Error parsing JSON:", error)
24+
console.error(`Error parsing JSON${context ? ` (${context})` : ""}:`, error)
1825
return defaultValue
1926
}
2027
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// npx vitest run src/__tests__/looksLikeFilePath.spec.ts
2+
3+
import { looksLikeFilePath } from "../utils/looksLikeFilePath.js"
4+
5+
describe("looksLikeFilePath", () => {
6+
describe("nullish, empty, and whitespace-only input", () => {
7+
it.each([
8+
["undefined", undefined],
9+
["null", null],
10+
["empty string", ""],
11+
["whitespace only", " \t\n "],
12+
])("returns false for %s", (_label, value) => {
13+
expect(looksLikeFilePath(value)).toBe(false)
14+
})
15+
})
16+
17+
describe("path-shaped input", () => {
18+
it.each([
19+
["Windows backslash path", "C:\\Users\\dev\\sa.json"],
20+
["Windows forward-slash path", "C:/Users/dev/sa.json"],
21+
["Windows drive lowercase", "d:\\creds.json"],
22+
["POSIX absolute path", "/home/dev/sa.json"],
23+
["POSIX absolute root /tmp", "/tmp/creds.json"],
24+
["POSIX home path", "~/sa.json"],
25+
["POSIX relative ./", "./sa.json"],
26+
["POSIX relative ../", "../secrets/sa.json"],
27+
])("returns true for %s", (_label, value) => {
28+
expect(looksLikeFilePath(value)).toBe(true)
29+
})
30+
31+
it("returns true after trimming surrounding whitespace", () => {
32+
expect(looksLikeFilePath(" /tmp/creds.json ")).toBe(true)
33+
expect(looksLikeFilePath("\tC:\\sa.json\n")).toBe(true)
34+
})
35+
})
36+
37+
describe("JSON-shaped or bare-token input", () => {
38+
it.each([
39+
["JSON object", '{"type":"service_account","client_email":"x@y.z"}'],
40+
["JSON array", "[1,2,3]"],
41+
["JSON with leading whitespace", ' {"type":"service_account"}'],
42+
["bare token", "not-json-and-not-a-path"],
43+
["service-account-style email", "sa@project.iam.gserviceaccount.com"],
44+
])("returns false for %s", (_label, value) => {
45+
expect(looksLikeFilePath(value)).toBe(false)
46+
})
47+
})
48+
})

packages/types/src/global-settings.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,7 @@ export const SECRET_STATE_KEYS = [
279279
"zaiApiKey",
280280
"fireworksApiKey",
281281
"vercelAiGatewayApiKey",
282+
"opencodeGoApiKey",
282283
"basetenApiKey",
283284
] as const
284285

packages/types/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,5 @@ export * from "./vscode.js"
3333
export * from "./worktree.js"
3434

3535
export * from "./providers/index.js"
36+
37+
export * from "./utils/looksLikeFilePath.js"

0 commit comments

Comments
 (0)