mirror of
https://github.com/cline/cline.git
synced 2026-09-07 04:44:58 +08:00
Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cab5183297 | |||
| 870e58280d | |||
| 010a23c795 | |||
| da9dd52bf2 | |||
| ff5b6584bc | |||
| 04204c14bf | |||
| 40a5f5ffad | |||
| 9fff0bd34d | |||
| 2e7dd7f841 | |||
| 18cf97431c | |||
| 805fb85371 | |||
| 488e377a44 | |||
| 16a378840b | |||
| 0bbc718766 | |||
| 74c6d1d2bc | |||
| 82b549c2ca |
+13
-13
@@ -70,7 +70,7 @@
|
||||
"noControlCharactersInRegex": "off",
|
||||
"noShadowRestrictedNames": "off",
|
||||
"noArrayIndexKey": "info",
|
||||
"noAssignInExpressions": "warn"
|
||||
"noAssignInExpressions": "info"
|
||||
},
|
||||
"complexity": {
|
||||
"noUselessConstructor": "off",
|
||||
@@ -82,7 +82,7 @@
|
||||
"noStaticOnlyClass": "off"
|
||||
},
|
||||
"security": {
|
||||
"noDangerouslySetInnerHtml": "warn"
|
||||
"noDangerouslySetInnerHtml": "info"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -114,17 +114,17 @@
|
||||
"files": {
|
||||
"includes": [
|
||||
"**",
|
||||
"!**/dist/**",
|
||||
"!**/dist-*/**",
|
||||
"!**/out/**",
|
||||
"!**/evals/**",
|
||||
"!**/playwright/**",
|
||||
"!**/test-results/**",
|
||||
"!**/node_modules/**",
|
||||
"!**/webview-ui/build/**",
|
||||
"!**/generated/**",
|
||||
"!**/proto/**",
|
||||
"!**/tests/specs/**"
|
||||
"!**/dist",
|
||||
"!**/dist-*",
|
||||
"!**/out",
|
||||
"!**/evals",
|
||||
"!**/playwright",
|
||||
"!**/test-results",
|
||||
"!**/node_modules",
|
||||
"!**/webview-ui/build",
|
||||
"!**/generated",
|
||||
"!**/proto",
|
||||
"!**/tests/specs"
|
||||
]
|
||||
},
|
||||
"plugins": [
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import execa from "execa"
|
||||
import * as path from "path"
|
||||
import * as fs from "fs"
|
||||
import fetch from "node-fetch"
|
||||
import * as os from "os"
|
||||
import { installRequiredExtensions, configureExtensionSettings } from "./extensions"
|
||||
import * as path from "path"
|
||||
import { configureExtensionSettings, installRequiredExtensions } from "./extensions"
|
||||
|
||||
// Store temporary directories for cleanup
|
||||
interface VSCodeResources {
|
||||
|
||||
@@ -124,7 +124,6 @@ export class WriteToFileToolHandler implements IFullyManagedTool {
|
||||
|
||||
const { relPath, absolutePath, fileExists, diff, content, newContent, workspaceContext } = result
|
||||
|
||||
|
||||
// Handle approval flow
|
||||
const sharedMessageProps: ClineSayTool = {
|
||||
tool: fileExists ? "editedExistingFile" : "newFileCreated",
|
||||
|
||||
@@ -43,7 +43,8 @@ e2e("Views - can set up API keys and navigate to Settings from Chat", async ({ s
|
||||
await expect(providerSelectorInput).not.toBeVisible()
|
||||
|
||||
// Verify you are now in the chat page after setup was completed
|
||||
const clineLogo = sidebar.getByRole("img").filter({ hasText: /^$/ }).locator("path")
|
||||
// cline logo has the name "clline-logo"
|
||||
const clineLogo = sidebar.locator(".size-20 > path")
|
||||
await expect(clineLogo).toBeVisible()
|
||||
const chatInputBox = sidebar.getByTestId("chat-input")
|
||||
await expect(chatInputBox).toBeVisible()
|
||||
|
||||
@@ -17,7 +17,7 @@ e2e("Chat - can send messages and switch between modes", async ({ helper, sideba
|
||||
await expect(sidebar.getByText("API Request...")).toBeVisible()
|
||||
|
||||
// Starting a new task should clear the current chat view and show the recent tasks
|
||||
await sidebar.getByRole("button", { name: "New Task" }).click()
|
||||
await sidebar.getByRole("button", { name: "New Task", exact: true }).first().click()
|
||||
await expect(sidebar.getByText("Recent Tasks")).toBeVisible()
|
||||
await expect(sidebar.getByText("Hello, Cline!")).toBeVisible()
|
||||
|
||||
@@ -26,12 +26,13 @@ e2e("Chat - can send messages and switch between modes", async ({ helper, sideba
|
||||
const actButton = sidebar.getByRole("switch", { name: "Act" })
|
||||
const planButton = sidebar.getByRole("switch", { name: "Plan" })
|
||||
|
||||
await expect(actButton).toBeChecked()
|
||||
await expect(planButton).not.toBeChecked()
|
||||
// Act button should be active. It doesn't have c
|
||||
await expect(actButton).toHaveAttribute("aria-checked", "true")
|
||||
await expect(planButton).not.toHaveAttribute("aria-checked", "true")
|
||||
|
||||
await actButton.click()
|
||||
await expect(actButton).not.toBeChecked()
|
||||
await expect(planButton).toBeChecked()
|
||||
await planButton.click()
|
||||
await expect(planButton).toHaveAttribute("aria-checked", "true")
|
||||
await expect(actButton).not.toHaveAttribute("aria-checked", "true")
|
||||
|
||||
// === slash commands preserve following text ===
|
||||
await expect(inputbox).toHaveValue("")
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"style": "new-york",
|
||||
"rsc": false,
|
||||
"tsx": true,
|
||||
"tailwind": {
|
||||
"config": "tailwind.config.mjs",
|
||||
"css": "src/index.css",
|
||||
"baseColor": "neutral",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"iconLibrary": "lucide",
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"utils": "@/lib/utils",
|
||||
"ui": "@/components/ui",
|
||||
"lib": "@/lib",
|
||||
"hooks": "@/hooks"
|
||||
},
|
||||
"registries": {}
|
||||
}
|
||||
Generated
+734
-24
@@ -12,7 +12,14 @@
|
||||
"@fontsource/azeret-mono": "^5.2.9",
|
||||
"@heroui/react": "^2.8.0-beta.2",
|
||||
"@paper-design/shaders-react": "^0.0.46",
|
||||
"@radix-ui/react-hover-card": "^1.1.15",
|
||||
"@radix-ui/react-popover": "^1.1.15",
|
||||
"@radix-ui/react-progress": "^1.1.7",
|
||||
"@radix-ui/react-slot": "^1.2.3",
|
||||
"@radix-ui/react-tooltip": "^1.2.8",
|
||||
"@vscode/webview-ui-toolkit": "^1.4.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"debounce": "^2.1.1",
|
||||
"dompurify": "^3.2.4",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
@@ -35,12 +42,14 @@
|
||||
"rehype-remark": "^10.0.1",
|
||||
"remark-stringify": "^11.0.0",
|
||||
"styled-components": "^6.1.15",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"unified": "^11.0.5",
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/react-vite": "^9.1.6",
|
||||
"@tailwindcss/vite": "^4.1.4",
|
||||
"@tailwindcss/vite": "^4.1.13",
|
||||
"@testing-library/jest-dom": "^6.6.3",
|
||||
"@testing-library/react": "^16.2.0",
|
||||
"@testing-library/user-event": "^14.6.1",
|
||||
@@ -56,7 +65,7 @@
|
||||
"globals": "^15.14.0",
|
||||
"jsdom": "^26.0.0",
|
||||
"storybook": "^9.1.6",
|
||||
"tailwindcss": "^4.1.5",
|
||||
"tailwindcss": "^4.1.13",
|
||||
"typescript": "^5.7.3",
|
||||
"vite": "^6.3.6",
|
||||
"vitest": "^3.0.5"
|
||||
@@ -2893,6 +2902,15 @@
|
||||
"react": ">=18 || >=19.0.0-rc.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@heroui/system-rsc/node_modules/clsx": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
|
||||
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@heroui/table": {
|
||||
"version": "2.2.26",
|
||||
"resolved": "https://registry.npmjs.org/@heroui/table/-/table-2.2.26.tgz",
|
||||
@@ -2965,6 +2983,15 @@
|
||||
"tailwindcss": ">=4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@heroui/theme/node_modules/clsx": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
|
||||
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@heroui/toast": {
|
||||
"version": "2.0.16",
|
||||
"resolved": "https://registry.npmjs.org/@heroui/toast/-/toast-2.0.16.tgz",
|
||||
@@ -3724,6 +3751,547 @@
|
||||
"integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==",
|
||||
"license": "BSD-3-Clause"
|
||||
},
|
||||
"node_modules/@radix-ui/primitive": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.3.tgz",
|
||||
"integrity": "sha512-JTF99U/6XIjCBo0wqkU5sK10glYe27MRRsfwoiq5zzOEZLHU3A3KCMa5X/azekYRCJ0HlwI0crAXS/5dEHTzDg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@radix-ui/react-arrow": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.7.tgz",
|
||||
"integrity": "sha512-F+M1tLhO+mlQaOWspE8Wstg+z6PwxwRd8oQ8IXceWz92kfAmalTRf0EjrouQeo7QssEPfCn05B4Ihs1K9WQ/7w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-primitive": "2.1.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-compose-refs": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.2.tgz",
|
||||
"integrity": "sha512-z4eqJvfiNnFMHIIvXP3CY57y2WJs5g2v3X0zm9mEJkrkNv4rDxu+sg9Jh8EkXyeqBkB7SOcboo9dMVqhyrACIg==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-context": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz",
|
||||
"integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-dismissable-layer": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.11.tgz",
|
||||
"integrity": "sha512-Nqcp+t5cTB8BinFkZgXiMJniQH0PsUt2k51FUhbdfeKvc4ACcG2uQniY/8+h1Yv6Kza4Q7lD7PQV0z0oicE0Mg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/primitive": "1.1.3",
|
||||
"@radix-ui/react-compose-refs": "1.1.2",
|
||||
"@radix-ui/react-primitive": "2.1.3",
|
||||
"@radix-ui/react-use-callback-ref": "1.1.1",
|
||||
"@radix-ui/react-use-escape-keydown": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-focus-guards": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.3.tgz",
|
||||
"integrity": "sha512-0rFg/Rj2Q62NCm62jZw0QX7a3sz6QCQU0LpZdNrJX8byRGaGVTqbrW9jAoIAHyMQqsNpeZ81YgSizOt5WXq0Pw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-focus-scope": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.7.tgz",
|
||||
"integrity": "sha512-t2ODlkXBQyn7jkl6TNaw/MtVEVvIGelJDCG41Okq/KwUsJBwQ4XVZsHAVUkK4mBv3ewiAS3PGuUWuY2BoK4ZUw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-compose-refs": "1.1.2",
|
||||
"@radix-ui/react-primitive": "2.1.3",
|
||||
"@radix-ui/react-use-callback-ref": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-hover-card": {
|
||||
"version": "1.1.15",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-hover-card/-/react-hover-card-1.1.15.tgz",
|
||||
"integrity": "sha512-qgTkjNT1CfKMoP0rcasmlH2r1DAiYicWsDsufxl940sT2wHNEWWv6FMWIQXWhVdmC1d/HYfbhQx60KYyAtKxjg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/primitive": "1.1.3",
|
||||
"@radix-ui/react-compose-refs": "1.1.2",
|
||||
"@radix-ui/react-context": "1.1.2",
|
||||
"@radix-ui/react-dismissable-layer": "1.1.11",
|
||||
"@radix-ui/react-popper": "1.2.8",
|
||||
"@radix-ui/react-portal": "1.1.9",
|
||||
"@radix-ui/react-presence": "1.1.5",
|
||||
"@radix-ui/react-primitive": "2.1.3",
|
||||
"@radix-ui/react-use-controllable-state": "1.2.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-id": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz",
|
||||
"integrity": "sha512-kGkGegYIdQsOb4XjsfM97rXsiHaBwco+hFI66oO4s9LU+PLAC5oJ7khdOVFxkhsmlbpUqDAvXw11CluXP+jkHg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-popover": {
|
||||
"version": "1.1.15",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-popover/-/react-popover-1.1.15.tgz",
|
||||
"integrity": "sha512-kr0X2+6Yy/vJzLYJUPCZEc8SfQcf+1COFoAqauJm74umQhta9M7lNJHP7QQS3vkvcGLQUbWpMzwrXYwrYztHKA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/primitive": "1.1.3",
|
||||
"@radix-ui/react-compose-refs": "1.1.2",
|
||||
"@radix-ui/react-context": "1.1.2",
|
||||
"@radix-ui/react-dismissable-layer": "1.1.11",
|
||||
"@radix-ui/react-focus-guards": "1.1.3",
|
||||
"@radix-ui/react-focus-scope": "1.1.7",
|
||||
"@radix-ui/react-id": "1.1.1",
|
||||
"@radix-ui/react-popper": "1.2.8",
|
||||
"@radix-ui/react-portal": "1.1.9",
|
||||
"@radix-ui/react-presence": "1.1.5",
|
||||
"@radix-ui/react-primitive": "2.1.3",
|
||||
"@radix-ui/react-slot": "1.2.3",
|
||||
"@radix-ui/react-use-controllable-state": "1.2.2",
|
||||
"aria-hidden": "^1.2.4",
|
||||
"react-remove-scroll": "^2.6.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-popper": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.8.tgz",
|
||||
"integrity": "sha512-0NJQ4LFFUuWkE7Oxf0htBKS6zLkkjBH+hM1uk7Ng705ReR8m/uelduy1DBo0PyBXPKVnBA6YBlU94MBGXrSBCw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@floating-ui/react-dom": "^2.0.0",
|
||||
"@radix-ui/react-arrow": "1.1.7",
|
||||
"@radix-ui/react-compose-refs": "1.1.2",
|
||||
"@radix-ui/react-context": "1.1.2",
|
||||
"@radix-ui/react-primitive": "2.1.3",
|
||||
"@radix-ui/react-use-callback-ref": "1.1.1",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1",
|
||||
"@radix-ui/react-use-rect": "1.1.1",
|
||||
"@radix-ui/react-use-size": "1.1.1",
|
||||
"@radix-ui/rect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-portal": {
|
||||
"version": "1.1.9",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.9.tgz",
|
||||
"integrity": "sha512-bpIxvq03if6UNwXZ+HTK71JLh4APvnXntDc6XOX8UVq4XQOVl7lwok0AvIl+b8zgCw3fSaVTZMpAPPagXbKmHQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-primitive": "2.1.3",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-presence": {
|
||||
"version": "1.1.5",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.5.tgz",
|
||||
"integrity": "sha512-/jfEwNDdQVBCNvjkGit4h6pMOzq8bHkopq458dPt2lMjx+eBQUohZNG9A7DtO/O5ukSbxuaNGXMjHicgwy6rQQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-compose-refs": "1.1.2",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-primitive": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz",
|
||||
"integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-slot": "1.2.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-progress": {
|
||||
"version": "1.1.7",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-progress/-/react-progress-1.1.7.tgz",
|
||||
"integrity": "sha512-vPdg/tF6YC/ynuBIJlk1mm7Le0VgW6ub6J2UWnTQ7/D23KXcPI1qy+0vBkgKgd38RCMJavBXpB83HPNFMTb0Fg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-context": "1.1.2",
|
||||
"@radix-ui/react-primitive": "2.1.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-slot": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz",
|
||||
"integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-compose-refs": "1.1.2"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-tooltip": {
|
||||
"version": "1.2.8",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.8.tgz",
|
||||
"integrity": "sha512-tY7sVt1yL9ozIxvmbtN5qtmH2krXcBCfjEiCgKGLqunJHvgvZG2Pcl2oQ3kbcZARb1BGEHdkLzcYGO8ynVlieg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/primitive": "1.1.3",
|
||||
"@radix-ui/react-compose-refs": "1.1.2",
|
||||
"@radix-ui/react-context": "1.1.2",
|
||||
"@radix-ui/react-dismissable-layer": "1.1.11",
|
||||
"@radix-ui/react-id": "1.1.1",
|
||||
"@radix-ui/react-popper": "1.2.8",
|
||||
"@radix-ui/react-portal": "1.1.9",
|
||||
"@radix-ui/react-presence": "1.1.5",
|
||||
"@radix-ui/react-primitive": "2.1.3",
|
||||
"@radix-ui/react-slot": "1.2.3",
|
||||
"@radix-ui/react-use-controllable-state": "1.2.2",
|
||||
"@radix-ui/react-visually-hidden": "1.2.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-callback-ref": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.1.tgz",
|
||||
"integrity": "sha512-FkBMwD+qbGQeMu1cOHnuGB6x4yzPjho8ap5WtbEJ26umhgqVXbhekKUQO+hZEL1vU92a3wHwdp0HAcqAUF5iDg==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-controllable-state": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.2.2.tgz",
|
||||
"integrity": "sha512-BjasUjixPFdS+NKkypcyyN5Pmg83Olst0+c6vGov0diwTEo6mgdqVR6hxcEgFuh4QrAs7Rc+9KuGJ9TVCj0Zzg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-use-effect-event": "0.0.2",
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-effect-event": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-effect-event/-/react-use-effect-event-0.0.2.tgz",
|
||||
"integrity": "sha512-Qp8WbZOBe+blgpuUT+lw2xheLP8q0oatc9UpmiemEICxGvFLYmHm9QowVZGHtJlGbS6A6yJ3iViad/2cVjnOiA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-escape-keydown": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.1.tgz",
|
||||
"integrity": "sha512-Il0+boE7w/XebUHyBjroE+DbByORGR9KKmITzbR7MyQ4akpORYP/ZmbhAr0DG7RmmBqoOnZdy2QlvajJ2QA59g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-use-callback-ref": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-layout-effect": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.1.tgz",
|
||||
"integrity": "sha512-RbJRS4UWQFkzHTTwVymMTUv8EqYhOp8dOOviLj2ugtTiXRaRQS7GLGxZTLL1jWhMeoSCf5zmcZkqTl9IiYfXcQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-rect": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.1.tgz",
|
||||
"integrity": "sha512-QTYuDesS0VtuHNNvMh+CjlKJ4LJickCMUAqjlE3+j8w+RlRpwyX3apEQKGFzbZGdo7XNG1tXa+bQqIE7HIXT2w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/rect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-use-size": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.1.tgz",
|
||||
"integrity": "sha512-ewrXRDTAqAXlkl6t/fkXWNAhFX9I+CkKlw6zjEwk86RSPKwZr3xpBRso655aqYafwtnbpHLj6toFzmd6xdVptQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-use-layout-effect": "1.1.1"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/react-visually-hidden": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz",
|
||||
"integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@radix-ui/react-primitive": "2.1.3"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"@types/react-dom": "*",
|
||||
"react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc",
|
||||
"react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
},
|
||||
"@types/react-dom": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/@radix-ui/rect": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.1.tgz",
|
||||
"integrity": "sha512-HPwpGIzkl28mWyZqG52jiqDJ12waP11Pa1lGoiyUkIEuMLBP0oeK/C89esbXrxsky5we7dfd8U58nm0SgAWpVw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@react-aria/breadcrumbs": {
|
||||
"version": "3.5.28",
|
||||
"resolved": "https://registry.npmjs.org/@react-aria/breadcrumbs/-/breadcrumbs-3.5.28.tgz",
|
||||
@@ -3899,15 +4467,6 @@
|
||||
"react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-aria/focus/node_modules/clsx": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-aria/form": {
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@react-aria/form/-/form-3.1.1.tgz",
|
||||
@@ -4425,15 +4984,6 @@
|
||||
"react-dom": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-aria/utils/node_modules/clsx": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/@react-aria/visually-hidden": {
|
||||
"version": "3.8.27",
|
||||
"resolved": "https://registry.npmjs.org/@react-aria/visually-hidden/-/visually-hidden-3.8.27.tgz",
|
||||
@@ -6697,7 +7247,7 @@
|
||||
"version": "18.3.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz",
|
||||
"integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==",
|
||||
"dev": true,
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@types/react": "^18.0.0"
|
||||
@@ -7014,6 +7564,18 @@
|
||||
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
|
||||
}
|
||||
},
|
||||
"node_modules/aria-hidden": {
|
||||
"version": "1.2.6",
|
||||
"resolved": "https://registry.npmjs.org/aria-hidden/-/aria-hidden-1.2.6.tgz",
|
||||
"integrity": "sha512-ik3ZgC9dY/lYVVM++OISsaYDeg1tb0VtP5uL3ouh1koGOaUMDPpbFIei4JkFimWUFPn90sbMNMXQAIVOlnYKJA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
}
|
||||
},
|
||||
"node_modules/aria-query": {
|
||||
"version": "5.3.0",
|
||||
"resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
|
||||
@@ -7359,6 +7921,18 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/class-variance-authority": {
|
||||
"version": "0.7.1",
|
||||
"resolved": "https://registry.npmjs.org/class-variance-authority/-/class-variance-authority-0.7.1.tgz",
|
||||
"integrity": "sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"clsx": "^2.1.1"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://polar.sh/cva"
|
||||
}
|
||||
},
|
||||
"node_modules/cliui": {
|
||||
"version": "8.0.1",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
|
||||
@@ -7423,9 +7997,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/clsx": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
|
||||
"integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
|
||||
"integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
@@ -8263,6 +8837,12 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/detect-node-es": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/detect-node-es/-/detect-node-es-1.1.0.tgz",
|
||||
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/devlop": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz",
|
||||
@@ -8775,6 +9355,15 @@
|
||||
"node": "6.* || 8.* || >= 10.*"
|
||||
}
|
||||
},
|
||||
"node_modules/get-nonce": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/get-nonce/-/get-nonce-1.0.1.tgz",
|
||||
"integrity": "sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/glob": {
|
||||
"version": "10.4.5",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
|
||||
@@ -11449,6 +12038,75 @@
|
||||
"url": "https://opencollective.com/unified"
|
||||
}
|
||||
},
|
||||
"node_modules/react-remove-scroll": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.7.1.tgz",
|
||||
"integrity": "sha512-HpMh8+oahmIdOuS5aFKKY6Pyog+FNaZV/XyJOq7b4YFwsFHe5yYfdbIalI4k3vU2nSDql7YskmUseHsRrJqIPA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"react-remove-scroll-bar": "^2.3.7",
|
||||
"react-style-singleton": "^2.2.3",
|
||||
"tslib": "^2.1.0",
|
||||
"use-callback-ref": "^1.3.3",
|
||||
"use-sidecar": "^1.1.3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-remove-scroll-bar": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz",
|
||||
"integrity": "sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"react-style-singleton": "^2.2.2",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-style-singleton": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/react-style-singleton/-/react-style-singleton-2.2.3.tgz",
|
||||
"integrity": "sha512-b6jSvxvVnyptAiLjbkWLE/lOnR4lfTtDAl+eUC7RZy+QQWc6wRzIV2CE6xBuMmDxc2qIihtDCZD5NPOFl7fRBQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"get-nonce": "^1.0.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/react-textarea-autosize": {
|
||||
"version": "8.5.9",
|
||||
"resolved": "https://registry.npmjs.org/react-textarea-autosize/-/react-textarea-autosize-8.5.9.tgz",
|
||||
@@ -12463,6 +13121,15 @@
|
||||
"integrity": "sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tailwindcss-animate": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss-animate/-/tailwindcss-animate-1.0.7.tgz",
|
||||
"integrity": "sha512-bl6mpH3T7I3UFxuvDEXLxy/VuFxBk5bbzplh7tXI68mwMokNYd1t9qPBHlnyTwfa4JGC4zP516I1hYYtQ/vspA==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"tailwindcss": ">=3.0.0 || insiders"
|
||||
}
|
||||
},
|
||||
"node_modules/tapable": {
|
||||
"version": "2.2.3",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.3.tgz",
|
||||
@@ -13016,6 +13683,27 @@
|
||||
"browserslist": ">= 4.21.0"
|
||||
}
|
||||
},
|
||||
"node_modules/use-callback-ref": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz",
|
||||
"integrity": "sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/use-composed-ref": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/use-composed-ref/-/use-composed-ref-1.4.0.tgz",
|
||||
@@ -13061,6 +13749,28 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/use-sidecar": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/use-sidecar/-/use-sidecar-1.1.3.tgz",
|
||||
"integrity": "sha512-Fedw0aZvkhynoPYlA5WXrMCAMm+nSWdZt6lzJQ7Ok8S6Q+VsHmHpRWndVRJ8Be0ZbkfPc5LRYH+5XrzXcEeLRQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"detect-node-es": "^1.1.0",
|
||||
"tslib": "^2.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@types/react": "*",
|
||||
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@types/react": {
|
||||
"optional": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"node_modules/use-sync-external-store": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.5.0.tgz",
|
||||
|
||||
+11
-2
@@ -20,7 +20,14 @@
|
||||
"@fontsource/azeret-mono": "^5.2.9",
|
||||
"@heroui/react": "^2.8.0-beta.2",
|
||||
"@paper-design/shaders-react": "^0.0.46",
|
||||
"@radix-ui/react-hover-card": "^1.1.15",
|
||||
"@radix-ui/react-popover": "^1.1.15",
|
||||
"@radix-ui/react-progress": "^1.1.7",
|
||||
"@radix-ui/react-slot": "^1.2.3",
|
||||
"@radix-ui/react-tooltip": "^1.2.8",
|
||||
"@vscode/webview-ui-toolkit": "^1.4.0",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"debounce": "^2.1.1",
|
||||
"dompurify": "^3.2.4",
|
||||
"fast-deep-equal": "^3.1.3",
|
||||
@@ -43,12 +50,14 @@
|
||||
"rehype-remark": "^10.0.1",
|
||||
"remark-stringify": "^11.0.0",
|
||||
"styled-components": "^6.1.15",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"unified": "^11.0.5",
|
||||
"uuid": "^9.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@storybook/react-vite": "^9.1.6",
|
||||
"@tailwindcss/vite": "^4.1.4",
|
||||
"@tailwindcss/vite": "^4.1.13",
|
||||
"@testing-library/jest-dom": "^6.6.3",
|
||||
"@testing-library/react": "^16.2.0",
|
||||
"@testing-library/user-event": "^14.6.1",
|
||||
@@ -64,7 +73,7 @@
|
||||
"globals": "^15.14.0",
|
||||
"jsdom": "^26.0.0",
|
||||
"storybook": "^9.1.6",
|
||||
"tailwindcss": "^4.1.5",
|
||||
"tailwindcss": "^4.1.13",
|
||||
"typescript": "^5.7.3",
|
||||
"vite": "^6.3.6",
|
||||
"vitest": "^3.0.5"
|
||||
|
||||
@@ -5,11 +5,12 @@ import { VSCodeButton, VSCodeDivider, VSCodeDropdown, VSCodeOption, VSCodeTag }
|
||||
import deepEqual from "fast-deep-equal"
|
||||
import { memo, useCallback, useEffect, useRef, useState } from "react"
|
||||
import { useInterval } from "react-use"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { type ClineUser, handleSignOut } from "@/context/ClineAuthContext"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { AccountServiceClient } from "@/services/grpc-client"
|
||||
import { getEnvironmentColor } from "@/utils/environmentColors"
|
||||
import HeroTooltip from "../common/HeroTooltip"
|
||||
import { getClineEnvironmentClassname } from "@/utils/environmentColors"
|
||||
import VSCodeButtonLink from "../common/VSCodeButtonLink"
|
||||
import { AccountWelcomeView } from "./AccountWelcomeView"
|
||||
import { CreditBalance } from "./CreditBalance"
|
||||
@@ -38,17 +39,15 @@ type CachedData = {
|
||||
|
||||
const AccountView = ({ onDone, clineUser, organizations, activeOrganization }: AccountViewProps) => {
|
||||
const { environment } = useExtensionState()
|
||||
const titleColor = getEnvironmentColor(environment)
|
||||
const titleColor = getClineEnvironmentClassname(environment)
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 flex flex-col overflow-hidden pt-[10px] pl-[20px]">
|
||||
<div className="flex justify-between items-center mb-[17px] pr-[17px]">
|
||||
<h3 className="m-0" style={{ color: titleColor }}>
|
||||
Account
|
||||
</h3>
|
||||
<h3 className={cn("text-(--vscode-foreground) m-0", titleColor)}>Account</h3>
|
||||
<VSCodeButton onClick={onDone}>Done</VSCodeButton>
|
||||
</div>
|
||||
<div className="flex-grow overflow-hidden pr-[8px] flex flex-col">
|
||||
<div className="grow overflow-hidden pr-[8px] flex flex-col">
|
||||
<div className="h-full mb-1.5">
|
||||
{clineUser?.uid ? (
|
||||
<ClineAccountView
|
||||
@@ -310,21 +309,19 @@ export const ClineAccountView = ({ clineUser, userOrganizations, activeOrganizat
|
||||
{/* {user.photoUrl ? (
|
||||
<img src={user.photoUrl} alt="Profile" className="size-16 rounded-full mr-4" />
|
||||
) : ( */}
|
||||
<div className="size-16 rounded-full bg-[var(--vscode-button-background)] flex items-center justify-center text-2xl text-[var(--vscode-button-foreground)] mr-4">
|
||||
<div className="size-16 rounded-full bg-(--vscode-button-background) flex items-center justify-center text-2xl text-(--vscode-button-foreground) mr-4">
|
||||
{displayName?.[0] || email?.[0] || "?"}
|
||||
</div>
|
||||
{/* )} */}
|
||||
|
||||
<div className="flex flex-col">
|
||||
{displayName && (
|
||||
<h2 className="text-[var(--vscode-foreground)] m-0 text-lg font-medium">{displayName}</h2>
|
||||
)}
|
||||
{displayName && <h2 className="text-(--vscode-foreground) m-0 text-lg font-medium">{displayName}</h2>}
|
||||
|
||||
{email && <div className="text-sm text-[var(--vscode-descriptionForeground)]">{email}</div>}
|
||||
{email && <div className="text-sm text-(--vscode-descriptionForeground)">{email}</div>}
|
||||
|
||||
<div className="flex gap-2 items-center mt-1">
|
||||
{isLockedByRemoteConfig ? (
|
||||
<HeroTooltip content="This cannot be changed while your organization has remote configuration enabled.">
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<VSCodeDropdown
|
||||
className="w-full"
|
||||
currentValue={dropdownValue}
|
||||
@@ -339,23 +336,11 @@ export const ClineAccountView = ({ clineUser, userOrganizations, activeOrganizat
|
||||
</VSCodeOption>
|
||||
))}
|
||||
</VSCodeDropdown>
|
||||
</HeroTooltip>
|
||||
) : (
|
||||
<VSCodeDropdown
|
||||
className="w-full"
|
||||
currentValue={dropdownValue}
|
||||
disabled={isLoading}
|
||||
onChange={handleOrganizationChange}>
|
||||
<VSCodeOption key="personal" value={uid}>
|
||||
Personal
|
||||
</VSCodeOption>
|
||||
{userOrganizations?.map((org: UserOrganization) => (
|
||||
<VSCodeOption key={org.organizationId} value={org.organizationId}>
|
||||
{org.name}
|
||||
</VSCodeOption>
|
||||
))}
|
||||
</VSCodeDropdown>
|
||||
)}
|
||||
</TooltipTrigger>
|
||||
<TooltipContent hidden={isLockedByRemoteConfig}>
|
||||
This cannot be changed while your organization has remote configuration enabled.
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
{activeOrganization && (
|
||||
<VSCodeTag className="text-xs p-2" title="Role">
|
||||
{getMainRole(activeOrganization.roles)}
|
||||
@@ -389,7 +374,7 @@ export const ClineAccountView = ({ clineUser, userOrganizations, activeOrganizat
|
||||
|
||||
<VSCodeDivider className="mt-6 mb-3 w-full" />
|
||||
|
||||
<div className="flex-grow flex flex-col min-h-0 pb-[0px]">
|
||||
<div className="grow flex flex-col min-h-0 pb-[0px]">
|
||||
<CreditsHistoryTable
|
||||
isLoading={isLoading}
|
||||
paymentsData={paymentsData}
|
||||
|
||||
@@ -3,11 +3,14 @@ import { handleSignIn } from "@/context/ClineAuthContext"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import ClineLogoVariable from "../../assets/ClineLogoVariable"
|
||||
|
||||
// export const AccountWelcomeView = () => (
|
||||
// <div className="flex flex-col items-center pr-3 gap-2.5">
|
||||
// <ClineLogoWhite className="size-16 mb-4" />
|
||||
export const AccountWelcomeView = () => {
|
||||
const { environment } = useExtensionState()
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center pr-3">
|
||||
<div className="flex flex-col items-center pr-3 gap-2.5">
|
||||
<ClineLogoVariable className="size-16 mb-4" environment={environment} />
|
||||
|
||||
<p>
|
||||
@@ -19,7 +22,7 @@ export const AccountWelcomeView = () => {
|
||||
Sign up with Cline
|
||||
</VSCodeButton>
|
||||
|
||||
<p className="text-[var(--vscode-descriptionForeground)] text-xs text-center m-0">
|
||||
<p className="text-(--vscode-descriptionForeground) text-xs text-center m-0">
|
||||
By continuing, you agree to the <VSCodeLink href="https://cline.bot/tos">Terms of Service</VSCodeLink> and{" "}
|
||||
<VSCodeLink href="https://cline.bot/privacy">Privacy Policy.</VSCodeLink>
|
||||
</p>
|
||||
|
||||
@@ -15,11 +15,9 @@ export const CreditBalance = ({ balance, fetchCreditBalance, creditUrl, lastFetc
|
||||
<div
|
||||
className="w-full flex flex-col items-center"
|
||||
title={`Last updated: ${new Date(lastFetchTime).toLocaleTimeString()}`}>
|
||||
<div className="text-sm text-[var(--vscode-descriptionForeground)] mb-3 font-azeret-mono font-light">
|
||||
CURRENT BALANCE
|
||||
</div>
|
||||
<div className="text-sm text-(--vscode-descriptionForeground) mb-3 font-azeret-mono font-light">CURRENT BALANCE</div>
|
||||
|
||||
<div className="text-4xl font-bold text-[var(--vscode-foreground)] mb-6 flex items-center gap-2">
|
||||
<div className="font-bold text-2xl mb-6 flex items-center gap-2">
|
||||
{balance === null ? <span>----</span> : <StyledCreditDisplay balance={balance} />}
|
||||
<VSCodeButton
|
||||
appearance="icon"
|
||||
|
||||
@@ -15,9 +15,9 @@ const CreditsHistoryTable = ({ isLoading, usageData, paymentsData, showPayments
|
||||
const [activeTab, setActiveTab] = useState<"usage" | "payments">("usage")
|
||||
|
||||
return (
|
||||
<div className="flex flex-col flex-grow h-full">
|
||||
<div className="flex flex-col grow h-full">
|
||||
{/* Tabs container */}
|
||||
<div className="flex border-b border-[var(--vscode-panel-border)]">
|
||||
<div className="flex border-b border-(--vscode-panel-border)">
|
||||
<TabButton isActive={activeTab === "usage"} onClick={() => setActiveTab("usage")}>
|
||||
USAGE HISTORY
|
||||
</TabButton>
|
||||
@@ -29,10 +29,10 @@ const CreditsHistoryTable = ({ isLoading, usageData, paymentsData, showPayments
|
||||
</div>
|
||||
|
||||
{/* Content container */}
|
||||
<div className="mt-[15px] mb-[0px] rounded-md overflow-auto flex-grow">
|
||||
<div className="mt-[15px] mb-[0px] rounded-md overflow-auto grow">
|
||||
{isLoading ? (
|
||||
<div className="flex justify-center items-center p-4">
|
||||
<div className="text-[var(--vscode-descriptionForeground)]">Loading...</div>
|
||||
<div className="text-(--vscode-descriptionForeground)">Loading...</div>
|
||||
</div>
|
||||
) : (
|
||||
<>
|
||||
@@ -55,6 +55,7 @@ const CreditsHistoryTable = ({ isLoading, usageData, paymentsData, showPayments
|
||||
</VSCodeDataGridRow>
|
||||
|
||||
{usageData.map((row, index) => (
|
||||
// biome-ignore lint/suspicious/noArrayIndexKey: use index as key
|
||||
<VSCodeDataGridRow key={index}>
|
||||
<VSCodeDataGridCell grid-column="1">
|
||||
{formatTimestamp(row.createdAt)}
|
||||
@@ -67,7 +68,7 @@ const CreditsHistoryTable = ({ isLoading, usageData, paymentsData, showPayments
|
||||
</VSCodeDataGrid>
|
||||
) : (
|
||||
<div className="flex justify-center items-center p-4">
|
||||
<div className="text-[var(--vscode-descriptionForeground)]">No usage history</div>
|
||||
<div className="text-(--vscode-descriptionForeground)">No usage history</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
@@ -88,6 +89,7 @@ const CreditsHistoryTable = ({ isLoading, usageData, paymentsData, showPayments
|
||||
</VSCodeDataGridRow>
|
||||
|
||||
{paymentsData.map((row, index) => (
|
||||
// biome-ignore lint/suspicious/noArrayIndexKey: use index as key
|
||||
<VSCodeDataGridRow key={index}>
|
||||
<VSCodeDataGridCell grid-column="1">{formatTimestamp(row.paidAt)}</VSCodeDataGridCell>
|
||||
<VSCodeDataGridCell grid-column="2">{`$${formatDollars(row.amountCents)}`}</VSCodeDataGridCell>
|
||||
@@ -97,7 +99,7 @@ const CreditsHistoryTable = ({ isLoading, usageData, paymentsData, showPayments
|
||||
</VSCodeDataGrid>
|
||||
) : (
|
||||
<div className="flex justify-center items-center p-4">
|
||||
<div className="text-[var(--vscode-descriptionForeground)]">No payment history</div>
|
||||
<div className="text-(--vscode-descriptionForeground)">No payment history</div>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
|
||||
@@ -52,9 +52,9 @@ export const StyledCreditDisplay = ({ balance }: { balance: number }) => {
|
||||
const lastTwoDecimals = decimalPart.slice(2)
|
||||
|
||||
return (
|
||||
<span className="font-azeret-mono font-light tabular-nums">
|
||||
<span className="font-azeret-mono font-light tabular-nums text-2xl">
|
||||
{wholePart}.{firstTwoDecimals}
|
||||
<span className="text-[var(--vscode-descriptionForeground)]">{lastTwoDecimals}</span>
|
||||
<span className="text-description text-2xl">{lastTwoDecimals}</span>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ export const BrowserSettingsMenu = () => {
|
||||
{showInfoPopover && (
|
||||
// InfoPopover - Dropdown container with connection details
|
||||
<div
|
||||
className="absolute top-[30px] right-0 z-[100] w-[60dvw] max-w-[250px] rounded p-2.5 shadow-lg"
|
||||
className="absolute top-[30px] right-0 z-100 w-[60dvw] max-w-[250px] rounded p-2.5 shadow-lg"
|
||||
ref={popoverRef}
|
||||
style={{
|
||||
backgroundColor: "var(--vscode-editorWidget-background)",
|
||||
|
||||
@@ -161,9 +161,9 @@ const Announcement = ({ version, hideAnnouncement }: AnnouncementProps) => {
|
||||
aria-label="Previous Updates"
|
||||
classNames={{
|
||||
trigger: "bg-transparent border-0 pl-0 pb-0 w-fit",
|
||||
title: "font-bold text-[var(--vscode-foreground)]",
|
||||
title: "font-bold text-(--vscode-foreground)",
|
||||
indicator:
|
||||
"text-[var(--vscode-foreground)] mb-0.5 -rotate-180 data-[open=true]:-rotate-90 rtl:rotate-0 rtl:data-[open=true]:-rotate-90",
|
||||
"text-(--vscode-foreground) mb-0.5 -rotate-180 data-[open=true]:-rotate-90 rtl:rotate-0 rtl:data-[open=true]:-rotate-90",
|
||||
}}
|
||||
key="1"
|
||||
title="Previous Updates:">
|
||||
|
||||
@@ -8,7 +8,6 @@ import { useSize } from "react-use"
|
||||
import styled from "styled-components"
|
||||
import { BrowserSettingsMenu } from "@/components/browser/BrowserSettingsMenu"
|
||||
import { ChatRowContent, ProgressIndicator } from "@/components/chat/ChatRow"
|
||||
import { CheckpointControls } from "@/components/common/CheckpointControls"
|
||||
import CodeBlock, { CODE_BLOCK_BG_COLOR } from "@/components/common/CodeBlock"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { FileServiceClient } from "@/services/grpc-client"
|
||||
@@ -630,10 +629,6 @@ const BrowserCursor: React.FC<{ style?: CSSProperties }> = ({ style }) => {
|
||||
const BrowserSessionRowContainer = styled.div`
|
||||
padding: 10px 6px 10px 15px;
|
||||
position: relative;
|
||||
|
||||
&:hover ${CheckpointControls} {
|
||||
opacity: 1;
|
||||
}
|
||||
`
|
||||
|
||||
export default BrowserSessionRow
|
||||
|
||||
@@ -27,7 +27,6 @@ import McpToolRow from "@/components/mcp/configuration/tabs/installed/server-row
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { FileServiceClient, TaskServiceClient, UiServiceClient } from "@/services/grpc-client"
|
||||
import { findMatchingResourceOrTemplate, getMcpServerDisplayName } from "@/utils/mcp"
|
||||
import { CheckpointControls } from "../common/CheckpointControls"
|
||||
import CodeAccordian, { cleanPathPrefix } from "../common/CodeAccordian"
|
||||
import { ErrorBlockTitle } from "./ErrorBlockTitle"
|
||||
import ErrorRow from "./ErrorRow"
|
||||
@@ -45,10 +44,6 @@ const _cancelledColor = "var(--vscode-descriptionForeground)"
|
||||
const ChatRowContainer = styled.div`
|
||||
padding: 10px 6px 10px 15px;
|
||||
position: relative;
|
||||
|
||||
&:hover ${CheckpointControls} {
|
||||
opacity: 1;
|
||||
}
|
||||
`
|
||||
|
||||
interface ChatRowProps {
|
||||
@@ -1401,7 +1396,7 @@ export const ChatRowContent = memo(
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div>
|
||||
{title && (
|
||||
<div style={headerStyle}>
|
||||
{icon}
|
||||
@@ -1409,10 +1404,10 @@ export const ChatRowContent = memo(
|
||||
</div>
|
||||
)}
|
||||
<WithCopyButton
|
||||
className="pt-2.5"
|
||||
onMouseUp={handleMouseUp}
|
||||
position="bottom-right"
|
||||
ref={contentRef}
|
||||
style={{ paddingTop: 10 }}
|
||||
textToCopy={question}>
|
||||
<Markdown markdown={question} />
|
||||
<OptionsButtons
|
||||
@@ -1434,7 +1429,7 @@ export const ChatRowContent = memo(
|
||||
/>
|
||||
)}
|
||||
</WithCopyButton>
|
||||
</>
|
||||
</div>
|
||||
)
|
||||
case "new_task":
|
||||
return (
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { cn } from "@heroui/react"
|
||||
import { PulsingBorder } from "@paper-design/shaders-react"
|
||||
import { mentionRegex, mentionRegexGlobal } from "@shared/context-mentions"
|
||||
import { EmptyRequest, StringRequest } from "@shared/proto/cline/common"
|
||||
@@ -19,12 +18,13 @@ import { CHAT_CONSTANTS } from "@/components/chat/chat-view/constants"
|
||||
import SlashCommandMenu from "@/components/chat/SlashCommandMenu"
|
||||
import { CODE_BLOCK_BG_COLOR } from "@/components/common/CodeBlock"
|
||||
import Thumbnails from "@/components/common/Thumbnails"
|
||||
import Tooltip from "@/components/common/Tooltip"
|
||||
import ApiOptions from "@/components/settings/ApiOptions"
|
||||
import { getModeSpecificFields, normalizeApiConfiguration } from "@/components/settings/utils/providerUtils"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { useClineAuth } from "@/context/ClineAuthContext"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { usePlatform } from "@/context/PlatformContext"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { FileServiceClient, ModelsServiceClient, StateServiceClient } from "@/services/grpc-client"
|
||||
import {
|
||||
ContextMenuOptionType,
|
||||
@@ -589,13 +589,13 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
||||
}
|
||||
|
||||
// Find the index of the next selectable option
|
||||
const currentSelectableIndex = selectableOptions.findIndex((option) => option === options[prevIndex])
|
||||
const currentSelectableIndex = selectableOptions.indexOf(options[prevIndex])
|
||||
|
||||
const newSelectableIndex =
|
||||
(currentSelectableIndex + direction + selectableOptions.length) % selectableOptions.length
|
||||
|
||||
// Find the index of the selected option in the original options array
|
||||
return options.findIndex((option) => option === selectableOptions[newSelectableIndex])
|
||||
return options.indexOf(selectableOptions[newSelectableIndex])
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -1622,7 +1622,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
||||
value={inputValue}
|
||||
/>
|
||||
{!inputValue && selectedImages.length === 0 && selectedFiles.length === 0 && (
|
||||
<div className="text-[10px] absolute bottom-5 left-5 right-16 text-[var(--vscode-input-placeholderForeground)]/50 whitespace-nowrap overflow-hidden text-ellipsis pointer-events-none z-1">
|
||||
<div className="text-xs absolute bottom-5 left-6.5 right-16 text-(--vscode-input-placeholderForeground)/50 whitespace-nowrap overflow-hidden text-ellipsis pointer-events-none z-1">
|
||||
Type @ for context, / for slash commands & workflows, hold shift to drag in files/images
|
||||
</div>
|
||||
)}
|
||||
@@ -1708,35 +1708,41 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
||||
<div className="relative flex-1 min-w-0 h-5">
|
||||
{/* ButtonGroup - always in DOM but visibility controlled */}
|
||||
<ButtonGroup className="absolute top-0 left-0 right-0 ease-in-out w-full h-5 z-10 flex items-center">
|
||||
<Tooltip style={{ left: 0 }} tipText="Add Context">
|
||||
<VSCodeButton
|
||||
appearance="icon"
|
||||
aria-label="Add Context"
|
||||
className="p-0 m-0 flex items-center"
|
||||
data-testid="context-button"
|
||||
onClick={handleContextButtonClick}>
|
||||
<ButtonContainer>
|
||||
<AtSignIcon size={12} />
|
||||
</ButtonContainer>
|
||||
</VSCodeButton>
|
||||
<Tooltip>
|
||||
<TooltipContent>Add Context</TooltipContent>
|
||||
<TooltipTrigger>
|
||||
<VSCodeButton
|
||||
appearance="icon"
|
||||
aria-label="Add Context"
|
||||
className="p-0 m-0 flex items-center mt-0.5"
|
||||
data-testid="context-button"
|
||||
onClick={handleContextButtonClick}>
|
||||
<ButtonContainer>
|
||||
<AtSignIcon size={12} />
|
||||
</ButtonContainer>
|
||||
</VSCodeButton>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip tipText="Add Files & Images">
|
||||
<VSCodeButton
|
||||
appearance="icon"
|
||||
aria-label="Add Files & Images"
|
||||
className="p-0 m-0 flex items-center"
|
||||
data-testid="files-button"
|
||||
disabled={shouldDisableFilesAndImages}
|
||||
onClick={() => {
|
||||
if (!shouldDisableFilesAndImages) {
|
||||
onSelectFilesAndImages()
|
||||
}
|
||||
}}>
|
||||
<ButtonContainer>
|
||||
<PlusIcon size={13} />
|
||||
</ButtonContainer>
|
||||
</VSCodeButton>
|
||||
<Tooltip>
|
||||
<TooltipContent>Add Files & Images</TooltipContent>
|
||||
<TooltipTrigger>
|
||||
<VSCodeButton
|
||||
appearance="icon"
|
||||
aria-label="Add Files & Images"
|
||||
className="p-0 m-0 flex items-center mt-0.5"
|
||||
data-testid="files-button"
|
||||
disabled={shouldDisableFilesAndImages}
|
||||
onClick={() => {
|
||||
if (!shouldDisableFilesAndImages) {
|
||||
onSelectFilesAndImages()
|
||||
}
|
||||
}}>
|
||||
<ButtonContainer>
|
||||
<PlusIcon size={13} />
|
||||
</ButtonContainer>
|
||||
</VSCodeButton>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
<ServersToggleModal />
|
||||
<ClineRulesToggleModal />
|
||||
@@ -1749,7 +1755,7 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
title="Select Model / API Provider">
|
||||
<ModelButtonContent>{modelDisplayName}</ModelButtonContent>
|
||||
<ModelButtonContent className="text-xs">{modelDisplayName}</ModelButtonContent>
|
||||
</ModelDisplayButton>
|
||||
</ModelButtonWrapper>
|
||||
{showModelSelector && (
|
||||
@@ -1772,30 +1778,38 @@ const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
|
||||
</ButtonGroup>
|
||||
</div>
|
||||
{/* Tooltip for Plan/Act toggle remains outside the conditional rendering */}
|
||||
<Tooltip
|
||||
hintText={`Toggle w/ ${togglePlanActKeys}`}
|
||||
style={{ zIndex: 1000 }}
|
||||
tipText={`In ${shownTooltipMode === "act" ? "Act" : "Plan"} mode, Cline will ${shownTooltipMode === "act" ? "complete the task immediately" : "gather information to architect a plan"}`}
|
||||
visible={shownTooltipMode !== null}>
|
||||
<SwitchContainer data-testid="mode-switch" disabled={false} onClick={onModeToggle}>
|
||||
<Slider isAct={mode === "act"} isPlan={mode === "plan"} />
|
||||
<SwitchOption
|
||||
aria-checked={mode === "plan"}
|
||||
isActive={mode === "plan"}
|
||||
onMouseLeave={() => setShownTooltipMode(null)}
|
||||
onMouseOver={() => setShownTooltipMode("plan")}
|
||||
role="switch">
|
||||
Plan
|
||||
</SwitchOption>
|
||||
<SwitchOption
|
||||
aria-checked={mode === "act"}
|
||||
isActive={mode === "act"}
|
||||
onMouseLeave={() => setShownTooltipMode(null)}
|
||||
onMouseOver={() => setShownTooltipMode("act")}
|
||||
role="switch">
|
||||
Act
|
||||
</SwitchOption>
|
||||
</SwitchContainer>
|
||||
<Tooltip>
|
||||
<TooltipContent
|
||||
className="text-xs text-description p-2 flex flex-col gap-1"
|
||||
hidden={shownTooltipMode === null}
|
||||
side="top">
|
||||
{`In ${shownTooltipMode === "act" ? "Act" : "Plan"} mode, Cline will ${shownTooltipMode === "act" ? "complete the task immediately" : "gather information to architect a plan"}`}
|
||||
<p className="text-description/80 text-xs">
|
||||
Toggle w/ <kbd className="text-muted-foreground mx-1">{togglePlanActKeys}</kbd>
|
||||
</p>
|
||||
</TooltipContent>
|
||||
|
||||
<TooltipTrigger>
|
||||
<SwitchContainer data-testid="mode-switch" disabled={false} onClick={onModeToggle}>
|
||||
<Slider isAct={mode === "act"} isPlan={mode === "plan"} />
|
||||
<SwitchOption
|
||||
aria-checked={mode === "plan"}
|
||||
isActive={mode === "plan"}
|
||||
onMouseLeave={() => setShownTooltipMode(null)}
|
||||
onMouseOver={() => setShownTooltipMode("plan")}
|
||||
role="switch">
|
||||
Plan
|
||||
</SwitchOption>
|
||||
<SwitchOption
|
||||
aria-checked={mode === "act"}
|
||||
isActive={mode === "act"}
|
||||
onMouseLeave={() => setShownTooltipMode(null)}
|
||||
onMouseOver={() => setShownTooltipMode("act")}
|
||||
role="switch">
|
||||
Act
|
||||
</SwitchOption>
|
||||
</SwitchContainer>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -366,7 +366,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
<footer className="bg-[var(--vscode-sidebar-background)]" style={{ gridRow: "2" }}>
|
||||
<footer className="bg-(--vscode-sidebar-background)" style={{ gridRow: "2" }}>
|
||||
<AutoApproveBar />
|
||||
<ActionButtons
|
||||
chatState={chatState}
|
||||
|
||||
@@ -50,7 +50,7 @@ const CreditLimitError: React.FC<CreditLimitErrorProps> = ({
|
||||
|
||||
// We have to divide because the balance is stored in microcredits
|
||||
return (
|
||||
<div className="p-2 border-none rounded-md mb-2 bg-[var(--vscode-textBlockQuote-background)]">
|
||||
<div className="p-2 border-none rounded-md mb-2 bg-(--vscode-textBlockQuote-background)">
|
||||
<div className="mb-3 font-azeret-mono">
|
||||
<div className="text-error mb-2">{message}</div>
|
||||
<div className="mb-3">
|
||||
|
||||
@@ -29,14 +29,14 @@ export const ErrorBlockTitle = ({
|
||||
const icon =
|
||||
apiReqCancelReason != null ? (
|
||||
apiReqCancelReason === "user_cancelled" ? (
|
||||
getIconSpan("error", "text-[var(--vscode-descriptionForeground)]")
|
||||
getIconSpan("error", "text-(--vscode-descriptionForeground)")
|
||||
) : (
|
||||
getIconSpan("error", "text-[var(--vscode-errorForeground)]")
|
||||
getIconSpan("error", "text-(--vscode-errorForeground)")
|
||||
)
|
||||
) : cost != null ? (
|
||||
getIconSpan("check", "text-[var(--vscode-charts-green)]")
|
||||
getIconSpan("check", "text-(--vscode-charts-green)")
|
||||
) : apiRequestFailedMessage ? (
|
||||
getIconSpan("error", "text-[var(--vscode-errorForeground)]")
|
||||
getIconSpan("error", "text-(--vscode-errorForeground)")
|
||||
) : (
|
||||
<ProgressIndicator />
|
||||
)
|
||||
@@ -47,20 +47,20 @@ export const ErrorBlockTitle = ({
|
||||
// Handle cancellation states first
|
||||
if (apiReqCancelReason === "user_cancelled") {
|
||||
details.title = "API Request Cancelled"
|
||||
details.classNames.push("text-[var(--vscode-foreground)]")
|
||||
details.classNames.push("text-(--vscode-foreground)")
|
||||
} else if (apiReqCancelReason != null) {
|
||||
details.title = "API Request Failed"
|
||||
details.classNames.push("text-[var(--vscode-errorForeground)]")
|
||||
details.classNames.push("text-(--vscode-errorForeground)")
|
||||
} else if (cost != null) {
|
||||
// Handle completed request
|
||||
details.title = "API Request"
|
||||
details.classNames.push("text-[var(--vscode-foreground)]")
|
||||
details.classNames.push("text-(--vscode-foreground)")
|
||||
} else if (apiRequestFailedMessage) {
|
||||
// Handle failed request
|
||||
const clineError = ClineError.parse(apiRequestFailedMessage)
|
||||
const titleText = clineError?.isErrorType(ClineErrorType.Balance) ? "Credit Limit Reached" : "API Request Failed"
|
||||
details.title = titleText
|
||||
details.classNames.push("font-bold text-[var(--vscode-errorForeground)]")
|
||||
details.classNames.push("font-bold text-(--vscode-errorForeground)")
|
||||
} else if (retryStatus) {
|
||||
// Handle retry state
|
||||
details.title = "API Request"
|
||||
|
||||
@@ -47,7 +47,7 @@ const ErrorRow = memo(({ message, errorType, apiRequestFailedMessage, apiReqStre
|
||||
|
||||
if (clineError?.isErrorType(ClineErrorType.RateLimit)) {
|
||||
return (
|
||||
<p className="m-0 whitespace-pre-wrap text-[var(--vscode-errorForeground)] wrap-anywhere">
|
||||
<p className="m-0 whitespace-pre-wrap text-(--vscode-errorForeground) wrap-anywhere">
|
||||
{clineErrorMessage}
|
||||
{requestId && <div>Request ID: {requestId}</div>}
|
||||
</p>
|
||||
@@ -61,7 +61,7 @@ const ErrorRow = memo(({ message, errorType, apiRequestFailedMessage, apiReqStre
|
||||
|
||||
// Default error display
|
||||
return (
|
||||
<p className="m-0 whitespace-pre-wrap text-[var(--vscode-errorForeground)] wrap-anywhere">
|
||||
<p className="m-0 whitespace-pre-wrap text-(--vscode-errorForeground) wrap-anywhere">
|
||||
{errorMessageToDisplay}
|
||||
{requestId && <div>Request ID: {requestId}</div>}
|
||||
{clineErrorMessage?.toLowerCase()?.includes("powershell") && (
|
||||
@@ -83,9 +83,7 @@ const ErrorRow = memo(({ message, errorType, apiRequestFailedMessage, apiReqStre
|
||||
<br />
|
||||
{/* The user is signed in or not using cline provider */}
|
||||
{clineUser && !isClineProvider ? (
|
||||
<span className="mb-4 text-[var(--vscode-descriptionForeground)]">
|
||||
(Click "Retry" below)
|
||||
</span>
|
||||
<span className="mb-4 text-(--vscode-descriptionForeground)">(Click "Retry" below)</span>
|
||||
) : (
|
||||
<VSCodeButton className="w-full mb-4" onClick={handleSignIn}>
|
||||
Sign in to Cline
|
||||
@@ -98,20 +96,18 @@ const ErrorRow = memo(({ message, errorType, apiRequestFailedMessage, apiReqStre
|
||||
}
|
||||
|
||||
// Regular error message
|
||||
return (
|
||||
<p className="m-0 whitespace-pre-wrap text-[var(--vscode-errorForeground)] wrap-anywhere">{message.text}</p>
|
||||
)
|
||||
return <p className="m-0 whitespace-pre-wrap text-(--vscode-errorForeground) wrap-anywhere">{message.text}</p>
|
||||
|
||||
case "diff_error":
|
||||
return (
|
||||
<div className="flex flex-col p-2 rounded text-xs opacity-80 bg-[var(--vscode-textBlockQuote-background)] text-[var(--vscode-foreground)]">
|
||||
<div className="flex flex-col p-2 rounded text-xs opacity-80 bg-(--vscode-textBlockQuote-background) text-(--vscode-foreground)">
|
||||
<div>The model used search patterns that don't match anything in the file. Retrying...</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
case "clineignore_error":
|
||||
return (
|
||||
<div className="flex flex-col p-2 rounded text-xs bg-[var(--vscode-textBlockQuote-background)] text-[var(--vscode-foreground)] opacity-80">
|
||||
<div className="flex flex-col p-2 rounded text-xs bg-(--vscode-textBlockQuote-background) text-(--vscode-foreground) opacity-80">
|
||||
<div>
|
||||
Cline tried to access <code>{message.text}</code> which is blocked by the <code>.clineignore</code>
|
||||
file.
|
||||
|
||||
@@ -7,7 +7,7 @@ interface NewTaskPreviewProps {
|
||||
|
||||
const NewTaskPreview: React.FC<NewTaskPreviewProps> = ({ context }) => {
|
||||
return (
|
||||
<div className="bg-[var(--vscode-badge-background)] text-[var(--vscode-badge-foreground)] rounded-[3px] p-[14px] pb-[6px]">
|
||||
<div className="bg-(--vscode-badge-background) text-(--vscode-badge-foreground) rounded-[3px] p-[14px] pb-[6px]">
|
||||
<span style={{ fontWeight: "bold" }}>Task</span>
|
||||
<MarkdownBlock markdown={context} />
|
||||
</div>
|
||||
|
||||
@@ -28,7 +28,7 @@ const ContentRow = styled.div`
|
||||
`
|
||||
|
||||
const TextContainer = styled.div`
|
||||
flex-grow: 1;
|
||||
grow: 1;
|
||||
margin: 0 2px; /* Further reduced space around text */
|
||||
white-space: pre-wrap;
|
||||
word-break: break-word;
|
||||
@@ -45,7 +45,7 @@ const TextContainer = styled.div`
|
||||
|
||||
const DismissButton = styled(VSCodeButton)`
|
||||
/* margin-left: auto; */ /* Removed as ContentRow handles spacing */
|
||||
flex-shrink: 0; /* Prevent button from shrinking */
|
||||
shrink: 0; /* Prevent button from shrinking */
|
||||
min-width: 22px;
|
||||
height: 22px;
|
||||
padding: 0;
|
||||
@@ -58,7 +58,7 @@ const DismissButton = styled(VSCodeButton)`
|
||||
const ReplyIcon = styled.span`
|
||||
color: var(--vscode-descriptionForeground);
|
||||
margin-right: 2px; /* Further reduced space between icon and text */
|
||||
flex-shrink: 0;
|
||||
shrink: 0;
|
||||
font-size: 13px; /* Make icon even smaller */
|
||||
/* transform: translateY(-1px); */ /* Removed vertical transform */
|
||||
`
|
||||
|
||||
@@ -17,7 +17,7 @@ const ReportBugPreview: React.FC<ReportBugPreviewProps> = ({ data }) => {
|
||||
}, [data])
|
||||
|
||||
return (
|
||||
<div className="bg-[var(--vscode-badge-background)] text-[var(--vscode-badge-foreground)] rounded-[3px] p-[14px]">
|
||||
<div className="bg-(--vscode-badge-background) text-(--vscode-badge-foreground) rounded-[3px] p-[14px]">
|
||||
<h3 className="font-bold text-base mb-3 mt-0">{bugData.title || "Bug Report"}</h3>
|
||||
|
||||
<div className="space-y-3 text-sm">
|
||||
|
||||
@@ -2,39 +2,16 @@ import { EmptyRequest } from "@shared/proto/cline/common"
|
||||
import { McpServers } from "@shared/proto/cline/mcp"
|
||||
import { convertProtoMcpServersToMcpServers } from "@shared/proto-conversions/mcp/mcp-server-conversion"
|
||||
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
|
||||
import React, { useEffect, useRef, useState } from "react"
|
||||
import { useClickAway, useWindowSize } from "react-use"
|
||||
import { CODE_BLOCK_BG_COLOR } from "@/components/common/CodeBlock"
|
||||
import Tooltip from "@/components/common/Tooltip"
|
||||
import React, { useEffect, useState } from "react"
|
||||
import ServersToggleList from "@/components/mcp/configuration/tabs/installed/ServersToggleList"
|
||||
import { Popover, PopoverContent, PopoverTrigger } from "@/components/ui/popover"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { McpServiceClient } from "@/services/grpc-client"
|
||||
|
||||
const ServersToggleModal: React.FC = () => {
|
||||
const { mcpServers, navigateToMcp, setMcpServers } = useExtensionState()
|
||||
const [isVisible, setIsVisible] = useState(false)
|
||||
const buttonRef = useRef<HTMLDivElement>(null)
|
||||
const modalRef = useRef<HTMLDivElement>(null)
|
||||
const { width: viewportWidth, height: viewportHeight } = useWindowSize()
|
||||
const [arrowPosition, setArrowPosition] = useState(0)
|
||||
const [menuPosition, setMenuPosition] = useState(0)
|
||||
|
||||
// Close modal when clicking outside
|
||||
useClickAway(modalRef, () => {
|
||||
setIsVisible(false)
|
||||
})
|
||||
|
||||
// Calculate positions for modal and arrow
|
||||
useEffect(() => {
|
||||
if (isVisible && buttonRef.current) {
|
||||
const buttonRect = buttonRef.current.getBoundingClientRect()
|
||||
const buttonCenter = buttonRect.left + buttonRect.width / 2
|
||||
const rightPosition = document.documentElement.clientWidth - buttonCenter - 5
|
||||
|
||||
setArrowPosition(rightPosition)
|
||||
setMenuPosition(buttonRect.top + 1)
|
||||
}
|
||||
}, [isVisible, viewportWidth, viewportHeight])
|
||||
|
||||
useEffect(() => {
|
||||
if (isVisible) {
|
||||
@@ -52,61 +29,48 @@ const ServersToggleModal: React.FC = () => {
|
||||
}, [isVisible])
|
||||
|
||||
return (
|
||||
<div ref={modalRef}>
|
||||
<div className="inline-flex min-w-0 max-w-full" ref={buttonRef}>
|
||||
<Tooltip tipText="Manage MCP Servers" visible={isVisible ? false : undefined}>
|
||||
<VSCodeButton
|
||||
appearance="icon"
|
||||
aria-label={isVisible ? "Hide MCP Servers" : "Show MCP Servers"}
|
||||
onClick={() => setIsVisible(!isVisible)}
|
||||
style={{ padding: "0px 0px", height: "20px" }}>
|
||||
<div className="flex items-center gap-1 text-xs whitespace-nowrap min-w-0 w-full">
|
||||
<span
|
||||
className="codicon codicon-server flex items-center"
|
||||
style={{ fontSize: "12.5px", marginBottom: 1 }}
|
||||
/>
|
||||
</div>
|
||||
</VSCodeButton>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
{isVisible && (
|
||||
<div
|
||||
className="fixed left-[15px] right-[15px] border border-[var(--vscode-editorGroup-border)] p-3 rounded z-[1000] overflow-y-auto"
|
||||
style={{
|
||||
bottom: `calc(100vh - ${menuPosition}px + 6px)`,
|
||||
background: CODE_BLOCK_BG_COLOR,
|
||||
maxHeight: "calc(100vh - 100px)",
|
||||
overscrollBehavior: "contain",
|
||||
}}>
|
||||
<div
|
||||
className="fixed w-[10px] h-[10px] z-[-1] rotate-45 border-r border-b border-[var(--vscode-editorGroup-border)]"
|
||||
style={{
|
||||
bottom: `calc(100vh - ${menuPosition}px)`,
|
||||
right: arrowPosition,
|
||||
background: CODE_BLOCK_BG_COLOR,
|
||||
}}
|
||||
/>
|
||||
|
||||
<div className="flex justify-between items-center mb-2.5">
|
||||
<div className="m-0 text-base font-semibold">MCP Servers</div>
|
||||
<Popover onOpenChange={(isModalOpened) => setIsVisible(isModalOpened)}>
|
||||
<PopoverTrigger>
|
||||
<Tooltip>
|
||||
<TooltipContent hidden={isVisible} side="top">
|
||||
Manage MCP Servers
|
||||
</TooltipContent>
|
||||
<TooltipTrigger asChild>
|
||||
<VSCodeButton
|
||||
appearance="icon"
|
||||
aria-label="Go to MCP server settings"
|
||||
onClick={() => {
|
||||
setIsVisible(false)
|
||||
navigateToMcp("configure")
|
||||
}}>
|
||||
<span className="codicon codicon-gear text-[10px]"></span>
|
||||
aria-label={isVisible ? "Hide MCP Servers" : "Show MCP Servers"}
|
||||
onClick={() => setIsVisible(!isVisible)}
|
||||
style={{ padding: "0px 0px", height: "20px" }}>
|
||||
<div className="flex items-center gap-1 text-xs whitespace-nowrap min-w-0 w-full">
|
||||
<span
|
||||
className="codicon codicon-server flex items-center"
|
||||
style={{ fontSize: "12.5px", marginBottom: 1 }}
|
||||
/>
|
||||
</div>
|
||||
</VSCodeButton>
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
</PopoverTrigger>
|
||||
|
||||
<div style={{ marginBottom: -10 }}>
|
||||
<ServersToggleList hasTrashIcon={false} isExpandable={false} listGap="small" servers={mcpServers} />
|
||||
</div>
|
||||
<PopoverContent className="mx-3 h-full wrap-break-word text-foreground w-[94vw]" side="top">
|
||||
<div className="flex justify-between items-center mb-2.5">
|
||||
<div className="m-0 text-base font-semibold">MCP Servers</div>
|
||||
<VSCodeButton
|
||||
appearance="icon"
|
||||
aria-label="Go to MCP server settings"
|
||||
onClick={() => {
|
||||
setIsVisible(false)
|
||||
navigateToMcp("configure")
|
||||
}}>
|
||||
<span className="codicon codicon-gear text-[10px]"></span>
|
||||
</VSCodeButton>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div style={{ marginBottom: -10 }}>
|
||||
<ServersToggleList hasTrashIcon={false} isExpandable={false} listGap="small" servers={mcpServers} />
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -58,18 +58,18 @@ const SlashCommandMenu: React.FC<SlashCommandMenuProps> = ({
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="text-xs text-[var(--vscode-descriptionForeground)] px-3 py-1 font-bold border-b border-[var(--vscode-editorGroup-border)]">
|
||||
<div className="text-xs text-(--vscode-descriptionForeground) px-3 py-1 font-bold border-b border-(--vscode-editorGroup-border)">
|
||||
{title}
|
||||
</div>
|
||||
{commands.map((command, index) => {
|
||||
const itemIndex = index + indexOffset
|
||||
return (
|
||||
<div
|
||||
className={`slash-command-menu-item py-2 px-3 cursor-pointer flex flex-col border-b border-[var(--vscode-editorGroup-border)] ${
|
||||
className={`slash-command-menu-item py-2 px-3 cursor-pointer flex flex-col border-b border-(--vscode-editorGroup-border) ${
|
||||
itemIndex === selectedIndex
|
||||
? "bg-[var(--vscode-quickInputList-focusBackground)] text-[var(--vscode-quickInputList-focusForeground)]"
|
||||
? "bg-(--vscode-quickInputList-focusBackground) text-(--vscode-quickInputList-focusForeground)"
|
||||
: ""
|
||||
} hover:bg-[var(--vscode-list-hoverBackground)]`}
|
||||
} hover:bg-(--vscode-list-hoverBackground)`}
|
||||
id={`slash-command-menu-item-${itemIndex}`}
|
||||
key={command.name}
|
||||
onClick={() => handleClick(command)}
|
||||
@@ -78,7 +78,7 @@ const SlashCommandMenu: React.FC<SlashCommandMenuProps> = ({
|
||||
<span className="ph-no-capture">/{command.name}</span>
|
||||
</div>
|
||||
{showDescriptions && command.description && (
|
||||
<div className="text-[0.85em] text-[var(--vscode-descriptionForeground)] whitespace-normal overflow-hidden text-ellipsis">
|
||||
<div className="text-[0.85em] text-(--vscode-descriptionForeground) whitespace-normal overflow-hidden text-ellipsis">
|
||||
<span className="ph-no-capture">{command.description}</span>
|
||||
</div>
|
||||
)}
|
||||
@@ -91,10 +91,10 @@ const SlashCommandMenu: React.FC<SlashCommandMenuProps> = ({
|
||||
|
||||
return (
|
||||
<div
|
||||
className="absolute bottom-[calc(100%-10px)] left-[15px] right-[15px] overflow-x-hidden z-[1000]"
|
||||
className="absolute bottom-[calc(100%-10px)] left-[15px] right-[15px] overflow-x-hidden z-1000"
|
||||
onMouseDown={onMouseDown}>
|
||||
<div
|
||||
className="bg-[var(--vscode-dropdown-background)] border border-[var(--vscode-editorGroup-border)] rounded-[3px] shadow-[0_4px_10px_rgba(0,0,0,0.25)] flex flex-col overflow-y-auto"
|
||||
className="bg-(--vscode-dropdown-background) border border-(--vscode-editorGroup-border) rounded-[3px] shadow-[0_4px_10px_rgba(0,0,0,0.25)] flex flex-col overflow-y-auto"
|
||||
ref={menuRef}
|
||||
style={{ maxHeight: "min(200px, calc(50vh))", overscrollBehavior: "contain" }}>
|
||||
{filteredCommands.length > 0 ? (
|
||||
@@ -104,7 +104,7 @@ const SlashCommandMenu: React.FC<SlashCommandMenuProps> = ({
|
||||
</>
|
||||
) : (
|
||||
<div className="py-2 px-3 cursor-default flex flex-col">
|
||||
<div className="text-[0.85em] text-[var(--vscode-descriptionForeground)]">No matching commands found</div>
|
||||
<div className="text-[0.85em] text-(--vscode-descriptionForeground)">No matching commands found</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { cn } from "@heroui/react"
|
||||
import { TranscribeAudioRequest } from "@shared/proto/cline/dictation"
|
||||
import { EmptyRequest } from "@shared/proto/index.cline"
|
||||
import { SquareIcon, StopCircleIcon } from "lucide-react"
|
||||
import React, { useCallback, useEffect, useRef, useState } from "react"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { DictationServiceClient } from "@/services/grpc-client"
|
||||
import { formatSeconds } from "@/utils/format"
|
||||
import HeroTooltip from "../common/HeroTooltip"
|
||||
|
||||
interface VoiceRecorderProps {
|
||||
onTranscription: (text: string) => void
|
||||
@@ -240,40 +241,50 @@ const VoiceRecorder: React.FC<VoiceRecorderProps> = ({
|
||||
? "Starting recording..."
|
||||
: error
|
||||
? `Error: ${error}`
|
||||
: null
|
||||
: "Voice Input"
|
||||
|
||||
return (
|
||||
<HeroTooltip content={tooltipContent} placement="top">
|
||||
<div
|
||||
className={`input-icon-button mr-1.5 text-base ${iconAdjustment} ${iconAnimation} ${disabled || isProcessing || isStarting ? "disabled" : ""}`}
|
||||
onClick={handleStartClick}
|
||||
style={{ color: iconColor }}>
|
||||
<span className={`codicon ${iconClass}`} />
|
||||
</div>
|
||||
</HeroTooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<div
|
||||
className={`input-icon-button mr-1.5 text-base ${iconAdjustment} ${iconAnimation} ${disabled || isProcessing || isStarting ? "disabled" : ""}`}
|
||||
onClick={handleStartClick}
|
||||
style={{ color: iconColor }}>
|
||||
<span className={`codicon ${iconClass}`} />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="top">{tooltipContent}</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={`flex items-center ${isRecording ? "mr-0.5" : "mr-1.5"}`}>
|
||||
<HeroTooltip
|
||||
content={`Stop Recording (${formatSeconds(recordingDuration)}/${formatSeconds(MAX_DURATION)})`}
|
||||
placement="top">
|
||||
<div
|
||||
className={cn("input-icon-button mr-1.5 text-error", iconAdjustment, iconAnimation, {
|
||||
disabled: disabled || isProcessing,
|
||||
})}
|
||||
onClick={handleStopClick}>
|
||||
<span className="codicon codicon-stop-circle" />
|
||||
</div>
|
||||
</HeroTooltip>
|
||||
<HeroTooltip content="Cancel Recording" placement="top">
|
||||
<div
|
||||
className={`input-icon-button text-base ${isRecording ? "mt-0.5" : "mt-1"} text-foreground ${disabled || isProcessing ? "disabled" : ""}`}
|
||||
onClick={handleCancelClick}>
|
||||
<span className="codicon codicon-close" />
|
||||
</div>
|
||||
</HeroTooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<div
|
||||
className={cn("input-icon-button mr-1.5 text-base", iconAdjustment, iconAnimation, {
|
||||
disabled: disabled || isProcessing,
|
||||
})}
|
||||
onClick={handleStopClick}>
|
||||
<StopCircleIcon />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="top">
|
||||
Stop Recording ({formatSeconds(recordingDuration)}/{formatSeconds(MAX_DURATION)})
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<div
|
||||
className={`input-icon-button text-base mt-1 text-foreground ${disabled || isProcessing ? "disabled" : ""}`}
|
||||
onClick={handleCancelClick}>
|
||||
<SquareIcon />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="top">Cancel Recording</TooltipContent>
|
||||
</Tooltip>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -58,12 +58,12 @@ const AutoApproveBar = ({ style }: AutoApproveBarProps) => {
|
||||
return [
|
||||
...favorites.map((favId) => renderFavoritedItem(favId)),
|
||||
minusFavorites.length > 0 ? (
|
||||
<span className="text-[color:var(--vscode-foreground-muted)] pl-[10px] opacity-60" key="separator">
|
||||
<span className="text-muted opacity-60" key="separator">
|
||||
✓
|
||||
</span>
|
||||
) : null,
|
||||
...minusFavorites.map((action, index) => (
|
||||
<span className="text-[color:var(--vscode-foreground-muted)] opacity-60" key={action?.id}>
|
||||
<span className="text-muted opacity-60" key={action?.id}>
|
||||
{action?.shortName}
|
||||
{index < minusFavorites.length - 1 && ","}
|
||||
</span>
|
||||
@@ -73,21 +73,20 @@ const AutoApproveBar = ({ style }: AutoApproveBarProps) => {
|
||||
|
||||
return (
|
||||
<div
|
||||
className="px-[10px] mx-[15px] select-none rounded-[10px_10px_0_0]"
|
||||
className="px-3.5 mx-3.5 select-none rounded-tl-sm rounded-tr-sm overflow-y-auto break-words"
|
||||
style={{
|
||||
borderTop: `0.5px solid color-mix(in srgb, ${getAsVar(VSC_TITLEBAR_INACTIVE_FOREGROUND)} 20%, transparent)`,
|
||||
overflowY: "auto",
|
||||
backgroundColor: isModalVisible ? CODE_BLOCK_BG_COLOR : "transparent",
|
||||
...style,
|
||||
}}>
|
||||
<div
|
||||
className="cursor-pointer py-[8px] pr-[2px] flex items-center justify-between gap-[8px]"
|
||||
className="cursor-pointer py-1 pr-1 flex items-center justify-between gap-2"
|
||||
onClick={() => {
|
||||
setIsModalVisible((prev) => !prev)
|
||||
}}
|
||||
ref={buttonRef}>
|
||||
<div
|
||||
className="flex flex-nowrap items-center overflow-x-auto gap-[4px] whitespace-nowrap"
|
||||
className="flex flex-nowrap items-center overflow-x-auto gap-1 whitespace-nowrap"
|
||||
style={{
|
||||
msOverflowStyle: "none",
|
||||
scrollbarWidth: "none",
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react"
|
||||
import React from "react"
|
||||
import styled from "styled-components"
|
||||
import HeroTooltip from "@/components/common/HeroTooltip"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { ActionMetadata } from "./types"
|
||||
|
||||
interface AutoApproveMenuItemProps {
|
||||
@@ -14,46 +15,6 @@ interface AutoApproveMenuItemProps {
|
||||
showIcon?: boolean
|
||||
}
|
||||
|
||||
const CheckboxContainer = styled.div.withConfig({
|
||||
shouldForwardProp: (prop) => !["isFavorited"].includes(prop),
|
||||
})<{ isFavorited?: boolean; onClick?: (e: MouseEvent) => void; onMouseDown?: (e: React.MouseEvent) => void }>`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between; /* Push content to edges */
|
||||
padding-left: 4px;
|
||||
padding-right: 1px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
|
||||
&:hover {
|
||||
background-color: var(--vscode-textBlockQuote-background);
|
||||
}
|
||||
|
||||
.left-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
color: var(--vscode-foreground);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.label {
|
||||
color: var(--vscode-foreground);
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.star {
|
||||
color: ${(props) => (props.isFavorited ? "var(--vscode-terminal-ansiYellow)" : "var(--vscode-descriptionForeground)")};
|
||||
opacity: ${(props) => (props.isFavorited ? 1 : 0.6)};
|
||||
font-size: 14px;
|
||||
}
|
||||
`
|
||||
|
||||
const SubOptionAnimateIn = styled.div<{ show: boolean }>`
|
||||
position: relative;
|
||||
transform: ${(props) => (props.show ? "scaleY(1)" : "scaleY(0)")};
|
||||
@@ -87,36 +48,44 @@ const AutoApproveMenuItem = ({
|
||||
}
|
||||
|
||||
const content = (
|
||||
<>
|
||||
<ActionButtonContainer>
|
||||
<HeroTooltip content={action.description} delay={500}>
|
||||
<CheckboxContainer isFavorited={favorited} onClick={onChange}>
|
||||
<div className="left-content">
|
||||
<div className="w-full">
|
||||
<ActionButtonContainer className="w-full">
|
||||
<Tooltip>
|
||||
<TooltipContent>{action.description}</TooltipContent>
|
||||
<TooltipTrigger asChild>
|
||||
<Button
|
||||
className={cn("w-full flex text-sm items-center justify-start text-foreground gap-2")}
|
||||
onClick={(e) => onChange(e as unknown as Event)}
|
||||
size="icon"
|
||||
variant="icon">
|
||||
{onToggleFavorite && !condensed && (
|
||||
<HeroTooltip
|
||||
content={favorited ? "Remove from quick-access menu" : "Add to quick-access menu"}
|
||||
delay={500}>
|
||||
<span
|
||||
className={`p-0.5 codicon codicon-${favorited ? "star-full" : "star-empty"} star`}
|
||||
onClick={async (e) => {
|
||||
e.stopPropagation()
|
||||
if (action.id === "enableAll") {
|
||||
return
|
||||
}
|
||||
await onToggleFavorite?.(action.id)
|
||||
}}
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
}}
|
||||
/>
|
||||
</HeroTooltip>
|
||||
<Tooltip>
|
||||
<TooltipContent>
|
||||
{favorited ? "Remove from quick-access menu" : "Add to quick-access menu"}
|
||||
</TooltipContent>
|
||||
<TooltipTrigger asChild>
|
||||
<span
|
||||
className={cn("p-0.5 codicon", {
|
||||
"codicon-star-full text-(--vscode-terminal-ansiYellow)": favorited,
|
||||
"codicon-star-empty text-description opacity-60": !favorited,
|
||||
})}
|
||||
onClick={async (e) => {
|
||||
e.stopPropagation()
|
||||
if (action.id === "enableAll") {
|
||||
return
|
||||
}
|
||||
await onToggleFavorite?.(action.id)
|
||||
}}
|
||||
/>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
)}
|
||||
<VSCodeCheckbox checked={checked} />
|
||||
{showIcon && <span className={`codicon ${action.icon} icon`}></span>}
|
||||
<span className="label">{condensed ? action.shortName : action.label}</span>
|
||||
</div>
|
||||
</CheckboxContainer>
|
||||
</HeroTooltip>
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
</ActionButtonContainer>
|
||||
{action.subAction && !condensed && (
|
||||
<SubOptionAnimateIn show={checked}>
|
||||
@@ -129,7 +98,7 @@ const AutoApproveMenuItem = ({
|
||||
/>
|
||||
</SubOptionAnimateIn>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
)
|
||||
|
||||
return content
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { VSCodeButton, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
import { VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
import { XIcon } from "lucide-react"
|
||||
import React, { useEffect, useRef, useState } from "react"
|
||||
import { useClickAway, useWindowSize } from "react-use"
|
||||
import { CODE_BLOCK_BG_COLOR } from "@/components/common/CodeBlock"
|
||||
import HeroTooltip from "@/components/common/HeroTooltip"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { useAutoApproveActions } from "@/hooks/useAutoApproveActions"
|
||||
import { getAsVar, VSC_TITLEBAR_INACTIVE_FOREGROUND } from "@/utils/vscStyles"
|
||||
@@ -125,35 +127,38 @@ const AutoApproveModal: React.FC<AutoApproveModalProps> = ({
|
||||
return (
|
||||
<div className="overflow-hidden" ref={modalRef}>
|
||||
<div
|
||||
className="fixed left-[15px] right-[15px] border border-[var(--vscode-editorGroup-border)] rounded z-[1000] flex flex-col"
|
||||
className="fixed left-3.5 right-3.5 border border-(--vscode-editorGroup-border) rounded z-20 flex flex-col"
|
||||
style={calculateModalStyle()}>
|
||||
<div
|
||||
className="fixed w-[10px] h-[10px] z-[-1] rotate-45 border-r border-b border-[var(--vscode-editorGroup-border)]"
|
||||
className="fixed w-3.5 h-3.5 z-0 rotate-45 border-r border-b border-(--vscode-editorGroup-border) bg-code"
|
||||
style={{
|
||||
bottom: `calc(100vh - ${menuPosition}px)`,
|
||||
right: arrowPosition,
|
||||
background: CODE_BLOCK_BG_COLOR,
|
||||
}}
|
||||
/>
|
||||
{/* Scrollable content container */}
|
||||
<div className="overflow-y-auto p-3 flex-1 min-h-0 overscroll-contain">
|
||||
<div className="flex justify-between items-center mb-3">
|
||||
<HeroTooltip
|
||||
content="Auto-approve allows Cline to perform the following actions without asking for permission. Please use with caution and only enable if you understand the risks."
|
||||
placement="top">
|
||||
<div className="text-base font-semibold mb-1">Auto-approve Settings</div>
|
||||
</HeroTooltip>
|
||||
<VSCodeButton appearance="icon" onClick={() => setIsVisible(false)}>
|
||||
<span className="codicon codicon-close text-[10px]"></span>
|
||||
</VSCodeButton>
|
||||
<div className="overflow-y-auto p-3 flex-1 min-h-0 overscroll-contain w-full">
|
||||
<div className="flex justify-between items-center mb-3 w-full">
|
||||
<Tooltip>
|
||||
<TooltipContent side="top">
|
||||
Auto-approve allows Cline to perform the following actions without asking for permission. Please
|
||||
use with caution and only enable if you understand the risks.
|
||||
</TooltipContent>
|
||||
<TooltipTrigger>
|
||||
<div className="text-md font-semibold mb-1">Auto-approve Settings</div>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
<Button onClick={() => setIsVisible(false)} variant="icon">
|
||||
<XIcon />
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="mb-2.5">
|
||||
<span className="text-[color:var(--vscode-foreground)] font-medium">Actions:</span>
|
||||
<span className="text-foreground font-medium">Actions:</span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="relative mb-6"
|
||||
className="relative mb-6 w-full"
|
||||
ref={itemsContainerRef}
|
||||
style={{
|
||||
columnCount: containerWidth > breakpoint ? 2 : 1,
|
||||
@@ -162,7 +167,7 @@ const AutoApproveModal: React.FC<AutoApproveModalProps> = ({
|
||||
{/* Vertical separator line - only visible in two-column mode */}
|
||||
{containerWidth > breakpoint && (
|
||||
<div
|
||||
className="absolute left-1/2 top-0 bottom-0 w-[0.5px] opacity-20"
|
||||
className="absolute left-1/2 top-0 bottom-0 opacity-20"
|
||||
style={{
|
||||
background: getAsVar(VSC_TITLEBAR_INACTIVE_FOREGROUND),
|
||||
transform: "translateX(-50%)", // Center the line
|
||||
@@ -184,7 +189,7 @@ const AutoApproveModal: React.FC<AutoApproveModalProps> = ({
|
||||
</div>
|
||||
|
||||
<div className="mb-2.5">
|
||||
<span className="text-[color:var(--vscode-foreground)] font-medium">Quick Settings:</span>
|
||||
<span className="font-medium">Quick Settings:</span>
|
||||
</div>
|
||||
|
||||
<AutoApproveMenuItem
|
||||
@@ -196,36 +201,40 @@ const AutoApproveModal: React.FC<AutoApproveModalProps> = ({
|
||||
onToggleFavorite={toggleFavorite}
|
||||
/>
|
||||
|
||||
<HeroTooltip
|
||||
content="Cline will automatically make this many API requests before asking for approval to proceed with the task."
|
||||
placement="top">
|
||||
<div className="flex items-center pl-1.5 my-2">
|
||||
<span className="codicon codicon-settings text-[#CCCCCC] text-[14px]" />
|
||||
<span className="text-[#CCCCCC] text-xs font-medium ml-2">Max Requests:</span>
|
||||
<VSCodeTextField
|
||||
className="flex-1 w-full pr-[35px] ml-4"
|
||||
onInput={async (e) => {
|
||||
const input = e.target as HTMLInputElement
|
||||
// Remove any non-numeric characters
|
||||
input.value = input.value.replace(/[^0-9]/g, "")
|
||||
const value = parseInt(input.value)
|
||||
if (!Number.isNaN(value) && value > 0) {
|
||||
await updateMaxRequests(value)
|
||||
}
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
// Prevent non-numeric keys (except for backspace, delete, arrows)
|
||||
if (
|
||||
!/^\d$/.test(e.key) &&
|
||||
!["Backspace", "Delete", "ArrowLeft", "ArrowRight"].includes(e.key)
|
||||
) {
|
||||
e.preventDefault()
|
||||
}
|
||||
}}
|
||||
value={autoApprovalSettings.maxRequests.toString()}
|
||||
/>
|
||||
</div>
|
||||
</HeroTooltip>
|
||||
<Tooltip>
|
||||
<TooltipContent side="top">
|
||||
Cline will automatically make this many API requests before asking for approval to proceed with the
|
||||
task.
|
||||
</TooltipContent>
|
||||
<TooltipTrigger>
|
||||
<div className="flex items-center pl-1.5 my-2">
|
||||
<span className="codicon codicon-settings text-[#CCCCCC] text-[14px]" />
|
||||
<span className="text-base font-medium ml-2">Max Requests:</span>
|
||||
<VSCodeTextField
|
||||
className="flex-1 w-full pr-[35px] ml-4"
|
||||
onInput={async (e) => {
|
||||
const input = e.target as HTMLInputElement
|
||||
// Remove any non-numeric characters
|
||||
input.value = input.value.replace(/[^0-9]/g, "")
|
||||
const value = parseInt(input.value)
|
||||
if (!Number.isNaN(value) && value > 0) {
|
||||
await updateMaxRequests(value)
|
||||
}
|
||||
}}
|
||||
onKeyDown={(e) => {
|
||||
// Prevent non-numeric keys (except for backspace, delete, arrows)
|
||||
if (
|
||||
!/^\d$/.test(e.key) &&
|
||||
!["Backspace", "Delete", "ArrowLeft", "ArrowRight"].includes(e.key)
|
||||
) {
|
||||
e.preventDefault()
|
||||
}
|
||||
}}
|
||||
value={autoApprovalSettings.maxRequests.toString()}
|
||||
/>
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -117,11 +117,11 @@ export const ActionButtons: React.FC<ActionButtonsProps> = ({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex px-[15px]">
|
||||
<div className="flex px-3.5">
|
||||
<VSCodeButton
|
||||
appearance="icon"
|
||||
aria-label={showScrollToBottom ? "Scroll to bottom" : "Scroll to top"}
|
||||
className="text-lg text-[var(--vscode-primaryButton-foreground)] bg-[color-mix(in_srgb,var(--vscode-toolbar-hoverBackground)_55%,transparent)] rounded-[3px] overflow-hidden cursor-pointer flex justify-center items-center flex-1 h-[25px] hover:bg-[color-mix(in_srgb,var(--vscode-toolbar-hoverBackground)_90%,transparent)] active:bg-[color-mix(in_srgb,var(--vscode-toolbar-hoverBackground)_70%,transparent)] border-0"
|
||||
className="text-lg text-(--vscode-primaryButton-foreground) bg-[color-mix(in_srgb,var(--vscode-toolbar-hoverBackground)_55%,transparent)] rounded-[3px] overflow-hidden cursor-pointer flex justify-center items-center flex-1 h-[25px] hover:bg-[color-mix(in_srgb,var(--vscode-toolbar-hoverBackground)_90%,transparent)] active:bg-[color-mix(in_srgb,var(--vscode-toolbar-hoverBackground)_70%,transparent)] border-0"
|
||||
onClick={showScrollToBottom ? handleScrollToBottom : handleScrollToTop}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter" || e.key === " ") {
|
||||
@@ -146,11 +146,11 @@ export const ActionButtons: React.FC<ActionButtonsProps> = ({
|
||||
const opacity = canInteract || isStreaming ? 1 : 0.5
|
||||
|
||||
return (
|
||||
<div className="flex px-[15px]" style={{ opacity }}>
|
||||
<div className="flex px-3.5" style={{ opacity }}>
|
||||
{primaryText && primaryAction && (
|
||||
<VSCodeButton
|
||||
appearance="primary"
|
||||
className={secondaryText ? "flex-1 mr-[6px]" : "flex-[2]"}
|
||||
className={secondaryText ? "flex-1 mr-[6px]" : "flex-2"}
|
||||
disabled={!canInteract}
|
||||
onClick={() => handleActionClick(primaryAction, inputValue, selectedImages, selectedFiles)}>
|
||||
{primaryText}
|
||||
@@ -159,7 +159,7 @@ export const ActionButtons: React.FC<ActionButtonsProps> = ({
|
||||
{secondaryText && secondaryAction && (
|
||||
<VSCodeButton
|
||||
appearance="secondary"
|
||||
className={primaryText ? "flex-1" : "flex-[2]"}
|
||||
className={primaryText ? "flex-1" : "flex-2"}
|
||||
disabled={!canInteract}
|
||||
onClick={() => handleActionClick(secondaryAction, inputValue, selectedImages, selectedFiles)}>
|
||||
{secondaryText}
|
||||
|
||||
@@ -62,7 +62,7 @@ export const MessagesArea: React.FC<MessagesAreaProps> = ({
|
||||
|
||||
return (
|
||||
<div className="overflow-hidden flex flex-col h-full">
|
||||
<div className="flex-grow flex" ref={scrollContainerRef}>
|
||||
<div className="grow flex" ref={scrollContainerRef}>
|
||||
<Virtuoso
|
||||
atBottomStateChange={(isAtBottom) => {
|
||||
setIsAtBottom(isAtBottom)
|
||||
|
||||
@@ -28,7 +28,7 @@ export const CheckpointError: React.FC<CheckpointErrorProps> = ({
|
||||
return (
|
||||
<div className="flex items-center justify-center w-full">
|
||||
<Alert
|
||||
className="rounded-sm border-0 bg-[var(--vscode-inputValidation-errorBackground)] text-[var(--vscode-inputValidation-errorForeground)] pl-1 pr-1.5 py-1"
|
||||
className="rounded-sm border-0 bg-(--vscode-inputValidation-errorBackground) text-(--vscode-inputValidation-errorForeground) pl-1 pr-1.5 py-1"
|
||||
color="warning"
|
||||
description={
|
||||
<div className="flex gap-2">
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
import { cn, Progress, Tooltip } from "@heroui/react"
|
||||
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
|
||||
import debounce from "debounce"
|
||||
import React, { memo, useCallback, useEffect, useMemo, useRef, useState } from "react"
|
||||
import { updateSetting } from "@/components/settings/utils/settingsHandlers"
|
||||
import { HoverCard, HoverCardContent, HoverCardTrigger } from "@/components/ui/hover-card"
|
||||
import { Progress } from "@/components/ui/progress"
|
||||
import { formatLargeNumber as formatTokenNumber } from "@/utils/format"
|
||||
import { AutoCondenseMarker } from "./AutoCondenseMarker"
|
||||
import CompactTaskButton from "./buttons/CompactTaskButton"
|
||||
@@ -29,12 +30,12 @@ const ConfirmationDialog = memo<{
|
||||
onConfirm: (e: React.MouseEvent) => void
|
||||
onCancel: (e: React.MouseEvent) => void
|
||||
}>(({ onConfirm, onCancel }) => (
|
||||
<div className="text-xs my-2 flex items-center gap-0 justify-between">
|
||||
<div className="text-sm my-2 flex items-center gap-0 justify-between">
|
||||
<span className="font-semibold text-sm">Compact the current task?</span>
|
||||
<span className="flex gap-1">
|
||||
<VSCodeButton
|
||||
appearance="secondary"
|
||||
className="text-xs"
|
||||
className="text-sm"
|
||||
onClick={onCancel}
|
||||
title="No, keep the task as is"
|
||||
type="button">
|
||||
@@ -43,7 +44,7 @@ const ConfirmationDialog = memo<{
|
||||
<VSCodeButton
|
||||
appearance="primary"
|
||||
autoFocus={true}
|
||||
className="text-xs"
|
||||
className="text-sm"
|
||||
onClick={onConfirm}
|
||||
title="Yes, compact the task"
|
||||
type="button">
|
||||
@@ -205,14 +206,13 @@ const ContextWindow: React.FC<ContextWindowProgressProps> = ({
|
||||
return (
|
||||
<div className="flex flex-col my-1.5" onMouseLeave={debounceCloseHover}>
|
||||
<div className="flex gap-1 flex-row @max-xs:flex-col @max-xs:items-start items-center text-sm">
|
||||
<div className="flex items-center gap-1.5 flex-1 whitespace-nowrap text-xs">
|
||||
<span className="cursor-pointer" title="Current tokens used in this request">
|
||||
<div className="flex items-center gap-1.5 flex-1 whitespace-nowrap">
|
||||
<span className="cursor-pointer text-sm" title="Current tokens used in this request">
|
||||
{formatTokenNumber(tokenData.used)}
|
||||
</span>
|
||||
<div className="flex relative items-center gap-1 flex-1 w-full h-full" onMouseEnter={() => setIsOpened(true)}>
|
||||
<Tooltip
|
||||
closeDelay={0}
|
||||
content={
|
||||
<HoverCard>
|
||||
<HoverCardContent className="bg-menu rounded-xs shadow-sm">
|
||||
<ContextWindowSummary
|
||||
autoCompactThreshold={useAutoCondense ? threshold : undefined}
|
||||
cacheReads={cacheReads}
|
||||
@@ -223,54 +223,40 @@ const ContextWindow: React.FC<ContextWindowProgressProps> = ({
|
||||
tokensOut={tokensOut}
|
||||
tokenUsed={tokenData.used}
|
||||
/>
|
||||
}
|
||||
disableAnimation={true}
|
||||
isOpen={isOpened}
|
||||
offset={-2}
|
||||
placement="bottom"
|
||||
shouldCloseOnBlur={false}
|
||||
shouldCloseOnInteractOutside={() => false}
|
||||
showArrow={true}>
|
||||
<div
|
||||
aria-label="Auto condense threshold"
|
||||
aria-valuemax={100}
|
||||
aria-valuemin={0}
|
||||
aria-valuenow={Math.round(threshold * 100)}
|
||||
aria-valuetext={`${Math.round(threshold * 100)}% threshold`}
|
||||
className="relative w-full text-foreground context-window-progress brightness-100"
|
||||
onFocus={handleFocus}
|
||||
onKeyDown={handleKeyDown}
|
||||
ref={progressBarRef}
|
||||
role="slider"
|
||||
tabIndex={useAutoCondense ? 0 : -1}>
|
||||
<Progress
|
||||
aria-label="Context window usage progress"
|
||||
classNames={{
|
||||
base: "drop-shadow-md w-full cursor-pointer",
|
||||
track: cn("rounded max-h-2 h-3 bg-foreground/10"),
|
||||
indicator: "bg-foreground rounded-r",
|
||||
label: "tracking-wider font-medium text-foreground/80",
|
||||
value: "text-description",
|
||||
}}
|
||||
color="success"
|
||||
disableAnimation={true}
|
||||
onClick={handleContextWindowBarClick}
|
||||
size="md"
|
||||
value={tokenData.percentage}
|
||||
/>
|
||||
{useAutoCondense && (
|
||||
<AutoCondenseMarker
|
||||
isContextWindowHoverOpen={isOpened}
|
||||
shouldAnimate={shouldAnimateMarker}
|
||||
threshold={threshold}
|
||||
usage={tokenData.percentage}
|
||||
</HoverCardContent>
|
||||
<HoverCardTrigger asChild>
|
||||
<div
|
||||
aria-label="Auto condense threshold"
|
||||
aria-valuemax={100}
|
||||
aria-valuemin={0}
|
||||
aria-valuenow={Math.round(threshold * 100)}
|
||||
aria-valuetext={`${Math.round(threshold * 100)}% threshold`}
|
||||
className="relative w-full text-foreground context-window-progress brightness-100"
|
||||
onFocus={handleFocus}
|
||||
onKeyDown={handleKeyDown}
|
||||
ref={progressBarRef}
|
||||
role="slider"
|
||||
tabIndex={useAutoCondense ? 0 : -1}>
|
||||
<Progress
|
||||
aria-label="Context window usage progress"
|
||||
color="success"
|
||||
onClick={handleContextWindowBarClick}
|
||||
value={tokenData.percentage}
|
||||
/>
|
||||
)}
|
||||
{isOpened}
|
||||
</div>
|
||||
</Tooltip>
|
||||
{useAutoCondense && (
|
||||
<AutoCondenseMarker
|
||||
isContextWindowHoverOpen={isOpened}
|
||||
shouldAnimate={shouldAnimateMarker}
|
||||
threshold={threshold}
|
||||
usage={tokenData.percentage}
|
||||
/>
|
||||
)}
|
||||
{isOpened}
|
||||
</div>
|
||||
</HoverCardTrigger>
|
||||
</HoverCard>
|
||||
</div>
|
||||
<span className="cursor-pointer" title="Maximum context window size for this model">
|
||||
<span className="cursor-pointer text-sm" title="Maximum context window size for this model">
|
||||
{formatTokenNumber(tokenData.max)}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -42,9 +42,9 @@ const AccordionItem = memo<{
|
||||
)
|
||||
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<div className="flex flex-col w-full">
|
||||
<div
|
||||
className="flex justify-between items-center gap-3 cursor-pointer hover:bg-foreground/5 rounded px-1 py-0.5 transition-colors"
|
||||
className="flex justify-between items-center gap-1 cursor-pointer hover:bg-foreground/5 rounded p-0.5 transition-colors w-full"
|
||||
onClick={handleClick}>
|
||||
<div className="flex items-center gap-1">
|
||||
{isExpanded ? <ChevronDownIcon size={12} /> : <ChevronRightIcon size={12} />}
|
||||
@@ -52,7 +52,7 @@ const AccordionItem = memo<{
|
||||
</div>
|
||||
<div className="text-muted-foreground text-sm">{value}</div>
|
||||
</div>
|
||||
{isExpanded && children && <div className="ml-4 mt-2 mb-1 text-xs text-muted-foreground">{children}</div>}
|
||||
{isExpanded && children && <div className="ml-5 my-1 text-xs text-muted-foreground">{children}</div>}
|
||||
</div>
|
||||
)
|
||||
})
|
||||
@@ -77,13 +77,10 @@ const TokenUsageDetails = memo<TokenUsageInfoProps>(({ tokensIn, tokensOut, cach
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="space-y-1">
|
||||
{contextTokenDetails.map((item) => (
|
||||
<div className="flex items-center justify-between" key={item.icon}>
|
||||
<div className="flex items-center gap-1">
|
||||
<i className={`codicon ${item.icon} text-xs`} />
|
||||
<span>{item.title}</span>
|
||||
</div>
|
||||
<div className="flex justify-between">
|
||||
<span>{item.title}</span>
|
||||
<span className="font-mono">{formatTokenNumber(item.value || 0)}</span>
|
||||
</div>
|
||||
))}
|
||||
@@ -124,7 +121,7 @@ export const ContextWindowSummary: React.FC<TaskContextWindowButtonsProps> = ({
|
||||
const totalTokens = (tokensIn || 0) + (tokensOut || 0) + (cacheWrites || 0) + (cacheReads || 0)
|
||||
|
||||
return (
|
||||
<div className="context-window-tooltip-content flex flex-col gap-2 bg-menu rounded shadow-sm border border-menu-border z-100 w-60 p-4">
|
||||
<div className="context-window-tooltip-content flex flex-col gap-2 bg-menu rounded shadow-sm z-100 w-60 p-1">
|
||||
{autoCompactThreshold > 0 && (
|
||||
<AccordionItem
|
||||
isExpanded={expandedSections.has("threshold")}
|
||||
@@ -146,7 +143,7 @@ export const ContextWindowSummary: React.FC<TaskContextWindowButtonsProps> = ({
|
||||
isExpanded={expandedSections.has("context")}
|
||||
onToggle={(event) => toggleSection("context", event)}
|
||||
title="Context Window"
|
||||
value={percentage ? `${percentage.toFixed(1)}% used` : formatTokenNumber(contextWindow)}>
|
||||
value={percentage ? `${percentage.toFixed(1)}%` : formatTokenNumber(contextWindow)}>
|
||||
<div className="space-y-1">
|
||||
<div className="flex justify-between">
|
||||
<span>Used:</span>
|
||||
@@ -168,7 +165,7 @@ export const ContextWindowSummary: React.FC<TaskContextWindowButtonsProps> = ({
|
||||
isExpanded={expandedSections.has("tokens")}
|
||||
onToggle={(event) => toggleSection("tokens", event)}
|
||||
title="Token Usage"
|
||||
value={`${formatTokenNumber(totalTokens)} total`}>
|
||||
value={`${formatTokenNumber(totalTokens)}`}>
|
||||
<TokenUsageDetails
|
||||
cacheReads={cacheReads}
|
||||
cacheWrites={cacheWrites}
|
||||
|
||||
@@ -55,7 +55,6 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
|
||||
checkpointManagerErrorMessage,
|
||||
clineMessages,
|
||||
navigateToSettings,
|
||||
useAutoCondense,
|
||||
mode,
|
||||
expandTaskHeader: isTaskExpanded,
|
||||
setExpandTaskHeader: setIsTaskExpanded,
|
||||
@@ -100,10 +99,10 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
|
||||
{/* Task Header */}
|
||||
<div
|
||||
className={cn(
|
||||
"relative overflow-hidden cursor-pointer rounded-sm flex flex-col gap-1.5 z-10 pt-2 pb-2 px-2 hover:opacity-100 bg-[var(--vscode-toolbar-hoverBackground)]/65",
|
||||
"relative overflow-hidden cursor-pointer rounded-sm flex flex-col gap-1.5 z-10 pt-2 pb-2 px-2 hover:opacity-100 bg-(--vscode-toolbar-hoverBackground)/65",
|
||||
{
|
||||
"opacity-100 border-1": isTaskExpanded, // No hover effects when expanded, add border
|
||||
"hover:bg-[var(--vscode-toolbar-hoverBackground)] border-1": !isTaskExpanded, // Hover effects only when collapsed
|
||||
"hover:bg-(--vscode-toolbar-hoverBackground) border-1": !isTaskExpanded, // Hover effects only when collapsed
|
||||
},
|
||||
)}
|
||||
style={{
|
||||
@@ -114,7 +113,7 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
|
||||
<div className="flex justify-between items-center">
|
||||
{isTaskExpanded ? <ChevronDownIcon size="16" /> : <ChevronRightIcon size="16" />}
|
||||
{isTaskExpanded && (
|
||||
<div className="mt-1 max-h-3 flex justify-end flex-wrap cursor-pointer opacity-80">
|
||||
<div className="mt-1 max-h-3 flex justify-end flex-wrap cursor-pointer opacity-80 gap-2 mx-2">
|
||||
<CopyTaskButton className={BUTTON_CLASS} taskText={task.text} />
|
||||
<DeleteTaskButton
|
||||
className={BUTTON_CLASS}
|
||||
@@ -128,19 +127,19 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center select-none flex-grow min-w-0 gap-1 justify-between">
|
||||
<div className="flex items-center select-none grow min-w-0 gap-1 justify-between">
|
||||
{!isTaskExpanded && (
|
||||
<div className="text-sm whitespace-nowrap overflow-hidden text-ellipsis flex-grow min-w-0">
|
||||
<span className="ph-no-capture">{highlightText(task.text, false)}</span>
|
||||
<div className="whitespace-nowrap overflow-hidden text-ellipsis grow min-w-0">
|
||||
<span className="ph-no-capture text-base">{highlightText(task.text, false)}</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="inline-flex items-center justify-end select-none flex-shrink-0">
|
||||
<div className="inline-flex items-center justify-end select-none shrink-0">
|
||||
{isCostAvailable && (
|
||||
<div
|
||||
className="mr-1 px-1 py-0.25 rounded-full inline-flex shrink-0 text-badge-background bg-badge-foreground/80 items-center"
|
||||
id="price-tag">
|
||||
<span className="text-xs">${totalCost?.toFixed(4)}</span>
|
||||
<span className="text-sm">${totalCost?.toFixed(4)}</span>
|
||||
</div>
|
||||
)}
|
||||
<NewTaskButton className={BUTTON_CLASS} onClick={onClose} />
|
||||
@@ -150,10 +149,10 @@ const TaskHeader: React.FC<TaskHeaderProps> = ({
|
||||
{/* Expand/Collapse Task Details */}
|
||||
{isTaskExpanded && (
|
||||
<div className="flex flex-col break-words" key={`task-details-${currentTaskItem?.id}`}>
|
||||
<div className="whitespace-nowrap overflow-hidden text-ellipsis flex-grow min-w-0 max-h-20 overflow-y-auto scroll-smooth">
|
||||
<div className="whitespace-nowrap overflow-hidden text-ellipsis grow min-w-0 max-h-20 overflow-y-auto scroll-smooth">
|
||||
<div
|
||||
className={
|
||||
"ph-no-capture overflow-hidden whitespace-pre-wrap break-words px-0.5 text-sm cursor-pointer mt-1"
|
||||
"ph-no-capture overflow-hidden whitespace-pre-wrap break-words px-0.5 text-base cursor-pointer my-1 pt-1"
|
||||
}>
|
||||
{highlightedText}
|
||||
</div>
|
||||
|
||||
@@ -154,7 +154,7 @@ const TaskTimelineTooltip = ({ message, children }: TaskTimelineTooltipProps) =>
|
||||
return (
|
||||
<Tooltip
|
||||
classNames={{
|
||||
base: "bg-[var(--vscode-editor-background)] text-[var(--vscode-editor-foreground)] border-[var(--vscode-widget-border)] py-1 rounded-[3px] max-w-[calc(100dvw-2rem)] text-xs",
|
||||
base: "bg-(--vscode-editor-background) text-(--vscode-editor-foreground) border-(--vscode-widget-border) py-1 rounded-[3px] max-w-[calc(100dvw-2rem)] text-xs",
|
||||
}}
|
||||
closeDelay={100}
|
||||
content={
|
||||
|
||||
@@ -1,34 +1,28 @@
|
||||
import { cn, Tooltip } from "@heroui/react"
|
||||
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
|
||||
import { FoldVerticalIcon } from "lucide-react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const CompactTaskButton: React.FC<{
|
||||
className?: string
|
||||
onClick: (e: React.MouseEvent<HTMLButtonElement>) => void
|
||||
}> = ({ onClick, className }) => {
|
||||
return (
|
||||
<Tooltip
|
||||
content={
|
||||
<div className="flex flex-col gap-1 bg-menu rounded shadow-sm border border-menu-border z-100 max-w-xs py-1 px-2">
|
||||
<div className="text-xs font-medium">Compact Task</div>
|
||||
<div className="text-xs text-muted-foreground">
|
||||
Reduces the number of tokens used by summarizing the task.
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
delay={0}
|
||||
disableAnimation={true}
|
||||
placement="bottom">
|
||||
<VSCodeButton
|
||||
appearance="icon"
|
||||
className={cn(
|
||||
"text-foreground flex items-center text-sm font-bold hover:bg-transparent hover:opacity-80",
|
||||
className,
|
||||
)}
|
||||
onClick={onClick}
|
||||
type="button">
|
||||
<FoldVerticalIcon size={12} />
|
||||
</VSCodeButton>
|
||||
<Tooltip>
|
||||
<TooltipContent side="bottom">Compact Task</TooltipContent>
|
||||
<TooltipTrigger className={cn("flex items-center", className)}>
|
||||
<Button
|
||||
aria-label="Compact Task"
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
onClick(e)
|
||||
}}
|
||||
size="icon"
|
||||
variant="icon">
|
||||
<FoldVerticalIcon />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Button } from "@heroui/button"
|
||||
import { cn } from "@heroui/react"
|
||||
import { CheckIcon, CopyIcon } from "lucide-react"
|
||||
import { useCallback, useState } from "react"
|
||||
import HeroTooltip from "@/components/common/HeroTooltip"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
|
||||
const CopyTaskButton: React.FC<{
|
||||
taskText?: string
|
||||
@@ -22,17 +22,14 @@ const CopyTaskButton: React.FC<{
|
||||
}, [taskText])
|
||||
|
||||
return (
|
||||
<HeroTooltip content="Copy Text" placement="right">
|
||||
<Button
|
||||
aria-label="Copy"
|
||||
className={cn("bg-transparent hover:opacity-100", className)}
|
||||
isIconOnly={true}
|
||||
onPress={() => handleCopy()}
|
||||
radius="sm"
|
||||
size="sm">
|
||||
{copied ? <CheckIcon size="13" /> : <CopyIcon size="13" />}
|
||||
</Button>
|
||||
</HeroTooltip>
|
||||
<Tooltip>
|
||||
<TooltipContent side="bottom">Copy Text</TooltipContent>
|
||||
<TooltipTrigger className={cn("flex items-center", className)}>
|
||||
<Button aria-label="Copy" onClick={() => handleCopy()} size="icon" variant="icon">
|
||||
{copied ? <CheckIcon /> : <CopyIcon />}
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Button, cn } from "@heroui/react"
|
||||
import { StringArrayRequest } from "@shared/proto/cline/common"
|
||||
import { TrashIcon } from "lucide-react"
|
||||
import HeroTooltip from "@/components/common/HeroTooltip"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { TaskServiceClient } from "@/services/grpc-client"
|
||||
import { formatSize } from "@/utils/format"
|
||||
|
||||
@@ -10,19 +11,19 @@ const DeleteTaskButton: React.FC<{
|
||||
taskSize?: number
|
||||
className?: string
|
||||
}> = ({ taskId, className, taskSize }) => (
|
||||
<HeroTooltip content={`Delete Task (size: ${taskSize ? formatSize(taskSize) : "--"})`} placement="right">
|
||||
<Button
|
||||
aria-label="Delete Task"
|
||||
className={cn("flex items-center border-0 text-sm font-bold bg-transparent hover:opacity-100 p-0", className)}
|
||||
isIconOnly={true}
|
||||
onPress={() => {
|
||||
taskId && TaskServiceClient.deleteTasksWithIds(StringArrayRequest.create({ value: [taskId] }))
|
||||
}}
|
||||
radius="sm"
|
||||
size="sm">
|
||||
<TrashIcon size="13" />
|
||||
</Button>
|
||||
</HeroTooltip>
|
||||
<Tooltip>
|
||||
<TooltipContent>{`Delete Task (size: ${taskSize ? formatSize(taskSize) : "--"})`}</TooltipContent>
|
||||
<TooltipTrigger className={cn("flex items-center", className)}>
|
||||
<Button
|
||||
aria-label="Delete Task"
|
||||
disabled={!taskId}
|
||||
onClick={() => taskId && TaskServiceClient.deleteTasksWithIds(StringArrayRequest.create({ value: [taskId] }))}
|
||||
size="xs"
|
||||
variant="icon">
|
||||
<TrashIcon />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
)
|
||||
DeleteTaskButton.displayName = "DeleteTaskButton"
|
||||
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
import { cn } from "@heroui/react"
|
||||
import { XIcon } from "lucide-react"
|
||||
import HeroTooltip from "@/components/common/HeroTooltip"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const NewTaskButton: React.FC<{
|
||||
onClick: () => void
|
||||
className?: string
|
||||
}> = ({ className, onClick }) => {
|
||||
return (
|
||||
<HeroTooltip content="Close current task to start new one" delay={1000} placement="bottom">
|
||||
<button
|
||||
aria-label="Start a New Task"
|
||||
className={cn(
|
||||
"flex items-center border-0 text-sm font-bold bg-transparent opacity-70 hover:opacity-100",
|
||||
className,
|
||||
"hover:bg-muted/10 px-0 cursor-pointer",
|
||||
)}
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
onClick()
|
||||
}}
|
||||
type="button">
|
||||
<XIcon size="14" />
|
||||
</button>
|
||||
</HeroTooltip>
|
||||
<Tooltip>
|
||||
<TooltipContent side="bottom">Start a New Task</TooltipContent>
|
||||
<TooltipTrigger className={cn("flex items-center", className)}>
|
||||
<Button
|
||||
aria-label="New Task"
|
||||
onClick={(e) => {
|
||||
e.preventDefault()
|
||||
e.stopPropagation()
|
||||
onClick()
|
||||
}}
|
||||
size="icon"
|
||||
variant="icon">
|
||||
<XIcon />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+16
-13
@@ -1,7 +1,8 @@
|
||||
import { Button, cn } from "@heroui/react"
|
||||
import { StringRequest } from "@shared/proto/cline/common"
|
||||
import { ArrowDownToLineIcon } from "lucide-react"
|
||||
import HeroTooltip from "@/components/common/HeroTooltip"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { FileServiceClient } from "@/services/grpc-client"
|
||||
|
||||
const OpenDiskConversationHistoryButton: React.FC<{
|
||||
@@ -19,18 +20,20 @@ const OpenDiskConversationHistoryButton: React.FC<{
|
||||
}
|
||||
|
||||
return (
|
||||
<HeroTooltip content="Open Conversation History File" placement="right">
|
||||
<Button
|
||||
aria-label="Open Disk Conversation History"
|
||||
className={cn("flex items-center border-0 text-sm font-bold bg-transparent hover:opacity-100", className)}
|
||||
isIconOnly={true}
|
||||
onPress={() => handleOpenDiskConversationHistory()}
|
||||
radius="sm"
|
||||
size="sm">
|
||||
<ArrowDownToLineIcon size="14" />
|
||||
</Button>
|
||||
</HeroTooltip>
|
||||
<Tooltip>
|
||||
<TooltipContent>Open Conversation History File</TooltipContent>
|
||||
<TooltipTrigger className={cn("flex items-center", className)}>
|
||||
<Button
|
||||
aria-label="Open Disk Conversation History"
|
||||
onClick={() => handleOpenDiskConversationHistory()}
|
||||
size="xs"
|
||||
variant="icon">
|
||||
<ArrowDownToLineIcon />
|
||||
</Button>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
OpenDiskConversationHistoryButton.displayName = "OpenDiskConversationHistoryButton"
|
||||
export default OpenDiskConversationHistoryButton
|
||||
|
||||
@@ -12,7 +12,7 @@ import React, { useEffect, useRef, useState } from "react"
|
||||
import { useClickAway, useWindowSize } from "react-use"
|
||||
import styled from "styled-components"
|
||||
import { CODE_BLOCK_BG_COLOR } from "@/components/common/CodeBlock"
|
||||
import Tooltip from "@/components/common/Tooltip"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { FileServiceClient } from "@/services/grpc-client"
|
||||
import RulesToggleList from "./RulesToggleList"
|
||||
@@ -196,25 +196,28 @@ const ClineRulesToggleModal: React.FC = () => {
|
||||
return (
|
||||
<div ref={modalRef}>
|
||||
<div className="inline-flex min-w-0 max-w-full" ref={buttonRef}>
|
||||
<Tooltip tipText="Manage Cline Rules & Workflows" visible={isVisible ? false : undefined}>
|
||||
<VSCodeButton
|
||||
appearance="icon"
|
||||
aria-label={isVisible ? "Hide Cline Rules & Workflows" : "Show Cline Rules & Workflows"}
|
||||
onClick={() => setIsVisible(!isVisible)}
|
||||
style={{ padding: "0px 0px", height: "20px" }}>
|
||||
<div className="flex items-center gap-1 text-xs whitespace-nowrap min-w-0 w-full">
|
||||
<span
|
||||
className="codicon codicon-law flex items-center"
|
||||
style={{ fontSize: "12.5px", marginBottom: 1 }}
|
||||
/>
|
||||
</div>
|
||||
</VSCodeButton>
|
||||
<Tooltip>
|
||||
{!isVisible && <TooltipContent>Manage Cline Rules & Workflows</TooltipContent>}
|
||||
<TooltipTrigger>
|
||||
<VSCodeButton
|
||||
appearance="icon"
|
||||
aria-label={isVisible ? "Hide Cline Rules & Workflows" : "Show Cline Rules & Workflows"}
|
||||
onClick={() => setIsVisible(!isVisible)}
|
||||
style={{ padding: "0px 0px", height: "20px" }}>
|
||||
<div className="flex items-center gap-1 text-xs whitespace-nowrap min-w-0 w-full">
|
||||
<span
|
||||
className="codicon codicon-law flex items-center"
|
||||
style={{ fontSize: "12.5px", marginBottom: 1 }}
|
||||
/>
|
||||
</div>
|
||||
</VSCodeButton>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
</div>
|
||||
|
||||
{isVisible && (
|
||||
<div
|
||||
className="fixed left-[15px] right-[15px] border border-[var(--vscode-editorGroup-border)] p-3 rounded z-[1000] overflow-y-auto"
|
||||
className="fixed left-[15px] right-[15px] border border-(--vscode-editorGroup-border) p-3 rounded z-1000 overflow-y-auto"
|
||||
style={{
|
||||
bottom: `calc(100vh - ${menuPosition}px + 6px)`,
|
||||
background: CODE_BLOCK_BG_COLOR,
|
||||
@@ -222,7 +225,7 @@ const ClineRulesToggleModal: React.FC = () => {
|
||||
overscrollBehavior: "contain",
|
||||
}}>
|
||||
<div
|
||||
className="fixed w-[10px] h-[10px] z-[-1] rotate-45 border-r border-b border-[var(--vscode-editorGroup-border)]"
|
||||
className="fixed w-[10px] h-[10px] z-[-1] rotate-45 border-r border-b border-(--vscode-editorGroup-border)"
|
||||
style={{
|
||||
bottom: `calc(100vh - ${menuPosition}px)`,
|
||||
right: arrowPosition,
|
||||
@@ -253,7 +256,7 @@ const ClineRulesToggleModal: React.FC = () => {
|
||||
</div>
|
||||
|
||||
{/* Description text */}
|
||||
<div className="text-xs text-[var(--vscode-descriptionForeground)] mb-4">
|
||||
<div className="text-xs text-(--vscode-descriptionForeground) mb-4">
|
||||
{currentView === "rules" ? (
|
||||
<p>
|
||||
Rules allow you to provide Cline with system-level guidance. Think of them as a persistent way to
|
||||
@@ -271,7 +274,7 @@ const ClineRulesToggleModal: React.FC = () => {
|
||||
such as deploying a service or submitting a PR. To invoke a workflow, type{" "}
|
||||
<span
|
||||
className="
|
||||
text-[var(--vscode-foreground)] font-bold">
|
||||
text-(--vscode-foreground) font-bold">
|
||||
/workflow-name
|
||||
</span>{" "}
|
||||
in the chat.{" "}
|
||||
|
||||
@@ -92,13 +92,13 @@ const NewRuleRow: React.FC<NewRuleRowProps> = ({ isGlobal, ruleType }) => {
|
||||
onClick={() => !isExpanded && setIsExpanded(true)}
|
||||
ref={componentRef}>
|
||||
<div
|
||||
className={`flex items-center p-2 rounded bg-[var(--vscode-input-background)] transition-all duration-300 ease-in-out h-[18px] ${
|
||||
className={`flex items-center p-2 rounded bg-(--vscode-input-background) transition-all duration-300 ease-in-out h-[18px] ${
|
||||
isExpanded ? "shadow-sm" : ""
|
||||
}`}>
|
||||
{isExpanded ? (
|
||||
<form className="flex flex-1 items-center" onSubmit={handleSubmit}>
|
||||
<input
|
||||
className="flex-1 bg-[var(--vscode-input-background)] text-[var(--vscode-input-foreground)] border-0 outline-0 rounded focus:outline-none focus:ring-0 focus:border-transparent"
|
||||
className="flex-1 bg-(--vscode-input-background) text-(--vscode-input-foreground) border-0 outline-0 rounded focus:outline-none focus:ring-0 focus:border-transparent"
|
||||
onChange={(e) => setFilename(e.target.value)}
|
||||
onKeyDown={handleKeyDown}
|
||||
placeholder={
|
||||
@@ -127,7 +127,7 @@ const NewRuleRow: React.FC<NewRuleRowProps> = ({ isGlobal, ruleType }) => {
|
||||
</form>
|
||||
) : (
|
||||
<>
|
||||
<span className="flex-1 text-[var(--vscode-descriptionForeground)] bg-[var(--vscode-input-background)] italic text-xs">
|
||||
<span className="flex-1 text-(--vscode-descriptionForeground) bg-(--vscode-input-background) italic text-xs">
|
||||
{ruleType === "workflow" ? "New workflow file..." : "New rule file..."}
|
||||
</span>
|
||||
<div className="flex items-center ml-2 space-x-2">
|
||||
@@ -146,7 +146,7 @@ const NewRuleRow: React.FC<NewRuleRowProps> = ({ isGlobal, ruleType }) => {
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
{isExpanded && error && <div className="text-[var(--vscode-errorForeground)] text-xs mt-1 ml-2">{error}</div>}
|
||||
{isExpanded && error && <div className="text-(--vscode-errorForeground) text-xs mt-1 ml-2">{error}</div>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ const RuleRow: React.FC<{
|
||||
return (
|
||||
<div className="mb-2.5">
|
||||
<div
|
||||
className={`flex items-center p-2 rounded bg-[var(--vscode-textCodeBlock-background)] h-[18px] ${
|
||||
className={`flex items-center p-2 rounded bg-(--vscode-textCodeBlock-background) h-[18px] ${
|
||||
enabled ? "opacity-100" : "opacity-60"
|
||||
}`}>
|
||||
<span className="flex-1 overflow-hidden break-all whitespace-normal flex items-center mr-1" title={rulePath}>
|
||||
@@ -89,8 +89,8 @@ const RuleRow: React.FC<{
|
||||
aria-checked={enabled}
|
||||
className={`w-[20px] h-[10px] rounded-[5px] relative cursor-pointer transition-colors duration-200 ${
|
||||
enabled
|
||||
? "bg-[var(--vscode-testing-iconPassed)] opacity-90"
|
||||
: "bg-[var(--vscode-titleBar-inactiveForeground)] opacity-50"
|
||||
? "bg-(--vscode-testing-iconPassed) opacity-90"
|
||||
: "bg-(--vscode-titleBar-inactiveForeground) opacity-50"
|
||||
}`}
|
||||
onClick={() => toggleRule(rulePath, !enabled)}
|
||||
onKeyDown={(e) => {
|
||||
@@ -102,7 +102,7 @@ const RuleRow: React.FC<{
|
||||
role="switch"
|
||||
tabIndex={0}>
|
||||
<div
|
||||
className={`w-[6px] h-[6px] bg-white border border-[#66666699] rounded-full absolute top-[1px] transition-all duration-200 ${
|
||||
className={`w-[6px] h-[6px] bg-white border border-[#66666699] rounded-full absolute top-px transition-all duration-200 ${
|
||||
enabled ? "left-[12px]" : "left-[2px]"
|
||||
}`}
|
||||
/>
|
||||
|
||||
@@ -45,7 +45,7 @@ const RulesToggleList = ({
|
||||
) : (
|
||||
<>
|
||||
{showNoRules && (
|
||||
<div className="flex flex-col items-center gap-3 my-3 text-[var(--vscode-descriptionForeground)]">
|
||||
<div className="flex flex-col items-center gap-3 my-3 text-(--vscode-descriptionForeground)">
|
||||
{ruleType === "workflow" ? "No workflows found" : "No rules found"}
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -37,7 +37,7 @@ export function AlertDialogContent({ className, children, ...props }: React.HTML
|
||||
className={`fixed top-[50%] left-[50%] grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] ${className}`}
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
{...props}>
|
||||
<div className="bg-[var(--vscode-editor-background)] rounded-sm gap-3 border border-[var(--vscode-panel-border)] p-6 shadow-lg sm:max-w-lg">
|
||||
<div className="bg-(--vscode-editor-background) rounded-sm gap-3 border border-(--vscode-panel-border) p-6 shadow-lg sm:max-w-lg">
|
||||
{children}
|
||||
</div>
|
||||
</div>
|
||||
@@ -55,14 +55,14 @@ export function AlertDialogFooter({ className, ...props }: React.HTMLAttributes<
|
||||
export function AlertDialogTitle({ className, ...props }: React.HTMLAttributes<HTMLHeadingElement>) {
|
||||
return (
|
||||
<h2
|
||||
className={`text-base font-medium text-[var(--vscode-editor-foreground)] flex items-center gap-2 text-left ${className}`}
|
||||
className={`text-base font-medium text-(--vscode-editor-foreground) flex items-center gap-2 text-left ${className}`}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export function AlertDialogDescription({ className, ...props }: React.HTMLAttributes<HTMLParagraphElement>) {
|
||||
return <p className={`text-[var(--vscode-descriptionForeground)] text-sm text-left ${className}`} {...props} />
|
||||
return <p className={`text-(--vscode-descriptionForeground) text-sm text-left ${className}`} {...props} />
|
||||
}
|
||||
|
||||
export function AlertDialogAction({ className, ...props }: React.ComponentProps<typeof VSCodeButton>) {
|
||||
@@ -101,7 +101,7 @@ export function UnsavedChangesDialog({
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>
|
||||
<AlertTriangle className="w-5 h-5 text-[var(--vscode-errorForeground)]" />
|
||||
<AlertTriangle className="w-5 h-5 text-(--vscode-errorForeground)" />
|
||||
{title}
|
||||
</AlertDialogTitle>
|
||||
<AlertDialogDescription>{description}</AlertDialogDescription>
|
||||
|
||||
@@ -284,7 +284,7 @@ const Container = styled.div<{ isMenuOpen?: boolean; $isCheckedOut?: boolean }>`
|
||||
margin-top: -10px;
|
||||
margin-bottom: -10px;
|
||||
opacity: ${(props) => (props.$isCheckedOut ? 1 : props.isMenuOpen ? 1 : 0.5)};
|
||||
|
||||
height: 0.5rem;
|
||||
&:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
@@ -313,7 +313,7 @@ const Container = styled.div<{ isMenuOpen?: boolean; $isCheckedOut?: boolean }>`
|
||||
const Label = styled.span<{ $isCheckedOut?: boolean }>`
|
||||
color: ${(props) => (props.$isCheckedOut ? "var(--vscode-textLink-foreground)" : "var(--vscode-descriptionForeground)")};
|
||||
font-size: 9px;
|
||||
flex-shrink: 0;
|
||||
shrink: 0;
|
||||
`
|
||||
|
||||
const DottedLine = styled.div<{ small?: boolean; $isCheckedOut?: boolean }>`
|
||||
@@ -333,7 +333,7 @@ const ButtonGroup = styled.div`
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
flex-shrink: 0;
|
||||
shrink: 0;
|
||||
`
|
||||
|
||||
const CustomButton = styled.button<{ disabled?: boolean; isActive?: boolean; $isCheckedOut?: boolean }>`
|
||||
|
||||
@@ -150,7 +150,7 @@ const CodeBlock = memo(({ source, forceWrap = false }: CodeBlockProps) => {
|
||||
maxHeight: forceWrap ? "none" : "100%",
|
||||
backgroundColor: CODE_BLOCK_BG_COLOR,
|
||||
}}>
|
||||
<StyledMarkdown className="ph-no-capture" forceWrap={forceWrap}>
|
||||
<StyledMarkdown className="ph-no-capture markdown" forceWrap={forceWrap}>
|
||||
{reactContent}
|
||||
</StyledMarkdown>
|
||||
</div>
|
||||
|
||||
@@ -7,13 +7,13 @@ const DangerButton: React.FC<DangerButtonProps> = (props) => {
|
||||
<VSCodeButton
|
||||
{...props}
|
||||
className={`
|
||||
!bg-[#c42b2b]
|
||||
!border-[#c42b2b]
|
||||
!text-white
|
||||
hover:!bg-[#a82424]
|
||||
hover:!border-[#a82424]
|
||||
active:!bg-[#8f1f1f]
|
||||
active:!border-[#8f1f1f]
|
||||
bg-[#c42b2b]!
|
||||
border-[#c42b2b]!
|
||||
text-white!
|
||||
hover:bg-[#a82424]!
|
||||
hover:border-[#a82424]!
|
||||
active:bg-[#8f1f1f]!
|
||||
active:border-[#8f1f1f]!
|
||||
${props.className || ""}
|
||||
`}
|
||||
/>
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
import { cn, Tooltip } from "@heroui/react"
|
||||
import React, { useMemo } from "react"
|
||||
|
||||
interface HeroTooltipProps {
|
||||
content: React.ReactNode
|
||||
children: React.ReactNode
|
||||
className?: string
|
||||
delay?: number
|
||||
closeDelay?: number
|
||||
placement?: "top" | "bottom" | "left" | "right"
|
||||
showArrow?: boolean
|
||||
disabled?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* HeroTooltip component that wraps the HeroUI tooltip with styling
|
||||
* similar to TaskTimelineTooltip
|
||||
*/
|
||||
const HeroTooltip: React.FC<HeroTooltipProps> = ({
|
||||
content,
|
||||
children,
|
||||
className,
|
||||
showArrow = false,
|
||||
delay = 0,
|
||||
closeDelay = 500,
|
||||
placement = "top",
|
||||
disabled = false,
|
||||
}) => {
|
||||
// If content is a simple string, wrap it in the tailwind styled divs
|
||||
const formattedContent = useMemo(() => {
|
||||
return typeof content === "string" ? (
|
||||
<div
|
||||
className={cn(
|
||||
"bg-code-background text-code-foreground border border-code-foreground/20 rounded shadow-md max-w-[250px] text-sm",
|
||||
className,
|
||||
"p-2",
|
||||
)}>
|
||||
<span className="whitespace-pre-wrap break-words overflow-y-auto">{content}</span>
|
||||
</div>
|
||||
) : (
|
||||
// If content is already a React node, assume it's pre-formatted
|
||||
content
|
||||
)
|
||||
}, [content, className])
|
||||
|
||||
return (
|
||||
<Tooltip
|
||||
classNames={{
|
||||
content: "hero-tooltip-content pointer-events-none", // Prevent hovering over tooltip
|
||||
}}
|
||||
closeDelay={closeDelay}
|
||||
content={formattedContent} // Immediate close when cursor moves away
|
||||
delay={delay}
|
||||
disableAnimation={true}
|
||||
isDisabled={disabled}
|
||||
placement={placement} // Disable animation for immediate appearance/disappearance
|
||||
showArrow={showArrow}>
|
||||
{children}
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
export default HeroTooltip
|
||||
@@ -1,5 +1,6 @@
|
||||
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
|
||||
import { XIcon } from "lucide-react"
|
||||
import { useCallback } from "react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { PlatformType } from "@/config/platform.config"
|
||||
import { usePlatform } from "@/context/PlatformContext"
|
||||
import { StateServiceClient } from "@/services/grpc-client"
|
||||
@@ -13,27 +14,26 @@ export const InfoBanner: React.FC = () => {
|
||||
if (usePlatform().type === PlatformType.VSCODE) {
|
||||
return (
|
||||
<a
|
||||
className="bg-banner-background px-3 py-2 flex flex-col gap-1 shrink-0 mb-1 relative text-sm m-4 no-underline transition-colors hover:brightness-120"
|
||||
className="bg-banner-background px-3 py-2 flex flex-col gap-1 shrink-0 mb-1 relative text-sm m-4 no-underline transition-colors hover:brightness-120 rounded-sm"
|
||||
href="https://docs.cline.bot/features/customization/opening-cline-in-sidebar"
|
||||
rel="noopener noreferrer"
|
||||
style={{ color: "var(--vscode-foreground)", outline: "none" }}
|
||||
target="_blank">
|
||||
<h4 className="m-0" style={{ paddingRight: "18px" }}>
|
||||
💡 Cline in the Right Sidebar
|
||||
</h4>
|
||||
<h4 className="m-0">💡 Cline in the Right Sidebar</h4>
|
||||
<p className="m-0">
|
||||
Keep your files visible when chatting with Cline. Drag the Cline icon to the right sidebar panel for a better
|
||||
experience. <span className="text-link cursor-pointer">See how →</span>
|
||||
</p>
|
||||
|
||||
{/* Close button */}
|
||||
<VSCodeButton
|
||||
appearance="icon"
|
||||
<Button
|
||||
className="absolute top-2.5 right-2"
|
||||
data-testid="info-banner-close-button"
|
||||
onClick={handleClose}
|
||||
style={{ position: "absolute", top: "6px", right: "6px" }}>
|
||||
<span className="codicon codicon-close"></span>
|
||||
</VSCodeButton>
|
||||
size="icon"
|
||||
variant="icon">
|
||||
<XIcon />
|
||||
</Button>
|
||||
</a>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ const ActModeHighlight: React.FC = () => {
|
||||
|
||||
return (
|
||||
<span
|
||||
className={`text-[var(--vscode-textLink-foreground)] inline-flex items-center gap-1 ${
|
||||
className={`text-(--vscode-textLink-foreground) inline-flex items-center gap-1 ${
|
||||
mode === "plan" ? "hover:opacity-90 cursor-pointer" : "cursor-default opacity-60"
|
||||
}`}
|
||||
onClick={() => {
|
||||
@@ -33,8 +33,8 @@ const ActModeHighlight: React.FC = () => {
|
||||
}
|
||||
}}
|
||||
title={mode === "plan" ? "Click to toggle to Act Mode" : "Already in Act Mode"}>
|
||||
<div className="p-1 rounded-[12px] bg-[var(--vscode-editor-background)] flex items-center justify-end w-4 border-[1px] border-[var(--vscode-input-border)]">
|
||||
<div className="rounded-full bg-[var(--vscode-textLink-foreground)] w-2 h-2" />
|
||||
<div className="p-1 rounded-[12px] bg-(--vscode-editor-background) flex items-center justify-end w-4 border border-(--vscode-input-border)">
|
||||
<div className="rounded-full bg-(--vscode-textLink-foreground) w-2 h-2" />
|
||||
</div>
|
||||
Act Mode (⌘⇧A)
|
||||
</span>
|
||||
@@ -60,13 +60,17 @@ const remarkUrlToLink = () => {
|
||||
visit(tree, "text", (node: any, index, parent) => {
|
||||
const urlRegex = /https?:\/\/[^\s<>)"]+/g
|
||||
const matches = node.value.match(urlRegex)
|
||||
if (!matches) return
|
||||
if (!matches) {
|
||||
return
|
||||
}
|
||||
|
||||
const parts = node.value.split(urlRegex)
|
||||
const children: any[] = []
|
||||
|
||||
parts.forEach((part: string, i: number) => {
|
||||
if (part) children.push({ type: "text", value: part })
|
||||
if (part) {
|
||||
children.push({ type: "text", value: part })
|
||||
}
|
||||
if (matches[i]) {
|
||||
children.push({
|
||||
type: "link",
|
||||
@@ -97,19 +101,25 @@ const remarkHighlightActMode = () => {
|
||||
// Added negative lookahead to avoid matching if already followed by the shortcut
|
||||
const actModeRegex = /\bto\s+Act\s+Mode\b(?!\s*\(⌘⇧A\))/i
|
||||
|
||||
if (!node.value.match(actModeRegex)) return
|
||||
if (!node.value.match(actModeRegex)) {
|
||||
return
|
||||
}
|
||||
|
||||
// Split the text by the matches
|
||||
const parts = node.value.split(actModeRegex)
|
||||
const matches = node.value.match(actModeRegex)
|
||||
|
||||
if (!matches || parts.length <= 1) return
|
||||
if (!matches || parts.length <= 1) {
|
||||
return
|
||||
}
|
||||
|
||||
const children: any[] = []
|
||||
|
||||
parts.forEach((part: string, i: number) => {
|
||||
// Add the text before the match
|
||||
if (part) children.push({ type: "text", value: part })
|
||||
if (part) {
|
||||
children.push({ type: "text", value: part })
|
||||
}
|
||||
|
||||
// Add the match, but only make "Act Mode" bold (not the "to" part)
|
||||
if (matches[i]) {
|
||||
@@ -157,22 +167,32 @@ const remarkPreventBoldFilenames = () => {
|
||||
return (tree: any) => {
|
||||
visit(tree, "strong", (node: any, index: number | undefined, parent: any) => {
|
||||
// Only process if there's a next node (potential file extension)
|
||||
if (!parent || typeof index === "undefined" || index === parent.children.length - 1) return
|
||||
if (!parent || typeof index === "undefined" || index === parent.children.length - 1) {
|
||||
return
|
||||
}
|
||||
|
||||
const nextNode = parent.children[index + 1]
|
||||
|
||||
// Check if next node is text and starts with . followed by extension
|
||||
if (nextNode.type !== "text" || !nextNode.value.match(/^\.[a-zA-Z0-9]+/)) return
|
||||
if (nextNode.type !== "text" || !nextNode.value.match(/^\.[a-zA-Z0-9]+/)) {
|
||||
return
|
||||
}
|
||||
|
||||
// If the strong node has multiple children, something weird is happening
|
||||
if (node.children?.length !== 1) return
|
||||
if (node.children?.length !== 1) {
|
||||
return
|
||||
}
|
||||
|
||||
// Get the text content from inside the strong node
|
||||
const strongContent = node.children?.[0]?.value
|
||||
if (!strongContent || typeof strongContent !== "string") return
|
||||
if (!strongContent || typeof strongContent !== "string") {
|
||||
return
|
||||
}
|
||||
|
||||
// Validate that the strong content is a valid filename
|
||||
if (!strongContent.match(/^[a-zA-Z0-9_-]+$/)) return
|
||||
if (!strongContent.match(/^[a-zA-Z0-9_-]+$/)) {
|
||||
return
|
||||
}
|
||||
|
||||
// Combine into a single text node
|
||||
const newNode = {
|
||||
@@ -285,7 +305,9 @@ const PreWithCopyButton = ({ children, ...preProps }: React.HTMLAttributes<HTMLP
|
||||
const codeElement = preRef.current.querySelector("code")
|
||||
const textToCopy = codeElement ? codeElement.textContent : preRef.current.textContent
|
||||
|
||||
if (!textToCopy) return
|
||||
if (!textToCopy) {
|
||||
return
|
||||
}
|
||||
return textToCopy
|
||||
}
|
||||
return null
|
||||
@@ -307,7 +329,7 @@ const PreWithCopyButton = ({ children, ...preProps }: React.HTMLAttributes<HTMLP
|
||||
const remarkFilePathDetection = () => {
|
||||
return async (tree: Node) => {
|
||||
const fileNameRegex = /^(?!\/)[\w\-./]+(?<!\/)$/
|
||||
const inlineCodeNodes: any[] = []
|
||||
const _inlineCodeNodes: any[] = []
|
||||
const filePathPromises: Promise<void>[] = []
|
||||
|
||||
// Collect all inline code nodes that might be file paths
|
||||
@@ -385,7 +407,7 @@ const MarkdownBlock = memo(({ markdown, compact }: MarkdownBlockProps) => {
|
||||
<>
|
||||
<code {...props} />
|
||||
<button
|
||||
className="codicon codicon-link-external bg-transparent border-0 appearance-none p-0 ml-0.5 leading-none align-middle opacity-70 hover:opacity-100 transition-opacity text-[1em] relative top-[1px] text-[var(--vscode-textPreformat-foreground)] translate-y-[-2px]"
|
||||
className="codicon codicon-link-external bg-transparent border-0 appearance-none p-0 ml-0.5 leading-none align-middle opacity-70 hover:opacity-100 transition-opacity text-[1em] relative top-px text-(--vscode-textPreformat-foreground) translate-y-[-2px]"
|
||||
onClick={() => FileServiceClient.openFileRelativePath({ value: filePath })}
|
||||
title={`Open ${filePath} in editor`}
|
||||
type="button"
|
||||
@@ -401,9 +423,12 @@ const MarkdownBlock = memo(({ markdown, compact }: MarkdownBlockProps) => {
|
||||
// Handle both string children and array of children cases
|
||||
const childrenText = React.Children.toArray(props.children)
|
||||
.map((child) => {
|
||||
if (typeof child === "string") return child
|
||||
if (typeof child === "object" && "props" in child && child.props.children)
|
||||
if (typeof child === "string") {
|
||||
return child
|
||||
}
|
||||
if (typeof child === "object" && "props" in child && child.props.children) {
|
||||
return String(child.props.children)
|
||||
}
|
||||
return ""
|
||||
})
|
||||
.join("")
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { EmptyRequest, Int64Request } from "@shared/proto/index.cline"
|
||||
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
|
||||
import { Megaphone } from "lucide-react"
|
||||
import { Megaphone, XIcon } from "lucide-react"
|
||||
import { useCallback } from "react"
|
||||
import { useMount } from "react-use"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { useClineAuth } from "@/context/ClineAuthContext"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { AccountServiceClient, StateServiceClient } from "@/services/grpc-client"
|
||||
@@ -67,14 +67,12 @@ export const NewModelBanner: React.FC = () => {
|
||||
|
||||
return (
|
||||
<div
|
||||
className="px-3 py-2 flex flex-col gap-1 shrink-0 mb-1 relative text-sm mt-1.5 m-4 no-underline transition-colors hover:brightness-120 border-0 cursor-pointer text-left w-auto"
|
||||
className="px-3 py-2 flex flex-col gap-1 shrink-0 mb-1 relative text-sm mt-1.5 m-4 no-underline transition-colors hover:brightness-120 border-0 cursor-pointer text-left w-auto rounded-sm"
|
||||
onClick={handleBannerClick}
|
||||
style={{
|
||||
backgroundColor: getAsVar(VSC_INACTIVE_SELECTION_BACKGROUND),
|
||||
borderRadius: "3px",
|
||||
color: "var(--vscode-foreground)",
|
||||
}}>
|
||||
<h4 className="m-0 flex items-center gap-2" style={{ paddingRight: "18px" }}>
|
||||
<h4 className="m-0 flex items-center gap-2">
|
||||
<Megaphone className="w-4 h-4" />
|
||||
Claude Sonnet 4.5
|
||||
</h4>
|
||||
@@ -84,13 +82,14 @@ export const NewModelBanner: React.FC = () => {
|
||||
</p>
|
||||
|
||||
{/* Close button */}
|
||||
<VSCodeButton
|
||||
appearance="icon"
|
||||
<Button
|
||||
className="absolute top-2.5 right-2"
|
||||
data-testid="info-banner-close-button"
|
||||
onClick={handleClose}
|
||||
style={{ position: "absolute", top: "6px", right: "6px" }}>
|
||||
<span className="codicon codicon-close"></span>
|
||||
</VSCodeButton>
|
||||
size="icon"
|
||||
variant="icon">
|
||||
<XIcon />
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ const StyledButton = styled(VSCodeButton)`
|
||||
|
||||
i.codicon {
|
||||
margin-right: 6px;
|
||||
flex-shrink: 0;
|
||||
shrink: 0;
|
||||
font-size: 16px !important;
|
||||
}
|
||||
`
|
||||
|
||||
@@ -7,13 +7,13 @@ const SuccessButtonTW: React.FC<SuccessButtonTWProps> = (props) => {
|
||||
<VSCodeButton
|
||||
{...props}
|
||||
className={`
|
||||
!bg-[#176f2c]
|
||||
!border-[#176f2c]
|
||||
!text-white
|
||||
hover:!bg-[#197f31]
|
||||
hover:!border-[#197f31]
|
||||
active:!bg-[#156528]
|
||||
active:!border-[#156528]
|
||||
bg-[#176f2c]!
|
||||
border-[#176f2c]!
|
||||
text-white!
|
||||
hover:bg-[#197f31]!
|
||||
hover:border-[#197f31]!
|
||||
active:bg-[#156528]!
|
||||
active:border-[#156528]!
|
||||
${props.className || ""}
|
||||
`
|
||||
.replace(/\s+/g, " ")
|
||||
|
||||
@@ -9,7 +9,7 @@ export const Tab = ({ className, children, ...props }: TabProps) => (
|
||||
)
|
||||
|
||||
export const TabHeader = ({ className, children, ...props }: TabProps) => (
|
||||
<div className={`px-5 py-2.5 border-b border-[var(--vscode-panel-border)] ${className}`} {...props}>
|
||||
<div className={`px-5 py-2.5 border-b border-(--vscode-panel-border) ${className}`} {...props}>
|
||||
{children}
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
import React, { useState } from "react"
|
||||
import styled from "styled-components"
|
||||
import {
|
||||
getAsVar,
|
||||
VSC_DESCRIPTION_FOREGROUND,
|
||||
VSC_INPUT_BORDER,
|
||||
VSC_INPUT_PLACEHOLDER_FOREGROUND,
|
||||
VSC_SIDEBAR_BACKGROUND,
|
||||
} from "@/utils/vscStyles"
|
||||
|
||||
interface TooltipProps {
|
||||
visible?: boolean
|
||||
hintText?: string
|
||||
tipText: string
|
||||
children: React.ReactNode
|
||||
style?: React.CSSProperties
|
||||
}
|
||||
|
||||
// add styled component for tooltip
|
||||
const TooltipBody = styled.div<Pick<TooltipProps, "style">>`
|
||||
position: absolute;
|
||||
background-color: ${getAsVar(VSC_SIDEBAR_BACKGROUND)};
|
||||
color: ${getAsVar(VSC_DESCRIPTION_FOREGROUND)};
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
bottom: 100%;
|
||||
left: ${(props) => props.style?.left ?? -180}%;
|
||||
z-index: ${(props) => props.style?.zIndex ?? 1000};
|
||||
white-space: wrap;
|
||||
max-width: 200px;
|
||||
border: 1px solid ${getAsVar(VSC_INPUT_BORDER)};
|
||||
pointer-events: none;
|
||||
font-size: 0.9em;
|
||||
`
|
||||
|
||||
const Hint = styled.div`
|
||||
font-size: 0.8em;
|
||||
color: ${getAsVar(VSC_INPUT_PLACEHOLDER_FOREGROUND)};
|
||||
opacity: 0.8;
|
||||
margin-top: 2px;
|
||||
`
|
||||
|
||||
const Tooltip: React.FC<TooltipProps> = ({ visible, tipText, hintText, children, style }) => {
|
||||
const [isHovered, setIsHovered] = useState(false)
|
||||
|
||||
// Determine final visibility based on prop or internal state
|
||||
const shouldShow = visible !== undefined ? visible : isHovered
|
||||
|
||||
return (
|
||||
<div
|
||||
onMouseEnter={() => setIsHovered(true)}
|
||||
onMouseLeave={() => setIsHovered(false)}
|
||||
style={{ position: "relative", display: "inline-block" }}>
|
||||
{children}
|
||||
{shouldShow && (
|
||||
<TooltipBody style={style}>
|
||||
{tipText}
|
||||
{hintText && <Hint>{hintText}</Hint>}
|
||||
</TooltipBody>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default Tooltip
|
||||
@@ -29,16 +29,16 @@ interface CustomFilterRadioProps {
|
||||
const CustomFilterRadio = ({ checked, onChange, icon, label }: CustomFilterRadioProps) => {
|
||||
return (
|
||||
<div
|
||||
className="flex items-center cursor-pointer py-[0.3em] px-0 mr-[10px] text-[var(--vscode-font-size)] select-none"
|
||||
className="flex items-center cursor-pointer py-[0.3em] px-0 mr-[10px] text-(--vscode-font-size) select-none"
|
||||
onClick={onChange}>
|
||||
<div
|
||||
className={`w-[14px] h-[14px] rounded-full border border-[var(--vscode-checkbox-border)] relative flex justify-center items-center mr-[6px] ${
|
||||
checked ? "bg-[var(--vscode-checkbox-background)]" : "bg-transparent"
|
||||
className={`w-[14px] h-[14px] rounded-full border border-(--vscode-checkbox-border) relative flex justify-center items-center mr-[6px] ${
|
||||
checked ? "bg-(--vscode-checkbox-background)" : "bg-transparent"
|
||||
}`}>
|
||||
{checked && <div className="w-[6px] h-[6px] rounded-full bg-[var(--vscode-checkbox-foreground)]" />}
|
||||
{checked && <div className="w-[6px] h-[6px] rounded-full bg-(--vscode-checkbox-foreground)" />}
|
||||
</div>
|
||||
<span className="flex items-center gap-[3px]">
|
||||
<div className={`codicon codicon-${icon} text-[var(--vscode-button-background)] text-base`} />
|
||||
<div className={`codicon codicon-${icon} text-(--vscode-button-background) text-base`} />
|
||||
{label}
|
||||
</span>
|
||||
</div>
|
||||
@@ -298,17 +298,7 @@ const HistoryView = ({ onDone }: HistoryViewProps) => {
|
||||
}
|
||||
`}
|
||||
</style>
|
||||
<div
|
||||
style={{
|
||||
position: "fixed",
|
||||
top: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
bottom: 0,
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
overflow: "hidden",
|
||||
}}>
|
||||
<div className="fixed overflow-hidden inset-0 flex flex-col">
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
@@ -326,12 +316,7 @@ const HistoryView = ({ onDone }: HistoryViewProps) => {
|
||||
<VSCodeButton onClick={() => onDone()}>Done</VSCodeButton>
|
||||
</div>
|
||||
<div style={{ padding: "5px 17px 6px 17px" }}>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "6px",
|
||||
}}>
|
||||
<div className="flex flex-col gap-3">
|
||||
<VSCodeTextField
|
||||
onInput={(e) => {
|
||||
const newValue = (e.target as HTMLInputElement)?.value
|
||||
@@ -368,8 +353,8 @@ const HistoryView = ({ onDone }: HistoryViewProps) => {
|
||||
)}
|
||||
</VSCodeTextField>
|
||||
<VSCodeRadioGroup
|
||||
className="flex flex-wrap"
|
||||
onChange={(e) => setSortOption((e.target as HTMLInputElement).value as SortOption)}
|
||||
style={{ display: "flex", flexWrap: "wrap" }}
|
||||
value={sortOption}>
|
||||
<VSCodeRadio value="newest">Newest</VSCodeRadio>
|
||||
<VSCodeRadio value="oldest">Oldest</VSCodeRadio>
|
||||
|
||||
@@ -8,10 +8,10 @@ type AddLocalServerFormProps = {
|
||||
onServerAdded: () => void
|
||||
}
|
||||
|
||||
const AddLocalServerForm = ({ onServerAdded }: AddLocalServerFormProps) => {
|
||||
const AddLocalServerForm = ({}: AddLocalServerFormProps) => {
|
||||
return (
|
||||
<FormContainer>
|
||||
<div className="text-[var(--vscode-foreground)]">
|
||||
<div className="text-(--vscode-foreground)">
|
||||
Add a local MCP server by configuring it in <code>cline_mcp_settings.json</code>. You'll need to specify the
|
||||
server name, command, arguments, and any required environment variables in the JSON configuration. Learn more
|
||||
<VSCodeLink href={LINKS.DOCUMENTATION.LOCAL_MCP_SERVER_DOCS} style={{ display: "inline" }}>
|
||||
|
||||
@@ -65,7 +65,7 @@ const AddRemoteServerForm = ({ onServerAdded }: { onServerAdded: () => void }) =
|
||||
|
||||
return (
|
||||
<div className="p-4 px-5">
|
||||
<div className="text-[var(--vscode-foreground)] mb-2">
|
||||
<div className="text-(--vscode-foreground) mb-2">
|
||||
Add a remote MCP server by providing a name and its URL endpoint. Learn more{" "}
|
||||
<VSCodeLink href={LINKS.DOCUMENTATION.REMOTE_MCP_SERVER_DOCS} style={{ display: "inline" }}>
|
||||
here.
|
||||
@@ -101,7 +101,7 @@ const AddRemoteServerForm = ({ onServerAdded }: { onServerAdded: () => void }) =
|
||||
</VSCodeTextField>
|
||||
</div>
|
||||
|
||||
{error && <div className="mb-3 text-[var(--vscode-errorForeground)]">{error}</div>}
|
||||
{error && <div className="mb-3 text-(--vscode-errorForeground)">{error}</div>}
|
||||
|
||||
<div className="flex items-center mt-3 w-full">
|
||||
<VSCodeButton className="w-full" disabled={isSubmitting} type="submit">
|
||||
@@ -109,7 +109,7 @@ const AddRemoteServerForm = ({ onServerAdded }: { onServerAdded: () => void }) =
|
||||
</VSCodeButton>
|
||||
|
||||
{showConnectingMessage && (
|
||||
<div className="ml-3 text-[var(--vscode-notificationsInfoIcon-foreground)] text-sm">
|
||||
<div className="ml-3 text-(--vscode-notificationsInfoIcon-foreground) text-sm">
|
||||
Connecting to server... This may take a few seconds.
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -27,7 +27,7 @@ const ServersToggleList = ({
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col items-center gap-3 my-5 text-[var(--vscode-descriptionForeground)]">
|
||||
<div className="flex flex-col items-center gap-3 my-5 text-(--vscode-descriptionForeground)">
|
||||
No MCP servers installed
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { TooltipContent } from "@radix-ui/react-tooltip"
|
||||
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
|
||||
import { HistoryIcon, PlusIcon, SettingsIcon, UserCircleIcon } from "lucide-react"
|
||||
import { useMemo } from "react"
|
||||
import { Tooltip, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { TaskServiceClient } from "@/services/grpc-client"
|
||||
import { useExtensionState } from "../../context/ExtensionStateContext"
|
||||
import HeroTooltip from "../common/HeroTooltip"
|
||||
|
||||
// Custom MCP Server Icon component using VSCode codicon
|
||||
const McpServerIcon = ({ className, size }: { className?: string; size?: number }) => (
|
||||
@@ -66,23 +67,25 @@ export const Navbar = () => {
|
||||
|
||||
return (
|
||||
<nav
|
||||
className="flex-none inline-flex justify-end bg-transparent gap-2 mb-1 z-10 border-none items-center mr-4!"
|
||||
id="cline-navbar-container"
|
||||
style={{ gap: "4px" }}>
|
||||
className="flex-none inline-flex justify-end bg-transparent gap-1 mb-1 z-10 border-none items-center mr-4!"
|
||||
id="cline-navbar-container">
|
||||
{SETTINGS_TABS.map((tab) => (
|
||||
<HeroTooltip content={tab.tooltip} key={`navbar-tooltip-${tab.id}`} placement="bottom">
|
||||
<VSCodeButton
|
||||
appearance="icon"
|
||||
aria-label={tab.tooltip}
|
||||
data-testid={`tab-${tab.id}`}
|
||||
key={`navbar-button-${tab.id}`}
|
||||
onClick={() => tab.navigate()}
|
||||
style={{ padding: "0px", height: "20px" }}>
|
||||
<div className="flex items-center gap-1 text-xs whitespace-nowrap min-w-0 w-full">
|
||||
<tab.icon className="text-[var(--vscode-foreground)]" size={18} strokeWidth={1} />
|
||||
</div>
|
||||
</VSCodeButton>
|
||||
</HeroTooltip>
|
||||
<Tooltip key={`navbar-tooltip-${tab.id}`}>
|
||||
<TooltipContent side="bottom">{tab.tooltip}</TooltipContent>
|
||||
<TooltipTrigger asChild>
|
||||
<VSCodeButton
|
||||
appearance="icon"
|
||||
aria-label={tab.tooltip}
|
||||
data-testid={`tab-${tab.id}`}
|
||||
key={`navbar-button-${tab.id}`}
|
||||
onClick={() => tab.navigate()}
|
||||
style={{ padding: "0px", height: "20px" }}>
|
||||
<div className="flex items-center gap-1 text-xs whitespace-nowrap min-w-0 w-full">
|
||||
<tab.icon className="text-(--vscode-foreground)" size={18} strokeWidth={1} />
|
||||
</div>
|
||||
</VSCodeButton>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
))}
|
||||
</nav>
|
||||
)
|
||||
|
||||
@@ -5,8 +5,8 @@ import Fuse from "fuse.js"
|
||||
import { KeyboardEvent, useCallback, useEffect, useMemo, useRef, useState } from "react"
|
||||
import { useInterval } from "react-use"
|
||||
import styled from "styled-components"
|
||||
import HeroTooltip from "@/components/common/HeroTooltip"
|
||||
import { normalizeApiConfiguration } from "@/components/settings/utils/providerUtils"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { PLATFORM_CONFIG, PlatformType } from "@/config/platform.config"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { ModelsServiceClient } from "@/services/grpc-client"
|
||||
@@ -297,14 +297,17 @@ const ApiOptions = ({ showModelOptions, apiErrorMessage, modelIdErrorMessage, is
|
||||
</style>
|
||||
<DropdownContainer className="dropdown-container">
|
||||
{remoteConfigSettings?.planModeApiProvider !== undefined ? (
|
||||
<HeroTooltip content="This setting is managed by your organization's remote configuration">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<label htmlFor="api-provider">
|
||||
<span style={{ fontWeight: 500 }}>API Provider</span>
|
||||
</label>
|
||||
<i className="codicon codicon-lock text-[var(--vscode-descriptionForeground)] text-sm" />
|
||||
</div>
|
||||
</HeroTooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<label htmlFor="api-provider">
|
||||
<span style={{ fontWeight: 500 }}>API Provider</span>
|
||||
</label>
|
||||
<i className="codicon codicon-lock text-[var(--vscode-descriptionForeground)] text-sm" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>This setting is managed by your organization's remote configuration</TooltipContent>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<label htmlFor="api-provider">
|
||||
<span style={{ fontWeight: 500 }}>API Provider</span>
|
||||
|
||||
@@ -241,7 +241,7 @@ const BasetenModelPicker: React.FC<BasetenModelPickerProps> = ({ isPopup, curren
|
||||
</VSCodeTextField>
|
||||
{isDropdownVisible && (
|
||||
<div
|
||||
className="absolute top-[calc(100%-3px)] left-0 w-[calc(100%-2px)] max-h-[200px] overflow-y-auto border border-[var(--vscode-list-activeSelectionBackground)] rounded-b-[3px]"
|
||||
className="absolute top-[calc(100%-3px)] left-0 w-[calc(100%-2px)] max-h-[200px] overflow-y-auto border border-(--vscode-list-activeSelectionBackground) rounded-b-[3px]"
|
||||
ref={dropdownListRef}
|
||||
style={{
|
||||
backgroundColor: "var(--vscode-dropdown-background)",
|
||||
@@ -249,8 +249,8 @@ const BasetenModelPicker: React.FC<BasetenModelPickerProps> = ({ isPopup, curren
|
||||
}}>
|
||||
{modelSearchResults.map((item, index) => (
|
||||
<div
|
||||
className={`px-2.5 py-1.5 cursor-pointer break-all whitespace-normal hover:bg-[var(--vscode-list-activeSelectionBackground)] ${
|
||||
index === selectedIndex ? "bg-[var(--vscode-list-activeSelectionBackground)]" : ""
|
||||
className={`px-2.5 py-1.5 cursor-pointer break-all whitespace-normal hover:bg-(--vscode-list-activeSelectionBackground) ${
|
||||
index === selectedIndex ? "bg-(--vscode-list-activeSelectionBackground)" : ""
|
||||
}`}
|
||||
key={item.id}
|
||||
onClick={() => {
|
||||
@@ -272,7 +272,7 @@ const BasetenModelPicker: React.FC<BasetenModelPickerProps> = ({ isPopup, curren
|
||||
{hasInfo ? (
|
||||
<ModelInfoView isPopup={isPopup} modelInfo={selectedModelInfo} selectedModelId={selectedModelId} />
|
||||
) : (
|
||||
<p className="text-xs mt-0 text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs mt-0 text-(--vscode-descriptionForeground)">
|
||||
The extension automatically fetches the latest list of models available on{" "}
|
||||
<VSCodeLink className="inline text-inherit" href="https://www.baseten.co/products/model-apis/">
|
||||
Baseten.
|
||||
|
||||
@@ -223,7 +223,7 @@ const GroqModelPicker: React.FC<GroqModelPickerProps> = ({ isPopup, currentMode
|
||||
</VSCodeTextField>
|
||||
{isDropdownVisible && (
|
||||
<div
|
||||
className="absolute top-[calc(100%-3px)] left-0 w-[calc(100%-2px)] max-h-[200px] overflow-y-auto border border-[var(--vscode-list-activeSelectionBackground)] rounded-b-[3px]"
|
||||
className="absolute top-[calc(100%-3px)] left-0 w-[calc(100%-2px)] max-h-[200px] overflow-y-auto border border-(--vscode-list-activeSelectionBackground) rounded-b-[3px]"
|
||||
ref={dropdownListRef}
|
||||
style={{
|
||||
backgroundColor: "var(--vscode-dropdown-background)",
|
||||
@@ -231,8 +231,8 @@ const GroqModelPicker: React.FC<GroqModelPickerProps> = ({ isPopup, currentMode
|
||||
}}>
|
||||
{modelSearchResults.map((item, index) => (
|
||||
<div
|
||||
className={`px-2.5 py-1.5 cursor-pointer break-all whitespace-normal hover:bg-[var(--vscode-list-activeSelectionBackground)] ${
|
||||
index === selectedIndex ? "bg-[var(--vscode-list-activeSelectionBackground)]" : ""
|
||||
className={`px-2.5 py-1.5 cursor-pointer break-all whitespace-normal hover:bg-(--vscode-list-activeSelectionBackground) ${
|
||||
index === selectedIndex ? "bg-(--vscode-list-activeSelectionBackground)" : ""
|
||||
}`}
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: item.html,
|
||||
@@ -254,7 +254,7 @@ const GroqModelPicker: React.FC<GroqModelPickerProps> = ({ isPopup, currentMode
|
||||
{hasInfo ? (
|
||||
<ModelInfoView isPopup={isPopup} modelInfo={selectedModelInfo} selectedModelId={selectedModelId} />
|
||||
) : (
|
||||
<p className="text-xs mt-0 text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs mt-0 text-(--vscode-descriptionForeground)">
|
||||
The extension automatically fetches the latest list of models available on{" "}
|
||||
<VSCodeLink className="inline text-inherit" href="https://console.groq.com/docs/models">
|
||||
Groq.
|
||||
|
||||
@@ -171,7 +171,7 @@ const HuggingFaceModelPicker: React.FC<HuggingFaceModelPickerProps> = ({ isPopup
|
||||
|
||||
<div className="relative w-full" ref={dropdownRef}>
|
||||
<VSCodeTextField
|
||||
className="w-full relative z-[1000]"
|
||||
className="w-full relative z-1000"
|
||||
id="hf-model-search"
|
||||
onFocus={() => setIsDropdownVisible(true)}
|
||||
onInput={(e: any) => {
|
||||
@@ -204,13 +204,13 @@ const HuggingFaceModelPicker: React.FC<HuggingFaceModelPickerProps> = ({ isPopup
|
||||
<div
|
||||
className={`absolute top-[calc(100%-3px)] left-0 w-[calc(100%-2px)] ${
|
||||
isPopup ? "max-h-[90px]" : "max-h-[200px]"
|
||||
} overflow-y-auto bg-[var(--vscode-dropdown-background)] border border-[var(--vscode-list-activeSelectionBackground)] z-[999] rounded-b-[3px]`}
|
||||
} overflow-y-auto bg-(--vscode-dropdown-background) border border-(--vscode-list-activeSelectionBackground) z-999 rounded-b-[3px]`}
|
||||
ref={dropdownListRef}>
|
||||
{modelSearchResults.map((result, index) => (
|
||||
<div
|
||||
className={`p-[5px_10px] cursor-pointer break-all whitespace-normal ${
|
||||
index === selectedIndex ? "bg-[var(--vscode-list-activeSelectionBackground)]" : ""
|
||||
} hover:bg-[var(--vscode-list-activeSelectionBackground)]`}
|
||||
index === selectedIndex ? "bg-(--vscode-list-activeSelectionBackground)" : ""
|
||||
} hover:bg-(--vscode-list-activeSelectionBackground)`}
|
||||
key={result.id}
|
||||
onClick={() => {
|
||||
handleModelChange(result.id)
|
||||
@@ -219,7 +219,7 @@ const HuggingFaceModelPicker: React.FC<HuggingFaceModelPickerProps> = ({ isPopup
|
||||
onMouseEnter={() => setSelectedIndex(index)}
|
||||
ref={(el: HTMLDivElement | null) => (itemRefs.current[index] = el)}>
|
||||
<div
|
||||
className="[&_.model-item-highlight]:bg-[var(--vscode-editor-findMatchHighlightBackground)] [&_.model-item-highlight]:text-inherit"
|
||||
className="[&_.model-item-highlight]:bg-(--vscode-editor-findMatchHighlightBackground) [&_.model-item-highlight]:text-inherit"
|
||||
dangerouslySetInnerHTML={{ __html: result.html }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -41,7 +41,7 @@ const PreferredLanguageSetting: React.FC = () => {
|
||||
<VSCodeOption value="Traditional Chinese - 繁體中文">Traditional Chinese - 繁體中文</VSCodeOption>
|
||||
<VSCodeOption value="Turkish - Türkçe">Turkish - Türkçe</VSCodeOption>
|
||||
</VSCodeDropdown>
|
||||
<p className="text-xs text-[var(--vscode-descriptionForeground)] mt-1">
|
||||
<p className="text-xs text-(--vscode-descriptionForeground) mt-1">
|
||||
The language that Cline should use for communication.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { TooltipTrigger } from "@radix-ui/react-tooltip"
|
||||
import { ExtensionMessage } from "@shared/ExtensionMessage"
|
||||
import { ResetStateRequest } from "@shared/proto/cline/state"
|
||||
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
|
||||
@@ -14,7 +15,7 @@ import {
|
||||
} from "lucide-react"
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react"
|
||||
import { useEvent } from "react-use"
|
||||
import HeroTooltip from "@/components/common/HeroTooltip"
|
||||
import { Tooltip, TooltipContent } from "@/components/ui/tooltip"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { StateServiceClient } from "@/services/grpc-client"
|
||||
import { getEnvironmentColor } from "@/utils/environmentColors"
|
||||
@@ -33,11 +34,11 @@ const IS_DEV = process.env.IS_DEV
|
||||
// Styles for the tab system
|
||||
const settingsTabsContainer = "flex flex-1 overflow-hidden [&.narrow_.tab-label]:hidden"
|
||||
const settingsTabList =
|
||||
"w-48 data-[compact=true]:w-12 flex-shrink-0 flex flex-col overflow-y-auto overflow-x-hidden border-r border-[var(--vscode-sideBar-background)]"
|
||||
"w-48 data-[compact=true]:w-12 shrink-0 flex flex-col overflow-y-auto overflow-x-hidden border-r border-(--vscode-sideBar-background)"
|
||||
const settingsTabTrigger =
|
||||
"whitespace-nowrap overflow-hidden min-w-0 h-12 px-4 py-3 box-border flex items-center border-l-2 border-transparent text-[var(--vscode-foreground)] opacity-70 bg-transparent hover:bg-[var(--vscode-list-hoverBackground)] data-[compact=true]:w-12 data-[compact=true]:p-4 cursor-pointer"
|
||||
"whitespace-nowrap overflow-hidden min-w-0 h-12 px-4 py-3 box-border flex items-center border-l-2 border-transparent text-(--vscode-foreground) opacity-70 bg-transparent hover:bg-(--vscode-list-hoverBackground) data-[compact=true]:w-12 data-[compact=true]:p-4 cursor-pointer"
|
||||
const settingsTabTriggerActive =
|
||||
"opacity-100 border-l-2 border-l-[var(--vscode-focusBorder)] border-t-0 border-r-0 border-b-0 bg-[var(--vscode-list-activeSelectionBackground)]"
|
||||
"opacity-100 border-l-2 border-l-(--vscode-focusBorder) border-t-0 border-r-0 border-b-0 bg-(--vscode-list-activeSelectionBackground)"
|
||||
|
||||
// Tab definitions
|
||||
interface SettingsTab {
|
||||
@@ -251,16 +252,19 @@ const SettingsView = ({ onDone, targetSection }: SettingsViewProps) => {
|
||||
|
||||
if (isCompactMode) {
|
||||
return (
|
||||
<HeroTooltip content={tab.tooltipText} key={tab.id} placement="right">
|
||||
<div
|
||||
className={tabClassName}
|
||||
data-compact={isCompactMode}
|
||||
data-testid={`tab-${tab.id}`}
|
||||
data-value={tab.id}
|
||||
onClick={() => handleTabChange(tab.id)}>
|
||||
{tabContent}
|
||||
</div>
|
||||
</HeroTooltip>
|
||||
<Tooltip key={tab.id}>
|
||||
<TooltipTrigger>
|
||||
<div
|
||||
className={tabClassName}
|
||||
data-compact={isCompactMode}
|
||||
data-testid={`tab-${tab.id}`}
|
||||
data-value={tab.id}
|
||||
onClick={() => handleTabChange(tab.id)}>
|
||||
{tabContent}
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent side="right">{tab.tooltipText}</TooltipContent>
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -50,19 +50,12 @@ export const ModelSelector = ({ models, selectedModelId, onChange, zIndex, label
|
||||
return (
|
||||
<DropdownContainer className="dropdown-container" zIndex={zIndex}>
|
||||
<label htmlFor="model-id">
|
||||
<span style={{ fontWeight: 500 }}>{label}</span>
|
||||
<span className="font-medium">{label}</span>
|
||||
</label>
|
||||
<VSCodeDropdown id="model-id" onChange={onChange} style={{ width: "100%" }} value={selectedModelId}>
|
||||
<VSCodeDropdown className="w-full" id="model-id" onChange={onChange} value={selectedModelId}>
|
||||
<VSCodeOption value="">Select a model...</VSCodeOption>
|
||||
{Object.keys(models).map((modelId) => (
|
||||
<VSCodeOption
|
||||
key={modelId}
|
||||
style={{
|
||||
whiteSpace: "normal",
|
||||
wordWrap: "break-word",
|
||||
maxWidth: "100%",
|
||||
}}
|
||||
value={modelId}>
|
||||
<VSCodeOption className="break-words whitespace-normal max-w-full" key={modelId} value={modelId}>
|
||||
{modelId}
|
||||
</VSCodeOption>
|
||||
))}
|
||||
|
||||
@@ -2,7 +2,7 @@ import { bedrockDefaultModelId, bedrockModels, CLAUDE_SONNET_1M_SUFFIX } from "@
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { VSCodeCheckbox, VSCodeDropdown, VSCodeOption, VSCodeRadio, VSCodeRadioGroup } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useState } from "react"
|
||||
import HeroTooltip from "@/components/common/HeroTooltip"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { DebouncedTextField } from "../common/DebouncedTextField"
|
||||
import { ModelInfoView } from "../common/ModelInfoView"
|
||||
@@ -97,51 +97,54 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
)}
|
||||
|
||||
{remoteConfigSettings?.awsRegion !== undefined ? (
|
||||
<HeroTooltip content="This setting is managed by your organization's remote configuration">
|
||||
<DropdownContainer className="dropdown-container mb-2.5" zIndex={DROPDOWN_Z_INDEX - 1}>
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<label htmlFor="aws-region-dropdown">
|
||||
<span style={{ fontWeight: 500 }}>AWS Region</span>
|
||||
</label>
|
||||
<i className="codicon codicon-lock text-[var(--vscode-descriptionForeground)] text-sm flex items-center" />
|
||||
</div>
|
||||
<VSCodeDropdown
|
||||
disabled={true}
|
||||
id="aws-region-dropdown"
|
||||
onChange={(e: any) => handleFieldChange("awsRegion", e.target.value)}
|
||||
style={{ width: "100%" }}
|
||||
value={apiConfiguration?.awsRegion || ""}>
|
||||
<VSCodeOption value="">Select a region...</VSCodeOption>
|
||||
{/* The user will have to choose a region that supports the model they use, but this shouldn't be a problem since they'd have to request access for it in that region in the first place. */}
|
||||
<VSCodeOption value="us-east-1">us-east-1</VSCodeOption>
|
||||
<VSCodeOption value="us-east-2">us-east-2</VSCodeOption>
|
||||
<VSCodeOption value="us-west-1">us-west-1</VSCodeOption>
|
||||
<VSCodeOption value="us-west-2">us-west-2</VSCodeOption>
|
||||
{/* <VSCodeOption value="af-south-1">af-south-1</VSCodeOption> */}
|
||||
{/* <VSCodeOption value="ap-east-1">ap-east-1</VSCodeOption> */}
|
||||
<VSCodeOption value="ap-south-1">ap-south-1</VSCodeOption>
|
||||
<VSCodeOption value="ap-northeast-1">ap-northeast-1</VSCodeOption>
|
||||
<VSCodeOption value="ap-northeast-2">ap-northeast-2</VSCodeOption>
|
||||
<VSCodeOption value="ap-northeast-3">ap-northeast-3</VSCodeOption>
|
||||
<VSCodeOption value="ap-southeast-1">ap-southeast-1</VSCodeOption>
|
||||
<VSCodeOption value="ap-southeast-2">ap-southeast-2</VSCodeOption>
|
||||
<VSCodeOption value="ca-central-1">ca-central-1</VSCodeOption>
|
||||
<VSCodeOption value="eu-central-1">eu-central-1</VSCodeOption>
|
||||
<VSCodeOption value="eu-central-2">eu-central-2</VSCodeOption>
|
||||
<VSCodeOption value="eu-west-1">eu-west-1</VSCodeOption>
|
||||
<VSCodeOption value="eu-west-2">eu-west-2</VSCodeOption>
|
||||
<VSCodeOption value="eu-west-3">eu-west-3</VSCodeOption>
|
||||
<VSCodeOption value="eu-north-1">eu-north-1</VSCodeOption>
|
||||
<VSCodeOption value="eu-south-1">eu-south-1</VSCodeOption>
|
||||
<VSCodeOption value="eu-south-2">eu-south-2</VSCodeOption>
|
||||
{/* <VSCodeOption value="me-south-1">me-south-1</VSCodeOption> */}
|
||||
<VSCodeOption value="sa-east-1">sa-east-1</VSCodeOption>
|
||||
<VSCodeOption value="us-gov-east-1">us-gov-east-1</VSCodeOption>
|
||||
<VSCodeOption value="us-gov-west-1">us-gov-west-1</VSCodeOption>
|
||||
{/* <VSCodeOption value="us-gov-east-1">us-gov-east-1</VSCodeOption> */}
|
||||
</VSCodeDropdown>
|
||||
</DropdownContainer>
|
||||
</HeroTooltip>
|
||||
<Tooltip>
|
||||
<TooltipContent>This setting is managed by your organization's remote configuration</TooltipContent>
|
||||
<TooltipTrigger>
|
||||
<DropdownContainer className="dropdown-container mb-2.5" zIndex={DROPDOWN_Z_INDEX - 1}>
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<label htmlFor="aws-region-dropdown">
|
||||
<span style={{ fontWeight: 500 }}>AWS Region</span>
|
||||
</label>
|
||||
<i className="codicon codicon-lock text-[var(--vscode-descriptionForeground)] text-sm flex items-center" />
|
||||
</div>
|
||||
<VSCodeDropdown
|
||||
disabled={true}
|
||||
id="aws-region-dropdown"
|
||||
onChange={(e: any) => handleFieldChange("awsRegion", e.target.value)}
|
||||
style={{ width: "100%" }}
|
||||
value={apiConfiguration?.awsRegion || ""}>
|
||||
<VSCodeOption value="">Select a region...</VSCodeOption>
|
||||
{/* The user will have to choose a region that supports the model they use, but this shouldn't be a problem since they'd have to request access for it in that region in the first place. */}
|
||||
<VSCodeOption value="us-east-1">us-east-1</VSCodeOption>
|
||||
<VSCodeOption value="us-east-2">us-east-2</VSCodeOption>
|
||||
<VSCodeOption value="us-west-1">us-west-1</VSCodeOption>
|
||||
<VSCodeOption value="us-west-2">us-west-2</VSCodeOption>
|
||||
{/* <VSCodeOption value="af-south-1">af-south-1</VSCodeOption> */}
|
||||
{/* <VSCodeOption value="ap-east-1">ap-east-1</VSCodeOption> */}
|
||||
<VSCodeOption value="ap-south-1">ap-south-1</VSCodeOption>
|
||||
<VSCodeOption value="ap-northeast-1">ap-northeast-1</VSCodeOption>
|
||||
<VSCodeOption value="ap-northeast-2">ap-northeast-2</VSCodeOption>
|
||||
<VSCodeOption value="ap-northeast-3">ap-northeast-3</VSCodeOption>
|
||||
<VSCodeOption value="ap-southeast-1">ap-southeast-1</VSCodeOption>
|
||||
<VSCodeOption value="ap-southeast-2">ap-southeast-2</VSCodeOption>
|
||||
<VSCodeOption value="ca-central-1">ca-central-1</VSCodeOption>
|
||||
<VSCodeOption value="eu-central-1">eu-central-1</VSCodeOption>
|
||||
<VSCodeOption value="eu-central-2">eu-central-2</VSCodeOption>
|
||||
<VSCodeOption value="eu-west-1">eu-west-1</VSCodeOption>
|
||||
<VSCodeOption value="eu-west-2">eu-west-2</VSCodeOption>
|
||||
<VSCodeOption value="eu-west-3">eu-west-3</VSCodeOption>
|
||||
<VSCodeOption value="eu-north-1">eu-north-1</VSCodeOption>
|
||||
<VSCodeOption value="eu-south-1">eu-south-1</VSCodeOption>
|
||||
<VSCodeOption value="eu-south-2">eu-south-2</VSCodeOption>
|
||||
{/* <VSCodeOption value="me-south-1">me-south-1</VSCodeOption> */}
|
||||
<VSCodeOption value="sa-east-1">sa-east-1</VSCodeOption>
|
||||
<VSCodeOption value="us-gov-east-1">us-gov-east-1</VSCodeOption>
|
||||
<VSCodeOption value="us-gov-west-1">us-gov-west-1</VSCodeOption>
|
||||
{/* <VSCodeOption value="us-gov-east-1">us-gov-east-1</VSCodeOption> */}
|
||||
</VSCodeDropdown>
|
||||
</DropdownContainer>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<DropdownContainer className="dropdown-container" zIndex={DROPDOWN_Z_INDEX - 1}>
|
||||
<label htmlFor="aws-region-dropdown">
|
||||
@@ -186,36 +189,39 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
|
||||
<div style={{ display: "flex", flexDirection: "column" }}>
|
||||
{remoteConfigSettings?.awsBedrockEndpoint !== undefined ? (
|
||||
<HeroTooltip content="This setting is managed by your organization's remote configuration">
|
||||
<div>
|
||||
<div className="flex items-center gap-2">
|
||||
<VSCodeCheckbox
|
||||
checked={awsEndpointSelected}
|
||||
disabled={true}
|
||||
onChange={(e: any) => {
|
||||
const isChecked = e.target.checked === true
|
||||
setAwsEndpointSelected(isChecked)
|
||||
if (!isChecked) {
|
||||
handleFieldChange("awsBedrockEndpoint", "")
|
||||
}
|
||||
}}>
|
||||
Use custom VPC endpoint
|
||||
</VSCodeCheckbox>
|
||||
<i className="codicon codicon-lock text-[var(--vscode-descriptionForeground)] text-sm" />
|
||||
</div>
|
||||
<Tooltip>
|
||||
<TooltipContent>This setting is managed by your organization's remote configuration</TooltipContent>
|
||||
<TooltipTrigger>
|
||||
<div>
|
||||
<div className="flex items-center gap-2">
|
||||
<VSCodeCheckbox
|
||||
checked={awsEndpointSelected}
|
||||
disabled={true}
|
||||
onChange={(e: any) => {
|
||||
const isChecked = e.target.checked === true
|
||||
setAwsEndpointSelected(isChecked)
|
||||
if (!isChecked) {
|
||||
handleFieldChange("awsBedrockEndpoint", "")
|
||||
}
|
||||
}}>
|
||||
Use custom VPC endpoint
|
||||
</VSCodeCheckbox>
|
||||
<i className="codicon codicon-lock text-[var(--vscode-descriptionForeground)] text-sm" />
|
||||
</div>
|
||||
|
||||
{awsEndpointSelected && (
|
||||
<DebouncedTextField
|
||||
disabled={true}
|
||||
initialValue={apiConfiguration?.awsBedrockEndpoint || ""}
|
||||
onChange={(value) => handleFieldChange("awsBedrockEndpoint", value)}
|
||||
placeholder="Enter VPC Endpoint URL (optional)"
|
||||
style={{ width: "100%", marginTop: 3, marginBottom: 5 }}
|
||||
type="text"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</HeroTooltip>
|
||||
{awsEndpointSelected && (
|
||||
<DebouncedTextField
|
||||
disabled={true}
|
||||
initialValue={apiConfiguration?.awsBedrockEndpoint || ""}
|
||||
onChange={(value) => handleFieldChange("awsBedrockEndpoint", value)}
|
||||
placeholder="Enter VPC Endpoint URL (optional)"
|
||||
style={{ width: "100%", marginTop: 3, marginBottom: 5 }}
|
||||
type="text"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<>
|
||||
<VSCodeCheckbox
|
||||
@@ -243,21 +249,24 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
)}
|
||||
|
||||
{remoteConfigSettings?.awsUseCrossRegionInference !== undefined ? (
|
||||
<HeroTooltip content="This setting is managed by your organization's remote configuration">
|
||||
<div className="flex items-center gap-2">
|
||||
<VSCodeCheckbox
|
||||
checked={apiConfiguration?.awsUseCrossRegionInference || false}
|
||||
disabled={true}
|
||||
onChange={(e: any) => {
|
||||
const isChecked = e.target.checked === true
|
||||
<Tooltip>
|
||||
<TooltipContent>This setting is managed by your organization's remote configuration</TooltipContent>
|
||||
<TooltipTrigger>
|
||||
<div className="flex items-center gap-2">
|
||||
<VSCodeCheckbox
|
||||
checked={apiConfiguration?.awsUseCrossRegionInference || false}
|
||||
disabled={true}
|
||||
onChange={(e: any) => {
|
||||
const isChecked = e.target.checked === true
|
||||
|
||||
handleFieldChange("awsUseCrossRegionInference", isChecked)
|
||||
}}>
|
||||
Use cross-region inference
|
||||
</VSCodeCheckbox>
|
||||
<i className="codicon codicon-lock text-[var(--vscode-descriptionForeground)] text-sm" />
|
||||
</div>
|
||||
</HeroTooltip>
|
||||
handleFieldChange("awsUseCrossRegionInference", isChecked)
|
||||
}}>
|
||||
Use cross-region inference
|
||||
</VSCodeCheckbox>
|
||||
<i className="codicon codicon-lock text-[var(--vscode-descriptionForeground)] text-sm" />
|
||||
</div>{" "}
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<VSCodeCheckbox
|
||||
checked={apiConfiguration?.awsUseCrossRegionInference || false}
|
||||
@@ -273,20 +282,23 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
{apiConfiguration?.awsUseCrossRegionInference &&
|
||||
selectedModelInfo.supportsGlobalEndpoint &&
|
||||
(remoteConfigSettings?.awsUseGlobalInference !== undefined ? (
|
||||
<HeroTooltip content="This setting is managed by your organization's remote configuration">
|
||||
<div className="flex items-center gap-2">
|
||||
<VSCodeCheckbox
|
||||
checked={apiConfiguration?.awsUseGlobalInference || false}
|
||||
disabled={true}
|
||||
onChange={(e: any) => {
|
||||
const isChecked = e.target.checked === true
|
||||
handleFieldChange("awsUseGlobalInference", isChecked)
|
||||
}}>
|
||||
Use global inference profile
|
||||
</VSCodeCheckbox>
|
||||
<i className="codicon codicon-lock text-[var(--vscode-descriptionForeground)] text-sm" />
|
||||
</div>
|
||||
</HeroTooltip>
|
||||
<Tooltip>
|
||||
<TooltipContent>This setting is managed by your organization's remote configuration</TooltipContent>
|
||||
<TooltipTrigger>
|
||||
<div className="flex items-center gap-2">
|
||||
<VSCodeCheckbox
|
||||
checked={apiConfiguration?.awsUseGlobalInference || false}
|
||||
disabled={true}
|
||||
onChange={(e: any) => {
|
||||
const isChecked = e.target.checked === true
|
||||
handleFieldChange("awsUseGlobalInference", isChecked)
|
||||
}}>
|
||||
Use global inference profile
|
||||
</VSCodeCheckbox>
|
||||
<i className="codicon codicon-lock text-[var(--vscode-descriptionForeground)] text-sm" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<VSCodeCheckbox
|
||||
checked={apiConfiguration?.awsUseGlobalInference || false}
|
||||
@@ -300,20 +312,23 @@ export const BedrockProvider = ({ showModelOptions, isPopup, currentMode }: Bedr
|
||||
|
||||
{selectedModelInfo.supportsPromptCache &&
|
||||
(remoteConfigSettings?.awsBedrockUsePromptCache !== undefined ? (
|
||||
<HeroTooltip content="This setting is managed by your organization's remote configuration">
|
||||
<div className="flex items-center gap-2">
|
||||
<VSCodeCheckbox
|
||||
checked={apiConfiguration?.awsBedrockUsePromptCache || false}
|
||||
disabled={true}
|
||||
onChange={(e: any) => {
|
||||
const isChecked = e.target.checked === true
|
||||
handleFieldChange("awsBedrockUsePromptCache", isChecked)
|
||||
}}>
|
||||
Use prompt caching
|
||||
</VSCodeCheckbox>
|
||||
<i className="codicon codicon-lock text-[var(--vscode-descriptionForeground)] text-sm" />
|
||||
</div>
|
||||
</HeroTooltip>
|
||||
<Tooltip>
|
||||
<TooltipContent>This setting is managed by your organization's remote configuration</TooltipContent>
|
||||
<TooltipTrigger>
|
||||
<div className="flex items-center gap-2">
|
||||
<VSCodeCheckbox
|
||||
checked={apiConfiguration?.awsBedrockUsePromptCache || false}
|
||||
disabled={true}
|
||||
onChange={(e: any) => {
|
||||
const isChecked = e.target.checked === true
|
||||
handleFieldChange("awsBedrockUsePromptCache", isChecked)
|
||||
}}>
|
||||
Use prompt caching
|
||||
</VSCodeCheckbox>
|
||||
<i className="codicon codicon-lock text-[var(--vscode-descriptionForeground)] text-sm" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<VSCodeCheckbox
|
||||
checked={apiConfiguration?.awsBedrockUsePromptCache || false}
|
||||
|
||||
@@ -110,7 +110,7 @@ const OcaModelPicker: React.FC<OcaModelPickerProps> = ({
|
||||
}
|
||||
`}</style>
|
||||
<label className="font-medium text-[12px] mt-[10px] mb-[2px]">Model</label>
|
||||
<div className="relative z-[100] flex items-center gap-2 mb-1">
|
||||
<div className="relative z-100 flex items-center gap-2 mb-1">
|
||||
<VSCodeDropdown
|
||||
className="flex-1 text-[12px] min-h-[24px]"
|
||||
id="model-id"
|
||||
@@ -151,7 +151,7 @@ const OcaModelPicker: React.FC<OcaModelPickerProps> = ({
|
||||
</VSCodeButton>
|
||||
</div>
|
||||
{lastRefreshedText ? (
|
||||
<div className="text-[11px] text-[var(--vscode-descriptionForeground)] mt-0 mb-2">
|
||||
<div className="text-[11px] text-(--vscode-descriptionForeground) mt-0 mb-2">
|
||||
Last refreshed at {lastRefreshedText}
|
||||
</div>
|
||||
) : null}
|
||||
@@ -171,7 +171,7 @@ const OcaRestrictivePopup: React.FC<{
|
||||
onAcknowledge: () => void
|
||||
bannerText?: string | null
|
||||
}> = React.memo(({ onAcknowledge, bannerText }) => (
|
||||
<div className="fixed top-0 left-0 w-screen h-screen z-[2000] [background:rgba(0,0,0,0.25)] flex items-center justify-center">
|
||||
<div className="fixed top-0 left-0 w-screen h-screen z-2000 [background:rgba(0,0,0,0.25)] flex items-center justify-center">
|
||||
<div
|
||||
aria-labelledby="oca-popup-title"
|
||||
aria-modal="true"
|
||||
@@ -183,7 +183,7 @@ const OcaRestrictivePopup: React.FC<{
|
||||
<h4 className={`mb-2 [color:var(${VSC_DESCRIPTION_FOREGROUND},#b3b3b3)] font-semibold`}>
|
||||
Disclaimer: Prohibited Data Submission
|
||||
</h4>
|
||||
<div className="overflow-y-auto flex-1 pr-2 mb-4 text-[13px] leading-[1.5] [color:var(--vscode-foreground,#222)] [mask-image:linear-gradient(to_bottom,black_96%,transparent_100%)]">
|
||||
<div className="overflow-y-auto flex-1 pr-2 mb-4 text-[13px] leading-normal text-(--vscode-foreground,#222) mask-[linear-gradient(to_bottom,black_96%,transparent_100%)]">
|
||||
{bannerText && <div dangerouslySetInnerHTML={{ __html: bannerText }} />}
|
||||
</div>
|
||||
<div className="text-right">
|
||||
|
||||
@@ -306,7 +306,7 @@ export const OcaProvider = ({ isPopup, currentMode }: OcaProviderProps) => {
|
||||
}}>
|
||||
Sign in with Oracle Code Assist
|
||||
</VSCodeButton>
|
||||
<p className="text-xs mt-0 text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs mt-0 text-(--vscode-descriptionForeground)">
|
||||
Please ask your IT administrator to set up Oracle Code Assist as a model provider. Oracle Employees,
|
||||
please see the{" "}
|
||||
<VSCodeLink
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { TooltipContent, TooltipTrigger } from "@radix-ui/react-tooltip"
|
||||
import { azureOpenAiDefaultApiVersion, openAiModelInfoSaneDefaults } from "@shared/api"
|
||||
import { OpenAiModelsRequest } from "@shared/proto/cline/models"
|
||||
import { Mode } from "@shared/storage/types"
|
||||
import { VSCodeButton, VSCodeCheckbox } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useCallback, useEffect, useRef, useState } from "react"
|
||||
import HeroTooltip from "@/components/common/HeroTooltip"
|
||||
import { Tooltip } from "@/components/ui/tooltip"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { ModelsServiceClient } from "@/services/grpc-client"
|
||||
import { getAsVar, VSC_DESCRIPTION_FOREGROUND } from "@/utils/vscStyles"
|
||||
@@ -71,25 +72,28 @@ export const OpenAICompatibleProvider = ({ showModelOptions, isPopup, currentMod
|
||||
return (
|
||||
<div>
|
||||
{remoteConfigSettings?.openAiBaseUrl !== undefined ? (
|
||||
<HeroTooltip content="This setting is managed by your organization's remote configuration">
|
||||
<div className="mb-2.5">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<span style={{ fontWeight: 500 }}>Base URL</span>
|
||||
<i className="codicon codicon-lock text-[var(--vscode-descriptionForeground)] text-sm" />
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<div className="mb-2.5">
|
||||
<div className="flex items-center gap-2 mb-1">
|
||||
<span style={{ fontWeight: 500 }}>Base URL</span>
|
||||
<i className="codicon codicon-lock text-[var(--vscode-descriptionForeground)] text-sm" />
|
||||
</div>
|
||||
<DebouncedTextField
|
||||
disabled={true}
|
||||
initialValue={apiConfiguration?.openAiBaseUrl || ""}
|
||||
onChange={(value) => {
|
||||
handleFieldChange("openAiBaseUrl", value)
|
||||
debouncedRefreshOpenAiModels(value, apiConfiguration?.openAiApiKey)
|
||||
}}
|
||||
placeholder={"Enter base URL..."}
|
||||
style={{ width: "100%" }}
|
||||
type="url"
|
||||
/>
|
||||
</div>
|
||||
<DebouncedTextField
|
||||
disabled={true}
|
||||
initialValue={apiConfiguration?.openAiBaseUrl || ""}
|
||||
onChange={(value) => {
|
||||
handleFieldChange("openAiBaseUrl", value)
|
||||
debouncedRefreshOpenAiModels(value, apiConfiguration?.openAiApiKey)
|
||||
}}
|
||||
placeholder={"Enter base URL..."}
|
||||
style={{ width: "100%" }}
|
||||
type="url"
|
||||
/>
|
||||
</div>
|
||||
</HeroTooltip>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>This setting is managed by your organization's remote configuration</TooltipContent>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<DebouncedTextField
|
||||
initialValue={apiConfiguration?.openAiBaseUrl || ""}
|
||||
@@ -131,12 +135,17 @@ export const OpenAICompatibleProvider = ({ showModelOptions, isPopup, currentMod
|
||||
<div style={{ marginBottom: 10 }}>
|
||||
{remoteConfigSettings?.openAiHeaders !== undefined ? (
|
||||
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "center" }}>
|
||||
<HeroTooltip content="This setting is managed by your organization's remote configuration">
|
||||
<div className="flex items-center gap-2">
|
||||
<span style={{ fontWeight: 500 }}>Custom Headers</span>
|
||||
<i className="codicon codicon-lock text-[var(--vscode-descriptionForeground)] text-sm" />
|
||||
</div>
|
||||
</HeroTooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<div className="flex items-center gap-2">
|
||||
<span style={{ fontWeight: 500 }}>Custom Headers</span>
|
||||
<i className="codicon codicon-lock text-(--vscode-descriptionForeground) text-sm" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
This setting is managed by your organization's remote configuration
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
<VSCodeButton disabled={true}>Add Header</VSCodeButton>
|
||||
</div>
|
||||
) : (
|
||||
@@ -202,16 +211,19 @@ export const OpenAICompatibleProvider = ({ showModelOptions, isPopup, currentMod
|
||||
})()}
|
||||
|
||||
{remoteConfigSettings?.azureApiVersion !== undefined ? (
|
||||
<HeroTooltip content="This setting is managed by your organization's remote configuration">
|
||||
<BaseUrlField
|
||||
disabled={true}
|
||||
initialValue={apiConfiguration?.azureApiVersion}
|
||||
label="Set Azure API version"
|
||||
onChange={(value) => handleFieldChange("azureApiVersion", value)}
|
||||
placeholder={`Default: ${azureOpenAiDefaultApiVersion}`}
|
||||
showLockIcon={true}
|
||||
/>
|
||||
</HeroTooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<BaseUrlField
|
||||
disabled={true}
|
||||
initialValue={apiConfiguration?.azureApiVersion}
|
||||
label="Set Azure API version"
|
||||
onChange={(value) => handleFieldChange("azureApiVersion", value)}
|
||||
placeholder={`Default: ${azureOpenAiDefaultApiVersion}`}
|
||||
showLockIcon={true}
|
||||
/>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>This setting is managed by your organization's remote configuration</TooltipContent>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<BaseUrlField
|
||||
initialValue={apiConfiguration?.azureApiVersion}
|
||||
|
||||
@@ -137,7 +137,7 @@ export const SapAiCoreProvider = ({ showModelOptions, isPopup, currentMode }: Sa
|
||||
<span className="font-medium">AI Core Client Id</span>
|
||||
</DebouncedTextField>
|
||||
{apiConfiguration?.sapAiCoreClientId && (
|
||||
<p className="text-xs text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs text-(--vscode-descriptionForeground)">
|
||||
Client Id is set. To change it, please re-enter the value.
|
||||
</p>
|
||||
)}
|
||||
@@ -151,7 +151,7 @@ export const SapAiCoreProvider = ({ showModelOptions, isPopup, currentMode }: Sa
|
||||
<span className="font-medium">AI Core Client Secret</span>
|
||||
</DebouncedTextField>
|
||||
{apiConfiguration?.sapAiCoreClientSecret && (
|
||||
<p className="text-xs text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs text-(--vscode-descriptionForeground)">
|
||||
Client Secret is set. To change it, please re-enter the value.
|
||||
</p>
|
||||
)}
|
||||
@@ -180,7 +180,7 @@ export const SapAiCoreProvider = ({ showModelOptions, isPopup, currentMode }: Sa
|
||||
<span className="font-medium">AI Core Resource Group</span>
|
||||
</DebouncedTextField>
|
||||
|
||||
<p className="text-xs mt-1.5 text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs mt-1.5 text-(--vscode-descriptionForeground)">
|
||||
These credentials are stored locally and only used to make API requests from this extension.
|
||||
<VSCodeLink
|
||||
className="inline"
|
||||
@@ -200,7 +200,7 @@ export const SapAiCoreProvider = ({ showModelOptions, isPopup, currentMode }: Sa
|
||||
<span className="font-medium">Orchestration Mode</span>
|
||||
</div>
|
||||
|
||||
<p className="text-xs text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs text-(--vscode-descriptionForeground)">
|
||||
When enabled, provides access to all available models without requiring individual deployments.
|
||||
<br />
|
||||
<br />
|
||||
@@ -213,12 +213,12 @@ export const SapAiCoreProvider = ({ showModelOptions, isPopup, currentMode }: Sa
|
||||
<>
|
||||
<div className="flex flex-col gap-1.5">
|
||||
{isLoadingModels ? (
|
||||
<div className="text-xs text-[var(--vscode-descriptionForeground)]">Loading models...</div>
|
||||
<div className="text-xs text-(--vscode-descriptionForeground)">Loading models...</div>
|
||||
) : modelError ? (
|
||||
<div className="text-xs text-[var(--vscode-errorForeground)]">
|
||||
<div className="text-xs text-(--vscode-errorForeground)">
|
||||
{modelError}
|
||||
<button
|
||||
className="ml-2 text-[11px] px-1.5 py-0.5 bg-[var(--vscode-button-background)] text-[var(--vscode-button-foreground)] border-none rounded-sm cursor-pointer"
|
||||
className="ml-2 text-[11px] px-1.5 py-0.5 bg-(--vscode-button-background) text-(--vscode-button-foreground) border-none rounded-sm cursor-pointer"
|
||||
onClick={fetchSapAiCoreModels}>
|
||||
Retry
|
||||
</button>
|
||||
@@ -226,7 +226,7 @@ export const SapAiCoreProvider = ({ showModelOptions, isPopup, currentMode }: Sa
|
||||
) : hasRequiredCredentials ? (
|
||||
<>
|
||||
{sapAiCoreModelDeployments.length === 0 && (
|
||||
<div className="text-xs text-[var(--vscode-errorForeground)] mb-2">
|
||||
<div className="text-xs text-(--vscode-errorForeground) mb-2">
|
||||
Unable to fetch models from SAP AI Core service instance. Please check your SAP AI Core
|
||||
configuration or ensure your deployments are deployed and running in the service instance
|
||||
</div>
|
||||
@@ -247,7 +247,7 @@ export const SapAiCoreProvider = ({ showModelOptions, isPopup, currentMode }: Sa
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<div className="text-xs text-[var(--vscode-errorForeground)]">
|
||||
<div className="text-xs text-(--vscode-errorForeground)">
|
||||
Please configure your SAP AI Core credentials to see available models.
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -10,15 +10,15 @@ const AboutSection = ({ version, renderSectionHeader }: AboutSectionProps) => {
|
||||
<div>
|
||||
{renderSectionHeader("about")}
|
||||
<Section>
|
||||
<div style={{ padding: "0 16px" }}>
|
||||
<h2>Cline v{version}</h2>
|
||||
<div className="flex px-4 flex-col gap-2">
|
||||
<h2 className="text-lg font-semibold">Cline v{version}</h2>
|
||||
<p>
|
||||
An AI assistant that can use your CLI and Editor. Cline can handle complex software development tasks
|
||||
step-by-step with tools that let him create & edit files, explore large projects, use the browser, and
|
||||
execute terminal commands (after you grant permission).
|
||||
</p>
|
||||
|
||||
<h3>Community & Support</h3>
|
||||
<h3 className="text-md font-semibold">Community & Support</h3>
|
||||
<p>
|
||||
<VSCodeLink href="https://x.com/cline">X</VSCodeLink>
|
||||
{" • "}
|
||||
@@ -27,7 +27,7 @@ const AboutSection = ({ version, renderSectionHeader }: AboutSectionProps) => {
|
||||
<VSCodeLink href="https://www.reddit.com/r/cline/"> r/cline</VSCodeLink>
|
||||
</p>
|
||||
|
||||
<h3>Development</h3>
|
||||
<h3 className="text-md font-semibold">Development</h3>
|
||||
<p>
|
||||
<VSCodeLink href="https://github.com/cline/cline">GitHub</VSCodeLink>
|
||||
{" • "}
|
||||
@@ -39,7 +39,7 @@ const AboutSection = ({ version, renderSectionHeader }: AboutSectionProps) => {
|
||||
</VSCodeLink>
|
||||
</p>
|
||||
|
||||
<h3>Resources</h3>
|
||||
<h3 className="text-md font-semibold">Resources</h3>
|
||||
<p>
|
||||
<VSCodeLink href="https://docs.cline.bot/getting-started/for-new-coders">Documentation</VSCodeLink>
|
||||
{" • "}
|
||||
|
||||
@@ -25,7 +25,7 @@ const ApiConfigurationSection = ({ renderSectionHeader }: ApiConfigurationSectio
|
||||
{/* Tabs container */}
|
||||
{planActSeparateModelsSetting ? (
|
||||
<div className="rounded-md mb-5">
|
||||
<div className="flex gap-[1px] mb-[10px] -mt-2 border-0 border-b border-solid border-[var(--vscode-panel-border)]">
|
||||
<div className="flex gap-px mb-[10px] -mt-2 border-0 border-b border-solid border-(--vscode-panel-border)">
|
||||
<TabButton
|
||||
disabled={currentTab === "plan"}
|
||||
isActive={currentTab === "plan"}
|
||||
@@ -79,7 +79,7 @@ const ApiConfigurationSection = ({ renderSectionHeader }: ApiConfigurationSectio
|
||||
}}>
|
||||
Use different models for Plan and Act modes
|
||||
</VSCodeCheckbox>
|
||||
<p className="text-xs mt-[5px] text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs mt-[5px] text-(--vscode-descriptionForeground)">
|
||||
Switching between Plan and Act mode will persist the API and model used in the previous mode. This may be
|
||||
helpful e.g. when using a strong reasoning model to architect a plan for a cheaper coding model to act on.
|
||||
</p>
|
||||
|
||||
@@ -23,7 +23,7 @@ const DebugSection = ({ onResetState, renderSectionHeader }: DebugSectionProps)
|
||||
style={{ backgroundColor: "var(--vscode-errorForeground)", color: "black" }}>
|
||||
Reset Global State
|
||||
</VSCodeButton>
|
||||
<p className="text-xs mt-[5px] text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs mt-[5px] text-(--vscode-descriptionForeground)">
|
||||
This will reset all global state and secret storage in the extension.
|
||||
</p>
|
||||
</Section>
|
||||
|
||||
@@ -3,8 +3,8 @@ import { McpDisplayMode } from "@shared/McpDisplayMode"
|
||||
import { OpenaiReasoningEffort } from "@shared/storage/types"
|
||||
import { VSCodeCheckbox, VSCodeDropdown, VSCodeOption, VSCodeTextField } from "@vscode/webview-ui-toolkit/react"
|
||||
import { memo } from "react"
|
||||
import HeroTooltip from "@/components/common/HeroTooltip"
|
||||
import McpDisplayModeDropdown from "@/components/mcp/chat-display/McpDisplayModeDropdown"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import Section from "../Section"
|
||||
import { updateSetting } from "../utils/settingsHandlers"
|
||||
@@ -48,27 +48,32 @@ const FeatureSettingsSection = ({ renderSectionHeader }: FeatureSettingsSectionP
|
||||
}}>
|
||||
Enable Checkpoints
|
||||
</VSCodeCheckbox>
|
||||
<p className="text-xs text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs text-(--vscode-descriptionForeground)">
|
||||
Enables extension to save checkpoints of workspace throughout the task. Uses git under the hood which
|
||||
may not work well with large workspaces.
|
||||
</p>
|
||||
</div>
|
||||
<div style={{ marginTop: 10 }}>
|
||||
{remoteConfigSettings?.mcpMarketplaceEnabled !== undefined ? (
|
||||
<HeroTooltip content="This setting is managed by your organization's remote configuration">
|
||||
<div className="flex items-center gap-2">
|
||||
<VSCodeCheckbox
|
||||
checked={mcpMarketplaceEnabled}
|
||||
disabled={true}
|
||||
onChange={(e: any) => {
|
||||
const checked = e.target.checked === true
|
||||
updateSetting("mcpMarketplaceEnabled", checked)
|
||||
}}>
|
||||
Enable MCP Marketplace
|
||||
</VSCodeCheckbox>
|
||||
<i className="codicon codicon-lock text-[var(--vscode-descriptionForeground)] text-sm" />
|
||||
</div>
|
||||
</HeroTooltip>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
<div className="flex items-center gap-2">
|
||||
<VSCodeCheckbox
|
||||
checked={mcpMarketplaceEnabled}
|
||||
disabled={true}
|
||||
onChange={(e: any) => {
|
||||
const checked = e.target.checked === true
|
||||
updateSetting("mcpMarketplaceEnabled", checked)
|
||||
}}>
|
||||
Enable MCP Marketplace
|
||||
</VSCodeCheckbox>
|
||||
<i className="codicon codicon-lock text-(--vscode-descriptionForeground) text-sm" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
This setting is managed by your organization's remote configuration
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<VSCodeCheckbox
|
||||
checked={mcpMarketplaceEnabled}
|
||||
@@ -80,13 +85,13 @@ const FeatureSettingsSection = ({ renderSectionHeader }: FeatureSettingsSectionP
|
||||
Enable MCP Marketplace
|
||||
</VSCodeCheckbox>
|
||||
)}
|
||||
<p className="text-xs text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs text-(--vscode-descriptionForeground)">
|
||||
Enables the MCP Marketplace tab for discovering and installing MCP servers.
|
||||
</p>
|
||||
</div>
|
||||
<div style={{ marginTop: 10 }}>
|
||||
<label
|
||||
className="block text-sm font-medium text-[var(--vscode-foreground)] mb-1"
|
||||
className="block text-sm font-medium text-(--vscode-foreground) mb-1"
|
||||
htmlFor="mcp-display-mode-dropdown">
|
||||
MCP Display Mode
|
||||
</label>
|
||||
@@ -96,7 +101,7 @@ const FeatureSettingsSection = ({ renderSectionHeader }: FeatureSettingsSectionP
|
||||
onChange={(newMode: McpDisplayMode) => updateSetting("mcpDisplayMode", newMode)}
|
||||
value={mcpDisplayMode}
|
||||
/>
|
||||
<p className="text-xs mt-[5px] text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs mt-[5px] text-(--vscode-descriptionForeground)">
|
||||
Controls how MCP responses are displayed: plain text, rich formatting with links/images, or markdown
|
||||
rendering.
|
||||
</p>
|
||||
@@ -110,13 +115,13 @@ const FeatureSettingsSection = ({ renderSectionHeader }: FeatureSettingsSectionP
|
||||
}}>
|
||||
Collapse MCP Responses
|
||||
</VSCodeCheckbox>
|
||||
<p className="text-xs text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs text-(--vscode-descriptionForeground)">
|
||||
Sets the default display mode for MCP response panels
|
||||
</p>
|
||||
</div>
|
||||
<div style={{ marginTop: 10 }}>
|
||||
<label
|
||||
className="block text-sm font-medium text-[var(--vscode-foreground)] mb-1"
|
||||
className="block text-sm font-medium text-(--vscode-foreground) mb-1"
|
||||
htmlFor="openai-reasoning-effort-dropdown">
|
||||
OpenAI Reasoning Effort
|
||||
</label>
|
||||
@@ -133,7 +138,7 @@ const FeatureSettingsSection = ({ renderSectionHeader }: FeatureSettingsSectionP
|
||||
<VSCodeOption value="medium">Medium</VSCodeOption>
|
||||
<VSCodeOption value="high">High</VSCodeOption>
|
||||
</VSCodeDropdown>
|
||||
<p className="text-xs mt-[5px] text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs mt-[5px] text-(--vscode-descriptionForeground)">
|
||||
Reasoning effort for the OpenAI family of models(applies to all OpenAI model providers)
|
||||
</p>
|
||||
</div>
|
||||
@@ -146,7 +151,7 @@ const FeatureSettingsSection = ({ renderSectionHeader }: FeatureSettingsSectionP
|
||||
}}>
|
||||
Enable strict plan mode
|
||||
</VSCodeCheckbox>
|
||||
<p className="text-xs text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs text-(--vscode-descriptionForeground)">
|
||||
Enforces strict tool use while in plan mode, preventing file edits.
|
||||
</p>
|
||||
</div>
|
||||
@@ -160,7 +165,7 @@ const FeatureSettingsSection = ({ renderSectionHeader }: FeatureSettingsSectionP
|
||||
}}>
|
||||
Enable Focus Chain
|
||||
</VSCodeCheckbox>
|
||||
<p className="text-xs text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs text-(--vscode-descriptionForeground)">
|
||||
Enables enhanced task progress tracking and automatic focus chain list management throughout
|
||||
tasks.
|
||||
</p>
|
||||
@@ -169,7 +174,7 @@ const FeatureSettingsSection = ({ renderSectionHeader }: FeatureSettingsSectionP
|
||||
{focusChainSettings?.enabled && (
|
||||
<div style={{ marginTop: 10, marginLeft: 20 }}>
|
||||
<label
|
||||
className="block text-sm font-medium text-[var(--vscode-foreground)] mb-1"
|
||||
className="block text-sm font-medium text-(--vscode-foreground) mb-1"
|
||||
htmlFor="focus-chain-remind-interval">
|
||||
Focus Chain Reminder Interval
|
||||
</label>
|
||||
@@ -187,7 +192,7 @@ const FeatureSettingsSection = ({ renderSectionHeader }: FeatureSettingsSectionP
|
||||
}}
|
||||
value={String(focusChainSettings?.remindClineInterval || 6)}
|
||||
/>
|
||||
<p className="text-xs mt-[5px] text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs mt-[5px] text-(--vscode-descriptionForeground)">
|
||||
Interval (in messages) to remind Cline about its focus chain checklist (1-100). Lower values
|
||||
provide more frequent reminders.
|
||||
</p>
|
||||
@@ -258,10 +263,10 @@ const FeatureSettingsSection = ({ renderSectionHeader }: FeatureSettingsSectionP
|
||||
}}>
|
||||
Enable Auto Compact
|
||||
</VSCodeCheckbox>
|
||||
<p className="text-xs text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs text-(--vscode-descriptionForeground)">
|
||||
Enables advanced context management system which uses LLM based condensing for next-gen models.{" "}
|
||||
<a
|
||||
className="text-[var(--vscode-textLink-foreground)] hover:text-[var(--vscode-textLink-activeForeground)]"
|
||||
className="text-(--vscode-textLink-foreground) hover:text-(--vscode-textLink-activeForeground)"
|
||||
href="https://docs.cline.bot/features/auto-compact"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank">
|
||||
@@ -296,7 +301,7 @@ const FeatureSettingsSection = ({ renderSectionHeader }: FeatureSettingsSectionP
|
||||
Enable Hooks
|
||||
</VSCodeCheckbox>
|
||||
<p className="text-xs">
|
||||
<span className="text-[var(--vscode-errorForeground)]">Experimental: </span>{" "}
|
||||
<span className="text-(--vscode-errorForeground)">Experimental: </span>{" "}
|
||||
<span className="text-description">
|
||||
Allows execution of hooks from .clinerules/hooks/ directory.
|
||||
</span>
|
||||
@@ -304,33 +309,30 @@ const FeatureSettingsSection = ({ renderSectionHeader }: FeatureSettingsSectionP
|
||||
</div>
|
||||
)}
|
||||
<div style={{ marginTop: 10 }}>
|
||||
{remoteConfigSettings?.yoloModeToggled !== undefined ? (
|
||||
<HeroTooltip content="This setting is managed by your organization's remote configuration">
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<div className="flex items-center gap-2">
|
||||
<VSCodeCheckbox
|
||||
checked={yoloModeToggled}
|
||||
disabled={true}
|
||||
disabled={remoteConfigSettings?.yoloModeToggled !== undefined}
|
||||
onChange={(e: any) => {
|
||||
const checked = e.target.checked === true
|
||||
updateSetting("yoloModeToggled", checked)
|
||||
}}>
|
||||
Enable YOLO Mode
|
||||
</VSCodeCheckbox>
|
||||
<i className="codicon codicon-lock text-[var(--vscode-descriptionForeground)] text-sm" />
|
||||
<i className="codicon codicon-lock text-(--vscode-descriptionForeground) text-sm" />
|
||||
</div>
|
||||
</HeroTooltip>
|
||||
) : (
|
||||
<VSCodeCheckbox
|
||||
checked={yoloModeToggled}
|
||||
disabled={false}
|
||||
onChange={(e: any) => {
|
||||
const checked = e.target.checked === true
|
||||
updateSetting("yoloModeToggled", checked)
|
||||
}}>
|
||||
Enable YOLO Mode
|
||||
</VSCodeCheckbox>
|
||||
)}
|
||||
<p className="text-xs text-[var(--vscode-errorForeground)]">
|
||||
</TooltipTrigger>
|
||||
<TooltipContent
|
||||
className="max-w-xs"
|
||||
hidden={remoteConfigSettings?.yoloModeToggled === undefined}
|
||||
side="top">
|
||||
This setting is managed by your organization's remote configuration
|
||||
</TooltipContent>
|
||||
</Tooltip>
|
||||
|
||||
<p className="text-xs text-(--vscode-errorForeground)">
|
||||
EXPERIMENTAL & DANGEROUS: This mode disables safety checks and user confirmations. Cline will
|
||||
automatically approve all actions without asking. Use with extreme caution.
|
||||
</p>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { VSCodeCheckbox, VSCodeLink } from "@vscode/webview-ui-toolkit/react"
|
||||
import HeroTooltip from "@/components/common/HeroTooltip"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import PreferredLanguageSetting from "../PreferredLanguageSetting"
|
||||
import Section from "../Section"
|
||||
@@ -21,20 +21,23 @@ const GeneralSettingsSection = ({ renderSectionHeader }: GeneralSettingsSectionP
|
||||
|
||||
<div className="mb-[5px]">
|
||||
{isDisabledByRemoteConfig ? (
|
||||
<HeroTooltip content="This setting is managed by your organization's remote configuration">
|
||||
<div className="flex items-center gap-2 mb-[5px]">
|
||||
<VSCodeCheckbox
|
||||
checked={telemetrySetting !== "disabled"}
|
||||
disabled={true}
|
||||
onChange={(e: any) => {
|
||||
const checked = e.target.checked === true
|
||||
updateSetting("telemetrySetting", checked ? "enabled" : "disabled")
|
||||
}}>
|
||||
Allow error and usage reporting
|
||||
</VSCodeCheckbox>
|
||||
<i className="codicon codicon-lock text-[var(--vscode-descriptionForeground)] text-sm" />
|
||||
</div>
|
||||
</HeroTooltip>
|
||||
<Tooltip>
|
||||
<TooltipContent>This setting is managed by your organization's remote configuration</TooltipContent>
|
||||
<TooltipTrigger asChild>
|
||||
<div className="flex items-center gap-2 mb-[5px]">
|
||||
<VSCodeCheckbox
|
||||
checked={telemetrySetting !== "disabled"}
|
||||
disabled={true}
|
||||
onChange={(e: any) => {
|
||||
const checked = e.target.checked === true
|
||||
updateSetting("telemetrySetting", checked ? "enabled" : "disabled")
|
||||
}}>
|
||||
Allow error and usage reporting
|
||||
</VSCodeCheckbox>
|
||||
<i className="codicon codicon-lock text--vscode-descriptionForeground) text-sm" />
|
||||
</div>
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
) : (
|
||||
<VSCodeCheckbox
|
||||
checked={telemetrySetting !== "disabled"}
|
||||
@@ -47,7 +50,7 @@ const GeneralSettingsSection = ({ renderSectionHeader }: GeneralSettingsSectionP
|
||||
Allow error and usage reporting
|
||||
</VSCodeCheckbox>
|
||||
)}
|
||||
<p className="text-xs mt-[5px] text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs mt-[5px] text--vscode-descriptionForeground)">
|
||||
Help improve Cline by sending usage data and error reports. No code, prompts, or personal information are
|
||||
ever sent. See our{" "}
|
||||
<VSCodeLink
|
||||
|
||||
@@ -91,7 +91,7 @@ export const TerminalSettingsSection: React.FC<TerminalSettingsSectionProps> = (
|
||||
</VSCodeOption>
|
||||
))}
|
||||
</VSCodeDropdown>
|
||||
<p className="text-xs text-[var(--vscode-descriptionForeground)] mt-1">
|
||||
<p className="text-xs text-(--vscode-descriptionForeground) mt-1">
|
||||
Select the default terminal Cline will use. 'Default' uses your VSCode global setting.
|
||||
</p>
|
||||
</div>
|
||||
@@ -108,9 +108,9 @@ export const TerminalSettingsSection: React.FC<TerminalSettingsSectionProps> = (
|
||||
value={inputValue}
|
||||
/>
|
||||
</div>
|
||||
{inputError && <div className="text-[var(--vscode-errorForeground)] text-xs mt-1">{inputError}</div>}
|
||||
{inputError && <div className="text-(--vscode-errorForeground) text-xs mt-1">{inputError}</div>}
|
||||
</div>
|
||||
<p className="text-xs text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs text-(--vscode-descriptionForeground)">
|
||||
Set how long Cline waits for shell integration to activate before executing commands. Increase this
|
||||
value if you experience terminal connection timeouts.
|
||||
</p>
|
||||
@@ -124,17 +124,17 @@ export const TerminalSettingsSection: React.FC<TerminalSettingsSectionProps> = (
|
||||
Enable aggressive terminal reuse
|
||||
</VSCodeCheckbox>
|
||||
</div>
|
||||
<p className="text-xs text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-xs text-(--vscode-descriptionForeground)">
|
||||
When enabled, Cline will reuse existing terminal windows that aren't in the current working directory.
|
||||
Disable this if you experience issues with task lockout after a terminal command.
|
||||
</p>
|
||||
</div>
|
||||
<TerminalOutputLineLimitSlider />
|
||||
<div className="mt-5 p-3 bg-[var(--vscode-textBlockQuote-background)] rounded border border-[var(--vscode-textBlockQuote-border)]">
|
||||
<div className="mt-5 p-3 bg-(--vscode-textBlockQuote-background) rounded border border-(--vscode-textBlockQuote-border)">
|
||||
<p className="text-[13px] m-0">
|
||||
<strong>Having terminal issues?</strong> Check our{" "}
|
||||
<a
|
||||
className="text-[var(--vscode-textLink-foreground)] underline hover:no-underline"
|
||||
className="text-(--vscode-textLink-foreground) underline hover:no-underline"
|
||||
href="https://docs.cline.bot/troubleshooting/terminal-quick-fixes"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank">
|
||||
@@ -142,7 +142,7 @@ export const TerminalSettingsSection: React.FC<TerminalSettingsSectionProps> = (
|
||||
</a>{" "}
|
||||
or the{" "}
|
||||
<a
|
||||
className="text-[var(--vscode-textLink-foreground)] underline hover:no-underline"
|
||||
className="text-(--vscode-textLink-foreground) underline hover:no-underline"
|
||||
href="https://docs.cline.bot/troubleshooting/terminal-integration-guide"
|
||||
rel="noopener noreferrer"
|
||||
target="_blank">
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import { Slot } from "@radix-ui/react-slot"
|
||||
import { cva, type VariantProps } from "class-variance-authority"
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 cursor-pointer [&_svg]:size-2",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default: "bg-button-background text-primary-foreground shadow hover:bg-button-background-hover",
|
||||
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
||||
outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
||||
secondary:
|
||||
"bg-button-secondary-background text-button-secondary-foreground shadow-sm hover:bg-button-secondary-background-hover",
|
||||
ghost: "hover:bg-accent/10 m-0 p-0",
|
||||
link: "text-primary underline-offset-4 hover:underline",
|
||||
icon: "bg-transparent hover:opacity-80 p-0 h-auto m-0 border-0 cursor-pointer hover:bg-transparent hover:shadow-none focus:ring-0 focus:ring-offset-0",
|
||||
},
|
||||
size: {
|
||||
default: "h-5 px-4 py-2",
|
||||
sm: "h-3 rounded-md px-3 text-sm",
|
||||
xs: "h-1 rounded-xs px-1 text-xs",
|
||||
lg: "h-8 rounded-md px-8",
|
||||
icon: "px-0.5 m-0 [&_svg]:size-2",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
size: "default",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, VariantProps<typeof buttonVariants> {
|
||||
asChild?: boolean
|
||||
}
|
||||
|
||||
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||
({ className, variant, size, asChild = false, ...props }, ref) => {
|
||||
const Comp = asChild ? Slot : "button"
|
||||
return <Comp className={cn(buttonVariants({ variant, size, className }))} ref={ref} {...props} />
|
||||
},
|
||||
)
|
||||
Button.displayName = "Button"
|
||||
|
||||
export { Button, buttonVariants }
|
||||
@@ -0,0 +1,37 @@
|
||||
import * as HoverCardPrimitive from "@radix-ui/react-hover-card"
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const HoverCard = HoverCardPrimitive.Root
|
||||
|
||||
const HoverCardTrigger = HoverCardPrimitive.Trigger
|
||||
|
||||
function HoverCardContent({
|
||||
className,
|
||||
align = "center",
|
||||
sideOffset = 4,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof HoverCardPrimitive.Content>) {
|
||||
return (
|
||||
<HoverCardPrimitive.Portal data-slot="hover-card-portal">
|
||||
<HoverCardPrimitive.Content
|
||||
align={align}
|
||||
className={cn(
|
||||
"bg-code text-code-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-64 origin-(--radix-hover-card-content-transform-origin) rounded-xs p-2 shadow-md outline-hidden border border-muted-foreground/30",
|
||||
className,
|
||||
)}
|
||||
data-slot="hover-card-content"
|
||||
sideOffset={sideOffset}
|
||||
{...props}>
|
||||
{children}
|
||||
<HoverCardPrimitive.Arrow className="bg-code fill-background z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] border-b border-r border-muted-foreground/30" />
|
||||
</HoverCardPrimitive.Content>
|
||||
</HoverCardPrimitive.Portal>
|
||||
)
|
||||
}
|
||||
|
||||
HoverCardContent.displayName = HoverCardPrimitive.Content.displayName
|
||||
|
||||
export { HoverCard, HoverCardTrigger, HoverCardContent }
|
||||
@@ -0,0 +1,39 @@
|
||||
import * as PopoverPrimitive from "@radix-ui/react-popover"
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const Popover = PopoverPrimitive.Root
|
||||
|
||||
const PopoverTrigger = PopoverPrimitive.Trigger
|
||||
|
||||
const PopoverAnchor = PopoverPrimitive.Anchor
|
||||
|
||||
function PopoverContent({
|
||||
className,
|
||||
align = "center",
|
||||
sideOffset = 4,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof PopoverPrimitive.Content>) {
|
||||
return (
|
||||
<PopoverPrimitive.Portal>
|
||||
<PopoverPrimitive.Content
|
||||
align={align}
|
||||
className={cn(
|
||||
"bg-menu text-base text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-xs border p-2 shadow-md outline-hidden border-menu-foreground/10",
|
||||
className,
|
||||
)}
|
||||
data-slot="popover-content"
|
||||
sideOffset={sideOffset}
|
||||
{...props}>
|
||||
{children}
|
||||
<PopoverPrimitive.Arrow className="bg-menu fill-background z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-xs border-b border-r border-menu-foreground/10" />
|
||||
</PopoverPrimitive.Content>
|
||||
</PopoverPrimitive.Portal>
|
||||
)
|
||||
}
|
||||
|
||||
PopoverContent.displayName = PopoverPrimitive.Content.displayName
|
||||
|
||||
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }
|
||||
@@ -0,0 +1,22 @@
|
||||
import * as ProgressPrimitive from "@radix-ui/react-progress"
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
const Progress = React.forwardRef<
|
||||
React.ElementRef<typeof ProgressPrimitive.Root>,
|
||||
React.ComponentPropsWithoutRef<typeof ProgressPrimitive.Root>
|
||||
>(({ className, value, ...props }, ref) => (
|
||||
<ProgressPrimitive.Root
|
||||
className={cn("relative h-2 w-full overflow-hidden rounded-full bg-code-foreground/20", className)}
|
||||
ref={ref}
|
||||
{...props}>
|
||||
<ProgressPrimitive.Indicator
|
||||
className="h-full w-full flex-1 bg-code-foreground transition-all"
|
||||
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
|
||||
/>
|
||||
</ProgressPrimitive.Root>
|
||||
))
|
||||
Progress.displayName = ProgressPrimitive.Root.displayName
|
||||
|
||||
export { Progress }
|
||||
@@ -0,0 +1,47 @@
|
||||
"use client"
|
||||
|
||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip"
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function TooltipProvider({ delayDuration = 0, ...props }: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
|
||||
return <TooltipPrimitive.Provider data-slot="tooltip-provider" delayDuration={delayDuration} {...props} />
|
||||
}
|
||||
|
||||
function Tooltip({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Root>) {
|
||||
return (
|
||||
<TooltipProvider>
|
||||
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
|
||||
</TooltipProvider>
|
||||
)
|
||||
}
|
||||
|
||||
function TooltipTrigger({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
|
||||
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
|
||||
}
|
||||
|
||||
function TooltipContent({
|
||||
className,
|
||||
sideOffset = 0,
|
||||
children,
|
||||
...props
|
||||
}: React.ComponentProps<typeof TooltipPrimitive.Content>) {
|
||||
return (
|
||||
<TooltipPrimitive.Portal>
|
||||
<TooltipPrimitive.Content
|
||||
className={cn(
|
||||
"bg-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 origin-(--radix-tooltip-content-transform-origin) rounded-xs px-1 py-1.5 text-xs text-balance border border-muted-foreground/30 shadow-2xs mx-1 wrap-break-word max-w-md p-2 overflow-visible",
|
||||
className,
|
||||
)}
|
||||
data-slot="tooltip-content"
|
||||
sideOffset={sideOffset}
|
||||
{...props}>
|
||||
<span className="text-xs leading-tight wrap-break-word">{children}</span>
|
||||
<TooltipPrimitive.Arrow className="bg-background fill-background z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-xs border-b border-r border-muted-foreground/30" />
|
||||
</TooltipPrimitive.Content>
|
||||
</TooltipPrimitive.Portal>
|
||||
)
|
||||
}
|
||||
|
||||
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
|
||||
@@ -1,6 +1,7 @@
|
||||
import { EmptyRequest } from "@shared/proto/cline/common"
|
||||
import { InfoIcon } from "lucide-react"
|
||||
import ClineLogoVariable from "@/assets/ClineLogoVariable"
|
||||
import HeroTooltip from "@/components/common/HeroTooltip"
|
||||
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { UiServiceClient } from "@/services/grpc-client"
|
||||
|
||||
@@ -21,24 +22,25 @@ const HomeHeader = ({ shouldShowQuickWins = false }: HomeHeaderProps) => {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center mb-5">
|
||||
<div className="my-5">
|
||||
<ClineLogoVariable className="size-16" environment={environment} />
|
||||
<div className="my-7">
|
||||
<ClineLogoVariable className="size-20" environment={environment} />
|
||||
</div>
|
||||
<div className="text-center flex items-center justify-center">
|
||||
<h2 className="m-0 text-lg">{"What can I do for you?"}</h2>
|
||||
<HeroTooltip
|
||||
className="max-w-[300px]"
|
||||
content={
|
||||
"I can develop software step-by-step by editing files, exploring projects, running commands, and using browsers. I can even extend my capabilities with MCP tools to assist beyond basic code completion."
|
||||
}
|
||||
placement="bottom">
|
||||
<span className="codicon codicon-info ml-2 cursor-pointer text-link text-sm" />
|
||||
</HeroTooltip>
|
||||
<h1 className="m-0 font-bold">What can I do for you?</h1>
|
||||
<Tooltip>
|
||||
<TooltipContent side="bottom">
|
||||
I can develop software step-by-step by editing files, exploring projects, running commands, and using
|
||||
browsers. I can even extend my capabilities with MCP tools to assist beyond basic code completion.
|
||||
</TooltipContent>
|
||||
<TooltipTrigger asChild>
|
||||
<InfoIcon className="ml-2 cursor-pointer text-link text-sm size-2" />
|
||||
</TooltipTrigger>
|
||||
</Tooltip>
|
||||
</div>
|
||||
{shouldShowQuickWins && (
|
||||
<div className="mt-4">
|
||||
<button
|
||||
className="flex items-center gap-2 px-4 py-2 rounded-full border border-border-panel bg-white/[0.02] hover:bg-list-background-hover transition-colors duration-150 ease-in-out text-code-foreground text-sm font-medium cursor-pointer"
|
||||
className="flex items-center gap-2 px-4 py-2 rounded-full border border-border-panel bg-white/2 hover:bg-list-background-hover transition-colors duration-150 ease-in-out text-code-foreground text-sm font-medium cursor-pointer"
|
||||
onClick={handleTakeATour}
|
||||
type="button">
|
||||
Take a Tour
|
||||
|
||||
@@ -8,7 +8,7 @@ interface QuickWinCardProps {
|
||||
|
||||
const renderIcon = (iconName?: string) => {
|
||||
if (!iconName) {
|
||||
return <span className="codicon codicon-rocket !text-[28px] !leading-[1]"></span>
|
||||
return <span className="codicon codicon-rocket text-[28px]! leading-none!"></span>
|
||||
}
|
||||
|
||||
let iconClass = "codicon-rocket"
|
||||
@@ -25,25 +25,23 @@ const renderIcon = (iconName?: string) => {
|
||||
default:
|
||||
break
|
||||
}
|
||||
return <span className={`codicon ${iconClass} !text-[28px] !leading-[1]`}></span>
|
||||
return <span className={`codicon ${iconClass} text-[28px]! leading-none!`}></span>
|
||||
}
|
||||
|
||||
const QuickWinCard: React.FC<QuickWinCardProps> = ({ task, onExecute }) => {
|
||||
return (
|
||||
<div
|
||||
className="flex items-center mb-2 py-0 px-5 space-x-3 rounded-full cursor-pointer group transition-colors duration-150 ease-in-out bg-white/[0.02] border border-[var(--vscode-panel-border)] hover:bg-[var(--vscode-list-hoverBackground)]"
|
||||
className="flex items-center mb-2 py-0 px-5 space-x-3 rounded-full cursor-pointer group transition-colors duration-150 ease-in-out bg-white/2 border border-(--vscode-panel-border) hover:bg-(--vscode-list-hoverBackground)"
|
||||
onClick={() => onExecute()}>
|
||||
<div className="flex-shrink-0 flex items-center justify-center w-6 h-6 text-[var(--vscode-icon-foreground)]">
|
||||
<div className="shrink-0 flex items-center justify-center w-6 h-6 text-(--vscode-icon-foreground)">
|
||||
{renderIcon(task.icon)}
|
||||
</div>
|
||||
|
||||
<div className="flex-grow min-w-0">
|
||||
<h3 className="text-sm font-medium truncate text-[var(--vscode-editor-foreground)] leading-tight mb-0 mt-0 pt-3">
|
||||
<div className="grow min-w-0">
|
||||
<h3 className="text-sm font-medium truncate text-(--vscode-editor-foreground) leading-tight mb-0 mt-0 pt-3">
|
||||
{task.title}
|
||||
</h3>
|
||||
<p className="text-xs truncate text-[var(--vscode-descriptionForeground)] leading-tight mt-[1px]">
|
||||
{task.description}
|
||||
</p>
|
||||
<p className="text-xs truncate text-(--vscode-descriptionForeground) leading-tight mt-px">{task.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -34,8 +34,8 @@ const WelcomeView = memo(() => {
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 p-0 flex flex-col">
|
||||
<div className="h-full px-5 overflow-auto">
|
||||
<h2>Hi, I'm Cline</h2>
|
||||
<div className="h-full px-5 overflow-auto flex flex-col gap-2.5">
|
||||
<h2 className="text-lg font-semibold">Hi, I'm Cline</h2>
|
||||
<div className="flex justify-center my-5">
|
||||
<ClineLogoWhite className="size-16" />
|
||||
</div>
|
||||
@@ -49,7 +49,7 @@ const WelcomeView = memo(() => {
|
||||
create new tools and extend my own capabilities.
|
||||
</p>
|
||||
|
||||
<p className="text-[var(--vscode-descriptionForeground)]">
|
||||
<p className="text-(--vscode-descriptionForeground)">
|
||||
Sign up for an account to get started for free, or use an API key that provides access to models like Claude
|
||||
Sonnet.
|
||||
</p>
|
||||
|
||||
+48
-209
@@ -1,215 +1,54 @@
|
||||
@layer theme, base, components, utilities;
|
||||
|
||||
/*
|
||||
Import order matters for Tailwind CSS v4 compatibility
|
||||
|
||||
External @import statements MUST come before Tailwind imports because:
|
||||
1. CSS spec requires ALL @import statements to precede other CSS rules (except @charset/@layer)
|
||||
2. Tailwind CSS v4 expands its imports into thousands of lines of generated utility CSS
|
||||
3. If external imports come after Tailwind imports, they end up after the generated CSS
|
||||
4. This causes PostCSS to throw: "@import must precede all other statements"
|
||||
|
||||
The correct order is:
|
||||
- @layer declarations (empty)
|
||||
- External @import statements (fonts, icons, etc.)
|
||||
- Tailwind @import statements (theme, utilities)
|
||||
- @config directives
|
||||
- Regular CSS rules
|
||||
*/
|
||||
|
||||
/* External imports must come first, before Tailwind imports */
|
||||
/* Import external CSS files */
|
||||
@import url("../../node_modules/@vscode/codicons/dist/codicon.css");
|
||||
@import url("../node_modules/@fontsource/azeret-mono/index.css");
|
||||
|
||||
/* Tailwind imports come after external imports */
|
||||
@import "tailwindcss/theme.css" layer(theme);
|
||||
/* Disable Tailwind's CSS reset to preserve existing styles */
|
||||
/* @import "tailwindcss/preflight.css" layer(base); */
|
||||
@import "tailwindcss/utilities.css" layer(utilities);
|
||||
@import "tailwindcss";
|
||||
@import "./theme.css";
|
||||
@plugin "tailwindcss-animate";
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
/* Configuration directives come after all imports */
|
||||
@config "../tailwind.config.mjs";
|
||||
|
||||
textarea:focus {
|
||||
outline: 1.5px solid var(--vscode-focusBorder, #007fd4);
|
||||
}
|
||||
|
||||
vscode-button::part(control):focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/*
|
||||
Use vscode native scrollbar styles
|
||||
https://github.com/gitkraken/vscode-gitlens/blob/b1d71d4844523e8b2ef16f9e007068e91f46fd88/src/webviews/apps/home/home.scss
|
||||
*/
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
line-height: 1.25;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
body.scrollable,
|
||||
.scrollable,
|
||||
body.code-block-scrollable,
|
||||
.code-block-scrollable {
|
||||
border-color: transparent;
|
||||
transition: border-color 0.7s linear;
|
||||
}
|
||||
|
||||
body:hover.scrollable,
|
||||
body:hover .scrollable,
|
||||
body:focus-within.scrollable,
|
||||
body:focus-within .scrollable,
|
||||
body:hover.code-block-scrollable,
|
||||
body:hover .code-block-scrollable,
|
||||
body:focus-within.code-block-scrollable,
|
||||
body:focus-within .code-block-scrollable {
|
||||
border-color: var(--vscode-scrollbarSlider-background);
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.scrollable::-webkit-scrollbar-corner {
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.scrollable::-webkit-scrollbar-thumb {
|
||||
background-color: transparent;
|
||||
border-color: inherit;
|
||||
border-right-style: inset;
|
||||
border-right-width: calc(100vw + 100vh);
|
||||
border-radius: unset !important;
|
||||
}
|
||||
|
||||
.scrollable::-webkit-scrollbar-thumb:hover {
|
||||
border-color: var(--vscode-scrollbarSlider-hoverBackground);
|
||||
}
|
||||
|
||||
.scrollable::-webkit-scrollbar-thumb:active {
|
||||
border-color: var(--vscode-scrollbarSlider-activeBackground);
|
||||
}
|
||||
|
||||
/*
|
||||
Fix VSCode ignoring webkit scrollbar modifiers
|
||||
https://github.com/microsoft/vscode/issues/213045
|
||||
*/
|
||||
@supports selector(::-webkit-scrollbar) {
|
||||
html {
|
||||
scrollbar-color: unset;
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border outline-ring/50 text-base;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
p {
|
||||
@apply my-0 text-base leading-5 block line-clamp-3;
|
||||
margin-block-start: 1em;
|
||||
margin-block-end: 1em;
|
||||
margin-inline-start: 0px;
|
||||
margin-inline-end: 0px;
|
||||
unicode-bidi: isolate;
|
||||
}
|
||||
h1 {
|
||||
font-size: var(--text-lg);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
}
|
||||
h2 {
|
||||
font-size: var(--text-md);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
}
|
||||
h3 {
|
||||
font-size: var(--text-sm);
|
||||
font-weight: var(--font-weight-semibold);
|
||||
}
|
||||
h4 {
|
||||
font-size: var(--text-base);
|
||||
font-weight: var(--font-weight-bold);
|
||||
}
|
||||
a {
|
||||
@apply text-link hover:text-link-hover;
|
||||
}
|
||||
ol {
|
||||
@apply list-decimal pl-6;
|
||||
}
|
||||
ul {
|
||||
@apply list-disc pl-6;
|
||||
}
|
||||
[role="radio"],
|
||||
[role="checkbox"] {
|
||||
margin: calc(var(--design-unit) * 1px) 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
The above scrollbar styling uses some transparent background color magic to accomplish its animation. However this doesn't play nicely with SyntaxHighlighter, so we need to set a background color for the code blocks' horizontal scrollbar. This actually has the unintended consequence of always showing the scrollbar which I prefer since it makes it more obvious that there is more content to scroll to.
|
||||
*/
|
||||
|
||||
.code-block-scrollable::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.code-block-scrollable::-webkit-scrollbar-thumb {
|
||||
background-color: var(--vscode-scrollbarSlider-background);
|
||||
border-radius: 5px;
|
||||
border: 2px solid transparent;
|
||||
background-clip: content-box;
|
||||
}
|
||||
|
||||
.code-block-scrollable::-webkit-scrollbar-thumb:hover {
|
||||
background-color: var(--vscode-scrollbarSlider-hoverBackground);
|
||||
}
|
||||
|
||||
.code-block-scrollable::-webkit-scrollbar-thumb:active {
|
||||
background-color: var(--vscode-scrollbarSlider-activeBackground);
|
||||
}
|
||||
|
||||
.code-block-scrollable::-webkit-scrollbar-corner {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/*
|
||||
Dropdown label
|
||||
https://github.com/microsoft/vscode-webview-ui-toolkit/tree/main/src/dropdown#with-label
|
||||
*/
|
||||
.dropdown-container {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
.dropdown-container label {
|
||||
display: block;
|
||||
color: var(--vscode-foreground);
|
||||
cursor: pointer;
|
||||
font-size: var(--vscode-font-size);
|
||||
line-height: normal;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
/* Fix scrollbar in dropdown */
|
||||
|
||||
vscode-dropdown::part(listbox) {
|
||||
border-color: var(--vscode-scrollbarSlider-background);
|
||||
transition: none;
|
||||
scrollbar-color: var(--vscode-scrollbarSlider-background) transparent;
|
||||
}
|
||||
|
||||
/* Faded icon buttons in textfields */
|
||||
|
||||
.input-icon-button {
|
||||
cursor: pointer;
|
||||
opacity: 0.65;
|
||||
}
|
||||
.input-icon-button:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
.input-icon-button.disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.4;
|
||||
}
|
||||
.input-icon-button.disabled:hover {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
/* Context mentions */
|
||||
|
||||
.mention-context-textarea-highlight {
|
||||
background-color: color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 0 0 0.5px color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
|
||||
color: transparent;
|
||||
/* padding: 0.5px;
|
||||
margin: -0.5px;
|
||||
position: relative;
|
||||
bottom: -0.5px; */
|
||||
}
|
||||
|
||||
.mention-context-highlight {
|
||||
background-color: color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.mention-context-highlight-with-shadow {
|
||||
background-color: color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 0 0 0.5px color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
|
||||
}
|
||||
|
||||
.slash-command-match-textarea-highlight {
|
||||
background-color: color-mix(in srgb, var(--vscode-focusBorder) 30%, transparent);
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 0 0 0.5px color-mix(in srgb, var(--vscode-focusBorder) 30%, transparent);
|
||||
color: transparent;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
import { type ClassValue, clsx } from "clsx"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
textarea:focus {
|
||||
outline: 1.5px solid var(--vscode-focusBorder, #007fd4);
|
||||
}
|
||||
|
||||
vscode-button::part(control):focus {
|
||||
outline: none;
|
||||
}
|
||||
|
||||
/*
|
||||
Use vscode native scrollbar styles
|
||||
https://github.com/gitkraken/vscode-gitlens/blob/b1d71d4844523e8b2ef16f9e007068e91f46fd88/src/webviews/apps/home/home.scss
|
||||
*/
|
||||
|
||||
html {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
line-height: 1.25;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
background-color: var(--vscode-sideBar-background);
|
||||
}
|
||||
|
||||
#root {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
body.scrollable,
|
||||
.scrollable,
|
||||
body.code-block-scrollable,
|
||||
.code-block-scrollable {
|
||||
border-color: transparent;
|
||||
transition: border-color 0.7s linear;
|
||||
}
|
||||
|
||||
body:hover.scrollable,
|
||||
body:hover .scrollable,
|
||||
body:focus-within.scrollable,
|
||||
body:focus-within .scrollable,
|
||||
body:hover.code-block-scrollable,
|
||||
body:hover .code-block-scrollable,
|
||||
body:focus-within.code-block-scrollable,
|
||||
body:focus-within .code-block-scrollable {
|
||||
border-color: var(--vscode-scrollbarSlider-background);
|
||||
transition: none;
|
||||
}
|
||||
|
||||
.scrollable::-webkit-scrollbar-corner {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
.scrollable::-webkit-scrollbar-thumb {
|
||||
background-color: transparent;
|
||||
border-color: inherit;
|
||||
border-right-style: inset;
|
||||
border-right-width: calc(100vw + 100vh);
|
||||
border-radius: unset;
|
||||
}
|
||||
|
||||
.scrollable::-webkit-scrollbar-thumb:hover {
|
||||
border-color: var(--vscode-scrollbarSlider-hoverBackground);
|
||||
}
|
||||
|
||||
.scrollable::-webkit-scrollbar-thumb:active {
|
||||
border-color: var(--vscode-scrollbarSlider-activeBackground);
|
||||
}
|
||||
|
||||
/*
|
||||
Fix VSCode ignoring webkit scrollbar modifiers
|
||||
https://github.com/microsoft/vscode/issues/213045
|
||||
*/
|
||||
@supports selector(::-webkit-scrollbar) {
|
||||
html {
|
||||
scrollbar-color: unset;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
The above scrollbar styling uses some transparent background color magic to accomplish its animation. However this doesn't play nicely with SyntaxHighlighter, so we need to set a background color for the code blocks' horizontal scrollbar. This actually has the unintended consequence of always showing the scrollbar which I prefer since it makes it more obvious that there is more content to scroll to.
|
||||
*/
|
||||
|
||||
.code-block-scrollable::-webkit-scrollbar-track {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.code-block-scrollable::-webkit-scrollbar-thumb {
|
||||
background-color: var(--vscode-scrollbarSlider-background);
|
||||
border-radius: 5px;
|
||||
border: 2px solid transparent;
|
||||
background-clip: content-box;
|
||||
}
|
||||
|
||||
.code-block-scrollable::-webkit-scrollbar-thumb:hover {
|
||||
background-color: var(--vscode-scrollbarSlider-hoverBackground);
|
||||
}
|
||||
|
||||
.code-block-scrollable::-webkit-scrollbar-thumb:active {
|
||||
background-color: var(--vscode-scrollbarSlider-activeBackground);
|
||||
}
|
||||
|
||||
.code-block-scrollable::-webkit-scrollbar-corner {
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
/*
|
||||
Dropdown label
|
||||
https://github.com/microsoft/vscode-webview-ui-toolkit/tree/main/src/dropdown#with-label
|
||||
*/
|
||||
.dropdown-container {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
align-items: flex-start;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
.dropdown-container label {
|
||||
display: block;
|
||||
color: var(--vscode-foreground);
|
||||
cursor: pointer;
|
||||
font-size: var(--vscode-font-size);
|
||||
line-height: normal;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
/* Fix scrollbar in dropdown */
|
||||
|
||||
vscode-dropdown::part(listbox) {
|
||||
border-color: var(--vscode-scrollbarSlider-background);
|
||||
transition: none;
|
||||
scrollbar-color: var(--vscode-scrollbarSlider-background) transparent;
|
||||
}
|
||||
|
||||
/* Faded icon buttons in textfields */
|
||||
|
||||
.input-icon-button {
|
||||
cursor: pointer;
|
||||
opacity: 0.65;
|
||||
}
|
||||
.input-icon-button:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
.input-icon-button.disabled {
|
||||
cursor: not-allowed;
|
||||
opacity: 0.4;
|
||||
}
|
||||
.input-icon-button.disabled:hover {
|
||||
opacity: 0.4;
|
||||
}
|
||||
|
||||
/* Context mentions */
|
||||
|
||||
.mention-context-textarea-highlight {
|
||||
background-color: color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 0 0 0.5px color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
|
||||
color: transparent;
|
||||
/* padding: 0.5px;
|
||||
margin: -0.5px;
|
||||
position: relative;
|
||||
bottom: -0.5px; */
|
||||
}
|
||||
|
||||
.mention-context-highlight {
|
||||
background-color: color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.mention-context-highlight-with-shadow {
|
||||
background-color: color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 0 0 0.5px color-mix(in srgb, var(--vscode-badge-foreground) 30%, transparent);
|
||||
}
|
||||
|
||||
.slash-command-match-textarea-highlight {
|
||||
background-color: color-mix(in srgb, var(--vscode-focusBorder) 30%, transparent);
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 0 0 0.5px color-mix(in srgb, var(--vscode-focusBorder) 30%, transparent);
|
||||
color: transparent;
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { StrictMode } from "react"
|
||||
import { createRoot } from "react-dom/client"
|
||||
import "./main.css"
|
||||
import "./index.css"
|
||||
import App from "./App.tsx"
|
||||
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
/* Editor theme mapping */
|
||||
@theme {
|
||||
--color-background: var(--vscode-sideBar-background);
|
||||
--color-border: var(--vscode-focusBorder);
|
||||
--color-border-panel: var(--vscode-panel-border);
|
||||
--color-foreground: var(--vscode-foreground);
|
||||
--color-shadow: var(--vscode-widget-shadow);
|
||||
--color-code: var(--vscode-editor-background);
|
||||
--color-code-foreground: var(--vscode-editor-foreground);
|
||||
--color-code-border: var(--vscode-editor-border);
|
||||
--color-sidebar-background: var(--vscode-sideBar-background);
|
||||
--color-sidebar-foreground: var(--vscode-sideBar-foreground);
|
||||
--color-input-foreground: var(--vscode-input-foreground);
|
||||
--color-input-background: var(--vscode-input-background);
|
||||
--color-input-border: var(--vscode-input-border);
|
||||
--color-input-placeholder: var(--vscode-input-placeholderForeground);
|
||||
--color-selection: var(--vscode-list-activeSelectionBackground);
|
||||
--color-selection-foreground: var(--vscode-list-activeSelectionForeground);
|
||||
--color-button-background: var(--vscode-button-background);
|
||||
--color-button-hover: var(--vscode-button-hoverBackground);
|
||||
--color-button-foreground: var(--vscode-button-foreground);
|
||||
--color-button-separator: var(--vscode-button-separator);
|
||||
--color-button-secondary-background: var(--vscode-button-secondaryBackground);
|
||||
--color-button-secondary-background-hover: var(--vscode-button-secondaryHoverBackground);
|
||||
--color-button-secondary-foreground: var(--vscode-button-secondaryForeground);
|
||||
--color-muted: var(--vscode-editor-foldBackground);
|
||||
--color-muted-foreground: var(--vscode-editor-foldPlaceholderForeground);
|
||||
--color-menu: var(--vscode-menu-background);
|
||||
--color-menu-foreground: var(--vscode-menu-foreground);
|
||||
--color-menu-border: var(--vscode-menu-border);
|
||||
--color-menu-shadow: var(--vscode-menu-shadow);
|
||||
--color-link: var(--vscode-textLink-foreground);
|
||||
--color-link-hover: var(--vscode-textLink-activeForeground);
|
||||
--color-list-hover: var(--vscode-list-hoverBackground);
|
||||
--color-badge-foreground: var(--vscode-badge-foreground);
|
||||
--color-badge-background: var(--vscode-badge-background);
|
||||
--color-banner-background: var(--vscode-banner-background);
|
||||
--color-banner-foreground: var(--vscode-banner-foreground);
|
||||
--color-banner-icon: var(--vscode-banner-iconForeground);
|
||||
--color-icon-foreground: var(--vscode-icon-foreground);
|
||||
--color-toolbar-default: var(--vscode-toolbar-background);
|
||||
--color-toolbar-hover: var(--vscode-toolbar-hoverBackground);
|
||||
--color-error: var(--vscode-errorForeground);
|
||||
--color-description: var(--vscode-descriptionForeground);
|
||||
--color-success: var(--vscode-charts-green);
|
||||
--color-warning: var(--vscode-charts-yellow);
|
||||
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
--font-azeret-mono: Azeret Mono, monospace;
|
||||
--text-2xl: calc(2.25 * var(--vscode-font-size));
|
||||
--text-xl: calc(2 * var(--vscode-font-size));
|
||||
--text-lg: calc(1.5 * var(--vscode-font-size));
|
||||
--text-md: calc(1.25 * var(--vscode-font-size));
|
||||
--text-base: var(--vscode-font-size);
|
||||
--text-sm: calc(0.9 * var(--vscode-font-size));
|
||||
--text-xs: calc(0.75 * var(--vscode-font-size));
|
||||
--text-xxs: calc(0.5 * var(--vscode-font-size));
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) + 4px);
|
||||
--color-card: var(--card);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-border: var(--border);
|
||||
--color-input: var(--input);
|
||||
--color-ring: var(--ring);
|
||||
--color-chart-1: var(--chart-1);
|
||||
--color-chart-2: var(--chart-2);
|
||||
--color-chart-3: var(--chart-3);
|
||||
--color-chart-4: var(--chart-4);
|
||||
--color-chart-5: var(--chart-5);
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||
--color-sidebar-primary: var(--sidebar-primary);
|
||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||
--color-sidebar-accent: var(--sidebar-accent);
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
--size-1: calc(0.5 * var(--vscode-font-size));
|
||||
--size-2: calc(1 * var(--vscode-font-size));
|
||||
--size-3: calc(1.5 * var(--vscode-font-size));
|
||||
}
|
||||
|
||||
:root {
|
||||
--radius: 0.625rem;
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.145 0 0);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.145 0 0);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.145 0 0);
|
||||
--primary: oklch(0.205 0 0);
|
||||
--primary-foreground: oklch(0.985 0 0);
|
||||
--secondary: oklch(0.97 0 0);
|
||||
--secondary-foreground: oklch(0.205 0 0);
|
||||
--muted: oklch(0.97 0 0);
|
||||
--muted-foreground: oklch(0.556 0 0);
|
||||
--accent: oklch(0.97 0 0);
|
||||
--accent-foreground: oklch(0.205 0 0);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.922 0 0);
|
||||
--input: oklch(0.922 0 0);
|
||||
--ring: oklch(0.708 0 0);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.145 0 0);
|
||||
--sidebar-primary: oklch(0.205 0 0);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.97 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.205 0 0);
|
||||
--sidebar-border: oklch(0.922 0 0);
|
||||
--sidebar-ring: oklch(0.708 0 0);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.145 0 0);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.205 0 0);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.205 0 0);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.922 0 0);
|
||||
--primary-foreground: oklch(0.205 0 0);
|
||||
--secondary: oklch(0.269 0 0);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.269 0 0);
|
||||
--muted-foreground: oklch(0.708 0 0);
|
||||
--accent: oklch(0.269 0 0);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.556 0 0);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.205 0 0);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.269 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.556 0 0);
|
||||
}
|
||||
@@ -27,3 +27,27 @@ export const getEnvironmentColor = (environment: Environment | undefined, type:
|
||||
? "var(--vscode-focusBorder)" // Blue for staging
|
||||
: "var(--vscode-foreground)" // Default for production
|
||||
}
|
||||
|
||||
export function getClineEnvironmentClassname(environment: Environment | undefined, type = "text") {
|
||||
if (type === "border") {
|
||||
switch (environment) {
|
||||
case "local":
|
||||
return "border-(--vscode-activityWarningBadge-background)"
|
||||
case "staging":
|
||||
return "border-(--vscode-focusBorder)"
|
||||
case "production":
|
||||
default:
|
||||
return "border-(--vscode-editorGroup-border)"
|
||||
}
|
||||
}
|
||||
|
||||
switch (environment) {
|
||||
case "local":
|
||||
return "var(--vscode-activityWarningBadge-background)"
|
||||
case "staging":
|
||||
return "var(--vscode-focusBorder)"
|
||||
case "production":
|
||||
default:
|
||||
return "var(--vscode-foreground)"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,5 +7,13 @@
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
}
|
||||
]
|
||||
],
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user