Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cc0ab31d8b | ||
|
|
7b0decba59 | ||
|
|
588e735493 | ||
|
|
552b562269 | ||
|
|
d7ae62dca1 | ||
|
|
89b46c10b2 | ||
|
|
df9b0a163d | ||
|
|
29af363090 | ||
|
|
89338a2c13 | ||
|
|
2adae27632 | ||
|
|
e3a343e8b0 | ||
|
|
e81147a8f7 | ||
|
|
d6d40ebe59 |
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": patch
|
||||
---
|
||||
|
||||
Introduce UI library for future UI development
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"claude-dev": minor
|
||||
---
|
||||
|
||||
Refactor to not pass a message for showing the MCP View from the servers modal
|
||||
@@ -18,4 +18,5 @@ coverage
|
||||
# But don't ignore the coverage scripts in .github/scripts/
|
||||
!.github/scripts/coverage/
|
||||
|
||||
*evals.env
|
||||
*evals.env
|
||||
*.zip
|
||||
|
||||
@@ -16,6 +16,28 @@
|
||||
"IS_DEV": "true",
|
||||
"DEV_WORKSPACE_FOLDER": "${workspaceFolder}"
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "Run Extension (Fresh Install Mode)",
|
||||
"type": "extensionHost",
|
||||
"request": "launch",
|
||||
"runtimeExecutable": "${execPath}",
|
||||
"args": [
|
||||
"--profile-temp",
|
||||
"--sync",
|
||||
"off",
|
||||
"--disable-extensions",
|
||||
"--extensionDevelopmentPath=${workspaceFolder}",
|
||||
"${workspaceFolder}"
|
||||
],
|
||||
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
|
||||
"preLaunchTask": "clean-sandbox",
|
||||
"internalConsoleOptions": "openOnSessionStart",
|
||||
"postDebugTask": "stop",
|
||||
"env": {
|
||||
"IS_DEV": "true",
|
||||
"DEV_WORKSPACE_FOLDER": "${workspaceFolder}"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -185,6 +185,12 @@
|
||||
"label": "stop",
|
||||
"command": "echo ${input:terminate}",
|
||||
"type": "shell"
|
||||
},
|
||||
{
|
||||
"label": "clean-sandbox",
|
||||
"type": "shell",
|
||||
"dependsOn": ["watch"],
|
||||
"command": "rm -rf .vscode-dev"
|
||||
}
|
||||
],
|
||||
"inputs": [
|
||||
|
||||
@@ -118,6 +118,11 @@
|
||||
"command": "cline.focusChatInput",
|
||||
"title": "Jump to Chat Input",
|
||||
"category": "Cline"
|
||||
},
|
||||
{
|
||||
"command": "cline.showWelcomeTab",
|
||||
"title": "Show Welcome Tab",
|
||||
"category": "Cline"
|
||||
}
|
||||
],
|
||||
"keybindings": [
|
||||
|
||||
@@ -1672,6 +1672,7 @@ Here is the project's README to help you get started:\n\n${mcpDetails.readmeCont
|
||||
planActSeparateModelsSetting,
|
||||
globalClineRulesToggles,
|
||||
shellIntegrationTimeout,
|
||||
showWelcome,
|
||||
} = await getAllExtensionState(this.context)
|
||||
|
||||
const localClineRulesToggles =
|
||||
@@ -1704,6 +1705,7 @@ Here is the project's README to help you get started:\n\n${mcpDetails.readmeCont
|
||||
mcpMarketplaceEnabled,
|
||||
telemetrySetting,
|
||||
planActSeparateModelsSetting,
|
||||
showWelcome,
|
||||
vscMachineId: vscode.env.machineId,
|
||||
globalClineRulesToggles: globalClineRulesToggles || {},
|
||||
localClineRulesToggles: localClineRulesToggles || {},
|
||||
|
||||
@@ -81,5 +81,6 @@ export type GlobalStateKey =
|
||||
| "favoritedModelIds"
|
||||
| "requestTimeoutMs"
|
||||
| "shellIntegrationTimeout"
|
||||
| "showWelcome"
|
||||
|
||||
export type LocalStateKey = "localClineRulesToggles"
|
||||
|
||||
@@ -131,6 +131,7 @@ export async function getAllExtensionState(context: vscode.ExtensionContext) {
|
||||
globalClineRulesToggles,
|
||||
requestTimeoutMs,
|
||||
shellIntegrationTimeout,
|
||||
showWelcome,
|
||||
] = await Promise.all([
|
||||
getGlobalState(context, "apiProvider") as Promise<ApiProvider | undefined>,
|
||||
getGlobalState(context, "apiModelId") as Promise<string | undefined>,
|
||||
@@ -210,6 +211,7 @@ export async function getAllExtensionState(context: vscode.ExtensionContext) {
|
||||
getGlobalState(context, "globalClineRulesToggles") as Promise<ClineRulesToggles | undefined>,
|
||||
getGlobalState(context, "requestTimeoutMs") as Promise<number | undefined>,
|
||||
getGlobalState(context, "shellIntegrationTimeout") as Promise<number | undefined>,
|
||||
getGlobalState(context, "showWelcome") as Promise<boolean | undefined>,
|
||||
])
|
||||
|
||||
let apiProvider: ApiProvider
|
||||
@@ -334,6 +336,7 @@ export async function getAllExtensionState(context: vscode.ExtensionContext) {
|
||||
telemetrySetting: telemetrySetting || "unset",
|
||||
planActSeparateModelsSetting,
|
||||
shellIntegrationTimeout: shellIntegrationTimeout || 4000,
|
||||
showWelcome,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,8 @@ import { Controller } from "@core/controller/index"
|
||||
import { findLast } from "@shared/array"
|
||||
import { readFile } from "fs/promises"
|
||||
import path from "node:path"
|
||||
|
||||
import { WebviewType } from "@shared/WebviewMessage"
|
||||
import { setTimeout as setTimeoutPromise } from "node:timers/promises"
|
||||
/*
|
||||
https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts
|
||||
https://github.com/KumarVariable/vscode-extension-sidebar-html/blob/master/src/customSidebarViewProvider.ts
|
||||
@@ -24,6 +25,7 @@ export class WebviewProvider implements vscode.WebviewViewProvider {
|
||||
constructor(
|
||||
readonly context: vscode.ExtensionContext,
|
||||
private readonly outputChannel: vscode.OutputChannel,
|
||||
private readonly webviewType: WebviewType = "sidebar",
|
||||
) {
|
||||
WebviewProvider.activeInstances.add(this)
|
||||
this.controller = new Controller(context, outputChannel, (message) => this.view?.webview.postMessage(message))
|
||||
@@ -86,12 +88,31 @@ export class WebviewProvider implements vscode.WebviewViewProvider {
|
||||
// WebviewView and WebviewPanel have all the same properties except for this visibility listener
|
||||
// panel
|
||||
webviewView.onDidChangeViewState(
|
||||
() => {
|
||||
async () => {
|
||||
if (this.view?.visible) {
|
||||
// Check if showWelcome flag is set in global state
|
||||
const showWelcome = await this.controller.context.globalState.get<boolean>("showWelcome")
|
||||
|
||||
// Send didBecomeVisible action
|
||||
this.controller.postMessageToWebview({
|
||||
type: "action",
|
||||
action: "didBecomeVisible",
|
||||
})
|
||||
|
||||
// If showWelcome flag is set, send showWelcome message and clear the flag
|
||||
// We're now sending it to all webviews to ensure it's displayed
|
||||
if (showWelcome) {
|
||||
console.log(`Sending showWelcome message to ${this.webviewType} webview`)
|
||||
this.controller.postMessageToWebview({
|
||||
type: "showWelcome",
|
||||
})
|
||||
|
||||
// Add a delay before clearing the flag to ensure the webview has time to process it
|
||||
await setTimeoutPromise(1000)
|
||||
|
||||
// Clear the flag after sending the message
|
||||
await this.controller.context.globalState.update("showWelcome", undefined)
|
||||
}
|
||||
}
|
||||
},
|
||||
null,
|
||||
@@ -100,12 +121,30 @@ export class WebviewProvider implements vscode.WebviewViewProvider {
|
||||
} else if ("onDidChangeVisibility" in webviewView) {
|
||||
// sidebar
|
||||
webviewView.onDidChangeVisibility(
|
||||
() => {
|
||||
async () => {
|
||||
if (this.view?.visible) {
|
||||
// Check if showWelcome flag is set in global state
|
||||
const showWelcome = await this.controller.context.globalState.get<boolean>("showWelcome")
|
||||
|
||||
// Send didBecomeVisible action
|
||||
this.controller.postMessageToWebview({
|
||||
type: "action",
|
||||
action: "didBecomeVisible",
|
||||
})
|
||||
|
||||
// If showWelcome flag is set, send showWelcome message and clear the flag
|
||||
if (showWelcome) {
|
||||
console.log(`Sending showWelcome message to ${this.webviewType} webview`)
|
||||
this.controller.postMessageToWebview({
|
||||
type: "showWelcome",
|
||||
})
|
||||
|
||||
// Add a delay before clearing the flag to ensure the webview has time to process it
|
||||
await setTimeoutPromise(1000)
|
||||
|
||||
// Clear the flag after sending the message
|
||||
await this.controller.context.globalState.update("showWelcome", undefined)
|
||||
}
|
||||
}
|
||||
},
|
||||
null,
|
||||
@@ -221,6 +260,7 @@ export class WebviewProvider implements vscode.WebviewViewProvider {
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
|
||||
<meta name="theme-color" content="#000000">
|
||||
<meta name="webview-type" content="${this.webviewType}">
|
||||
<link rel="stylesheet" type="text/css" href="${stylesUri}">
|
||||
<link href="${codiconsUri}" rel="stylesheet" />
|
||||
<link href="${katexCssUri}" rel="stylesheet" />
|
||||
@@ -331,6 +371,7 @@ export class WebviewProvider implements vscode.WebviewViewProvider {
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
|
||||
<meta http-equiv="Content-Security-Policy" content="${csp.join("; ")}">
|
||||
<meta name="webview-type" content="${this.webviewType}">
|
||||
<link rel="stylesheet" type="text/css" href="${stylesUri}">
|
||||
<link href="${codiconsUri}" rel="stylesheet" />
|
||||
<link href="${katexCssUri}" rel="stylesheet" />
|
||||
|
||||
@@ -34,7 +34,7 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
Logger.initialize(outputChannel)
|
||||
Logger.log("Cline extension activated")
|
||||
|
||||
const sidebarWebview = new WebviewProvider(context, outputChannel)
|
||||
const sidebarWebview = new WebviewProvider(context, outputChannel, "sidebar")
|
||||
|
||||
// Initialize test mode and add disposables to context
|
||||
context.subscriptions.push(...initializeTestMode(context, sidebarWebview))
|
||||
@@ -82,37 +82,47 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
}),
|
||||
)
|
||||
|
||||
const openClineInNewTab = async () => {
|
||||
const openClineInNewTab = async (isWelcome = false): Promise<WebviewProvider> => {
|
||||
Logger.log("Opening Cline in new tab")
|
||||
// (this example uses webviewProvider activation event which is necessary to deserialize cached webview, but since we use retainContextWhenHidden, we don't need to use that event)
|
||||
// https://github.com/microsoft/vscode-extension-samples/blob/main/webview-sample/src/extension.ts
|
||||
const tabWebview = new WebviewProvider(context, outputChannel)
|
||||
//const column = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined
|
||||
const lastCol = Math.max(...vscode.window.visibleTextEditors.map((editor) => editor.viewColumn || 0))
|
||||
const tabWebview = new WebviewProvider(context, outputChannel, "tab")
|
||||
let targetCol: vscode.ViewColumn
|
||||
|
||||
// Check if there are any visible text editors, otherwise open a new group to the right
|
||||
const hasVisibleEditors = vscode.window.visibleTextEditors.length > 0
|
||||
if (!hasVisibleEditors) {
|
||||
await vscode.commands.executeCommand("workbench.action.newGroupRight")
|
||||
if (!isWelcome) {
|
||||
//const column = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined
|
||||
const lastCol = Math.max(...vscode.window.visibleTextEditors.map((editor) => editor.viewColumn || 0))
|
||||
|
||||
// Check if there are any visible text editors, otherwise open a new group to the right
|
||||
const hasVisibleEditors = vscode.window.visibleTextEditors.length > 0
|
||||
if (!hasVisibleEditors) {
|
||||
await vscode.commands.executeCommand("workbench.action.newGroupRight")
|
||||
}
|
||||
targetCol = hasVisibleEditors ? Math.max(lastCol + 1, 1) : vscode.ViewColumn.Two
|
||||
} else {
|
||||
targetCol = vscode.ViewColumn.One
|
||||
}
|
||||
const targetCol = hasVisibleEditors ? Math.max(lastCol + 1, 1) : vscode.ViewColumn.Two
|
||||
|
||||
const panel = vscode.window.createWebviewPanel(WebviewProvider.tabPanelId, "Cline", targetCol, {
|
||||
enableScripts: true,
|
||||
retainContextWhenHidden: true,
|
||||
localResourceRoots: [context.extensionUri],
|
||||
})
|
||||
// TODO: use better svg icon with light and dark variants (see https://stackoverflow.com/questions/58365687/vscode-extension-iconpath)
|
||||
|
||||
panel.iconPath = {
|
||||
light: vscode.Uri.joinPath(context.extensionUri, "assets", "icons", "robot_panel_light.png"),
|
||||
dark: vscode.Uri.joinPath(context.extensionUri, "assets", "icons", "robot_panel_dark.png"),
|
||||
}
|
||||
tabWebview.resolveWebviewView(panel)
|
||||
|
||||
await tabWebview.resolveWebviewView(panel)
|
||||
|
||||
// Lock the editor group so clicking on files doesn't open them over the panel
|
||||
await setTimeoutPromise(100)
|
||||
await vscode.commands.executeCommand("workbench.action.lockEditorGroup")
|
||||
|
||||
if (isWelcome) {
|
||||
panel.reveal(targetCol)
|
||||
}
|
||||
return tabWebview
|
||||
}
|
||||
|
||||
context.subscriptions.push(vscode.commands.registerCommand("cline.popoutButtonClicked", openClineInNewTab))
|
||||
@@ -421,8 +431,32 @@ export function activate(context: vscode.ExtensionContext) {
|
||||
})
|
||||
}),
|
||||
)
|
||||
checkInstallationStatus(context)
|
||||
|
||||
return createClineAPI(outputChannel, sidebarWebview.controller)
|
||||
|
||||
async function checkInstallationStatus(context: vscode.ExtensionContext) {
|
||||
const VERSION_KEY = "cline.version"
|
||||
const current = context.extension.packageJSON.version as string
|
||||
const previous = context.globalState.get<string>(VERSION_KEY)
|
||||
|
||||
if (!previous) {
|
||||
console.log("First time installation detected, setting showWelcome flag")
|
||||
// Set the showWelcome flag to true in global state
|
||||
await context.globalState.update("showWelcome", true)
|
||||
|
||||
// Open a single tab with the welcome screen
|
||||
const tab = await openClineInNewTab(true)
|
||||
console.log("Tab opened for welcome screen")
|
||||
|
||||
// Send the showWelcome message directly to the webview
|
||||
await tab.controller.postMessageToWebview({ type: "showWelcome" })
|
||||
console.log("Sent showWelcome message directly to webview")
|
||||
|
||||
// persist for the next activation
|
||||
await context.globalState.update(VERSION_KEY, current)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Find a solution for automatically removing DEV related content from production builds.
|
||||
|
||||
@@ -47,6 +47,7 @@ export interface ExtensionMessage {
|
||||
| "fileSearchResults"
|
||||
| "grpc_response" // New type for gRPC responses
|
||||
| "setActiveQuote"
|
||||
| "showWelcome"
|
||||
text?: string
|
||||
action?:
|
||||
| "chatButtonClicked"
|
||||
@@ -143,6 +144,7 @@ export interface ExtensionState {
|
||||
localClineRulesToggles: ClineRulesToggles
|
||||
localCursorRulesToggles: ClineRulesToggles
|
||||
localWindsurfRulesToggles: ClineRulesToggles
|
||||
showWelcome?: boolean
|
||||
}
|
||||
|
||||
export interface ClineMessage {
|
||||
|
||||
@@ -125,3 +125,5 @@ export type ClineAskResponse = "yesButtonClicked" | "noButtonClicked" | "message
|
||||
export type ClineCheckpointRestore = "task" | "workspace" | "taskAndWorkspace"
|
||||
|
||||
export type TaskFeedbackType = "thumbs_up" | "thumbs_down"
|
||||
|
||||
export type WebviewType = "sidebar" | "tab"
|
||||
|
||||
@@ -5439,6 +5439,34 @@
|
||||
"react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0-rc.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.1.tgz",
|
||||
"integrity": "sha512-kxz0YeeCrRUHz3zyqvd7n+TVRlNyTifBsmnmNPtk3hQURUyG9eAB+usz6DAwagMusjx/zb3AjvDUvhFGDAexGw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.1.tgz",
|
||||
"integrity": "sha512-PPkxTOisoNC6TpnDKatjKkjRMsdaWIhyuMkA4UsBXT9WEZY4uHezBTjs6Vl4PbqQQeu6oION1w2voYZv9yquCw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.1.tgz",
|
||||
@@ -5453,6 +5481,174 @@
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.1.tgz",
|
||||
"integrity": "sha512-nIwkXafAI1/QCS7pxSpv/ZtFW6TXcNUEHAIA9EIyw5OzxJZQ1YDrX+CL6JAIQgZ33CInl1R6mHet9Y/UZTg2Bw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.1.tgz",
|
||||
"integrity": "sha512-BdrLJ2mHTrIYdaS2I99mriyJfGGenSaP+UwGi1kB9BLOCu9SR8ZpbkmmalKIALnRw24kM7qCN0IOm6L0S44iWw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.1.tgz",
|
||||
"integrity": "sha512-VXeo/puqvCG8JBPNZXZf5Dqq7BzElNJzHRRw3vjBE27WujdzuOPecDPc/+1DcdcTptNBep3861jNq0mYkT8Z6Q==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.1.tgz",
|
||||
"integrity": "sha512-ehSKrewwsESPt1TgSE/na9nIhWCosfGSFqv7vwEtjyAqZcvbGIg4JAcV7ZEh2tfj/IlfBeZjgOXm35iOOjadcg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.1.tgz",
|
||||
"integrity": "sha512-m39iO/aaurh5FVIu/F4/Zsl8xppd76S4qoID8E+dSRQvTyZTOI2gVk3T4oqzfq1PtcvOfAVlwLMK3KRQMaR8lg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.1.tgz",
|
||||
"integrity": "sha512-Y+GHnGaku4aVLSgrT0uWe2o2Rq8te9hi+MwqGF9r9ORgXhmHK5Q71N757u0F8yU1OIwUIFy6YiJtKjtyktk5hg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.1.tgz",
|
||||
"integrity": "sha512-jEwjn3jCA+tQGswK3aEWcD09/7M5wGwc6+flhva7dsQNRZZTe30vkalgIzV4tjkopsTS9Jd7Y1Bsj6a4lzz8gQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.1.tgz",
|
||||
"integrity": "sha512-ySyWikVhNzv+BV/IDCsrraOAZ3UaC8SZB67FZlqVwXwnFhPihOso9rPOxzZbjp81suB1O2Topw+6Ug3JNegejQ==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.1.tgz",
|
||||
"integrity": "sha512-BvvA64QxZlh7WZWqDPPdt0GH4bznuL6uOO1pmgPnnv86rpUpc8ZxgZwcEgXvo02GRIZX1hQ0j0pAnhwkhwPqWg==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.1.tgz",
|
||||
"integrity": "sha512-EQSP+8+1VuSulm9RKSMKitTav89fKbHymTf25n5+Yr6gAPZxYWpj3DzAsQqoaHAk9YX2lwEyAf9S4W8F4l3VBQ==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.1.tgz",
|
||||
"integrity": "sha512-n/vQ4xRZXKuIpqukkMXZt9RWdl+2zgGNx7Uda8NtmLJ06NL8jiHxUawbwC+hdSq1rrw/9CghCpEONor+l1e2gA==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.1.tgz",
|
||||
"integrity": "sha512-h8d28xzYb98fMQKUz0w2fMc1XuGzLLjdyxVIbhbil4ELfk5/orZlSTpF/xdI9C8K0I8lCkq+1En2RJsawZekkg==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.1.tgz",
|
||||
@@ -5466,6 +5662,62 @@
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.1.tgz",
|
||||
"integrity": "sha512-2BRORitq5rQ4Da9blVovzNCMaUlyKrzMSvkVR0D4qPuOy/+pMCrh1d7o01RATwVy+6Fa1WBw+da7QPeLWU/1mQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.1.tgz",
|
||||
"integrity": "sha512-b2bcNm9Kbde03H+q+Jjw9tSfhYkzrDUf2d5MAd1bOJuVplXvFhWz7tRtWvD8/ORZi7qSCy0idW6tf2HgxSXQSg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.1.tgz",
|
||||
"integrity": "sha512-DfcogW8N7Zg7llVEfpqWMZcaErKfsj9VvmfSyRjCyo4BI3wPEfrzTtJkZG6gKP/Z92wFm6rz2aDO7/JfiR/whA==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.40.1",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.1.tgz",
|
||||
"integrity": "sha512-ECyOuDeH3C1I8jH2MK1RtBJW+YPMvSfT0a5NN0nHfQYnDSJ6tUiZH3gzwVP5/Kfh/+Tt7tpWVF9LXNTnhTJ3kA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rrweb/types": {
|
||||
"version": "2.0.0-alpha.17",
|
||||
"resolved": "https://registry.npmjs.org/@rrweb/types/-/types-2.0.0-alpha.17.tgz",
|
||||
|
||||
@@ -1,23 +1,34 @@
|
||||
import { useCallback, useEffect, useState } from "react"
|
||||
import { useCallback, useEffect, useMemo, useState } from "react"
|
||||
import { useEvent } from "react-use"
|
||||
import { ExtensionMessage } from "@shared/ExtensionMessage"
|
||||
import { WebviewType } from "@shared/WebviewMessage"
|
||||
import ChatView from "./components/chat/ChatView"
|
||||
import HistoryView from "./components/history/HistoryView"
|
||||
import SettingsView from "./components/settings/SettingsView"
|
||||
import WelcomeView from "./components/welcome/WelcomeView"
|
||||
import AccountView from "./components/account/AccountView"
|
||||
import { useExtensionState } from "./context/ExtensionStateContext"
|
||||
import { vscode } from "./utils/vscode"
|
||||
import McpView from "./components/mcp/configuration/McpConfigurationView"
|
||||
import { Providers } from "./Providers"
|
||||
import { McpViewTab } from "@shared/mcp"
|
||||
import WelcomeWrapper from "./components/welcome/WelcomeWrapper"
|
||||
|
||||
const AppContent = () => {
|
||||
const { didHydrateState, showWelcome, shouldShowAnnouncement, showMcp, mcpTab } = useExtensionState()
|
||||
const { didHydrateState, shouldShowAnnouncement, showMcp, mcpTab } = useExtensionState()
|
||||
const [showSettings, setShowSettings] = useState(false)
|
||||
const hideSettings = useCallback(() => setShowSettings(false), [])
|
||||
const [showHistory, setShowHistory] = useState(false)
|
||||
const [showAccount, setShowAccount] = useState(false)
|
||||
const [showAnnouncement, setShowAnnouncement] = useState(false)
|
||||
// Use local state for welcome view, initialized from extension state
|
||||
const [showWelcomeLocal, setShowWelcomeLocal] = useState(true)
|
||||
const { setShowWelcome } = useExtensionState()
|
||||
|
||||
// Sync local state with extension state
|
||||
useEffect(() => {
|
||||
console.log("Setting showWelcome in extension state to true")
|
||||
setShowWelcome(true)
|
||||
}, [setShowWelcome])
|
||||
|
||||
const { setShowMcp, setMcpTab } = useExtensionState()
|
||||
|
||||
@@ -29,7 +40,12 @@ const AppContent = () => {
|
||||
const handleMessage = useCallback(
|
||||
(e: MessageEvent) => {
|
||||
const message: ExtensionMessage = e.data
|
||||
console.log("Received message in App.tsx:", message)
|
||||
switch (message.type) {
|
||||
case "showWelcome":
|
||||
console.log("Received showWelcome message in App.tsx")
|
||||
setShowWelcomeLocal(true)
|
||||
break
|
||||
case "action":
|
||||
switch (message.action!) {
|
||||
case "settingsButtonClicked":
|
||||
@@ -64,6 +80,7 @@ const AppContent = () => {
|
||||
setShowHistory(false)
|
||||
closeMcpView()
|
||||
setShowAccount(false)
|
||||
setShowWelcomeLocal(false) // Hide welcome view when chat button is clicked
|
||||
break
|
||||
}
|
||||
break
|
||||
@@ -96,8 +113,8 @@ const AppContent = () => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{showWelcome ? (
|
||||
<WelcomeView />
|
||||
{showWelcomeLocal ? (
|
||||
<WelcomeWrapper showWelcome={showWelcomeLocal} />
|
||||
) : (
|
||||
<>
|
||||
{showSettings && <SettingsView onDone={hideSettings} />}
|
||||
|
||||
@@ -0,0 +1,813 @@
|
||||
/* Welcome Tab Styles */
|
||||
|
||||
/* General Styles */
|
||||
.home {
|
||||
font-family: "Inter", sans-serif;
|
||||
color: var(--vscode-foreground);
|
||||
background-color: var(--vscode-editor-background);
|
||||
height: 100vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.main-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
height: 1px;
|
||||
background-color: var(--vscode-panel-border);
|
||||
margin: 40px 0;
|
||||
}
|
||||
|
||||
.divider-dashed {
|
||||
height: 1px;
|
||||
background: repeating-linear-gradient(
|
||||
to right,
|
||||
var(--vscode-panel-border),
|
||||
var(--vscode-panel-border) 6px,
|
||||
transparent 6px,
|
||||
transparent 12px
|
||||
);
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
/* Account Info Section */
|
||||
.account-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.vector-icon {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.welcome-message-container {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.welcome-message {
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 10px;
|
||||
color: var(--vscode-foreground);
|
||||
}
|
||||
|
||||
.description {
|
||||
font-size: 16px;
|
||||
color: var(--vscode-descriptionForeground);
|
||||
}
|
||||
|
||||
.buttons-container {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.primary-button {
|
||||
background-color: var(--vscode-button-background);
|
||||
color: var(--vscode-button-foreground);
|
||||
border: none;
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.primary-button:hover {
|
||||
background-color: var(--vscode-button-hoverBackground);
|
||||
}
|
||||
|
||||
.secondary-button {
|
||||
background-color: transparent;
|
||||
color: var(--vscode-button-secondaryForeground);
|
||||
border: 1px solid var(--vscode-button-secondaryBackground);
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.secondary-button:hover {
|
||||
background-color: var(--vscode-button-secondaryHoverBackground);
|
||||
}
|
||||
|
||||
/* Features Container */
|
||||
.features-container {
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.feature-row {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
gap: 16px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
background-color: var(--vscode-editor-background);
|
||||
border: 1px solid var(--vscode-panel-border);
|
||||
border-radius: 8px;
|
||||
padding: 16px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
.feature-card:hover {
|
||||
border-color: var(--vscode-focusBorder);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
.feature-icon-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.feature-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.feature-icon-1 {
|
||||
background-image: url("../images/rocket.svg");
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.feature-icon-2 {
|
||||
background-image: url("../images/rocket.svg");
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.feature-icon-3 {
|
||||
background-image: url("../images/play.svg");
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.feature-icon-4 {
|
||||
background-image: url("../images/rules.svg");
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.action-icon-1 {
|
||||
background-image: url("../images/star-check.svg");
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.action-icon-2 {
|
||||
background-image: url("../images/rocket.svg");
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.button-icon-1 {
|
||||
background-image: url("../images/button-icon-1.svg");
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.feature-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.feature-description {
|
||||
font-size: 14px;
|
||||
color: var(--vscode-descriptionForeground);
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
.footer {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.input-field {
|
||||
background-color: var(--vscode-input-background);
|
||||
border: 1px solid var(--vscode-input-border);
|
||||
border-radius: 4px;
|
||||
padding: 12px;
|
||||
position: relative;
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.input-placeholder {
|
||||
color: var(--vscode-input-placeholderForeground);
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.input-actions-container {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.input-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.action-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 6px 12px;
|
||||
border-radius: 4px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.action-button:hover {
|
||||
opacity: 1 !important;
|
||||
}
|
||||
|
||||
.action-button-secondary {
|
||||
color: var(--vscode-button-secondaryForeground);
|
||||
}
|
||||
|
||||
.action-button-secondary:hover {
|
||||
background-color: var(--vscode-button-secondaryHoverBackground);
|
||||
}
|
||||
|
||||
.action-button-primary {
|
||||
color: var(--vscode-button-foreground);
|
||||
background-color: var(--vscode-button-background);
|
||||
}
|
||||
|
||||
.action-button-primary:hover {
|
||||
background-color: var(--vscode-button-hoverBackground);
|
||||
}
|
||||
|
||||
.action-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
.action-text {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* Features Section */
|
||||
.features-section-container {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 40px;
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.features-text-container {
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.features-heading {
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 16px;
|
||||
font-family: "SF Pro", "Inter", sans-serif;
|
||||
}
|
||||
|
||||
.features-description {
|
||||
font-size: 16px;
|
||||
color: var(--vscode-descriptionForeground);
|
||||
margin-bottom: 20px;
|
||||
line-height: 1.3;
|
||||
letter-spacing: -0.01em;
|
||||
}
|
||||
|
||||
.features-tabs-container {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.tab-button {
|
||||
background-color: #181818;
|
||||
border: 1px solid #4e4e4e;
|
||||
border-radius: 9999px;
|
||||
padding: 0px 16px;
|
||||
height: 32px;
|
||||
font-size: 14px;
|
||||
cursor: pointer;
|
||||
color: var(--vscode-foreground);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
|
||||
.tab-button.active-tab {
|
||||
background-color: #026ec1;
|
||||
border: none;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.feature-content {
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.feature-selected {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.feature-check-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: #0078d4;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: white;
|
||||
font-size: 12px;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.feature-info h3 {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
margin: 0 0 8px 0;
|
||||
}
|
||||
|
||||
.feature-subtitle {
|
||||
font-size: 14px;
|
||||
color: #cccccc;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.feature-buttons-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
margin-bottom: 20px;
|
||||
border-top: 1px dashed #3d3d3d;
|
||||
border-bottom: 1px dashed #3d3d3d;
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
.feature-action-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: none;
|
||||
border: 1px solid #3d3d3d;
|
||||
padding: 0 8px;
|
||||
height: 28px;
|
||||
cursor: pointer;
|
||||
border-radius: 8px;
|
||||
color: white;
|
||||
font-size: 14px;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.feature-action-button:hover {
|
||||
background-color: rgba(255, 255, 255, 0.1);
|
||||
}
|
||||
|
||||
.feature-action-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.feature-options {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.feature-option {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.feature-option:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.feature-circle {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
border: 1.5px solid #0078d4;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.feature-option span {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.feature-image-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.feature-bg {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url("../images/feature-bg.png");
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
border-radius: 14px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
min-height: 400px;
|
||||
}
|
||||
|
||||
.feature-diagram {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.feature-pill {
|
||||
position: absolute;
|
||||
background-color: white;
|
||||
color: #0a4b8c;
|
||||
border-radius: 50px;
|
||||
padding: 8px 16px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-weight: 500;
|
||||
font-size: 14px;
|
||||
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
.feature-pill-icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.terminal-icon,
|
||||
.code-icon,
|
||||
.browser-icon {
|
||||
margin-right: 8px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.file-editing {
|
||||
top: 15%;
|
||||
right: 10%;
|
||||
}
|
||||
|
||||
.terminal-commands {
|
||||
top: 40%;
|
||||
left: 10%;
|
||||
}
|
||||
|
||||
.code-analysis {
|
||||
bottom: 30%;
|
||||
right: 15%;
|
||||
}
|
||||
|
||||
.browser-integration {
|
||||
bottom: 15%;
|
||||
left: 20%;
|
||||
}
|
||||
|
||||
.feature-robot-container {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
.feature-robot {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
/* Models Section */
|
||||
.models-container {
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.models-heading {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.models-section-container {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.model-card {
|
||||
background-color: var(--vscode-editor-background);
|
||||
border: 1px solid var(--vscode-panel-border);
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.model-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.model-name {
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.model-badge {
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.best {
|
||||
background-color: #4caf50;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.trending {
|
||||
background-color: #2196f3;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.new {
|
||||
background-color: #ff9800;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.model-description {
|
||||
font-size: 14px;
|
||||
color: var(--vscode-descriptionForeground);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.model-divider {
|
||||
height: 1px;
|
||||
background-color: var(--vscode-panel-border);
|
||||
margin: 16px 0;
|
||||
}
|
||||
|
||||
.model-image {
|
||||
width: 100%;
|
||||
height: 150px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 16px;
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.anthropic-model {
|
||||
background-image: url("../images/anthropic-model.jpg");
|
||||
}
|
||||
|
||||
.google-model {
|
||||
background-image: url("../images/google-model.jpg");
|
||||
}
|
||||
|
||||
.meta-model {
|
||||
background-image: url("../images/meta-model.jpg");
|
||||
}
|
||||
|
||||
.model-button {
|
||||
background-color: var(--vscode-button-background);
|
||||
color: var(--vscode-button-foreground);
|
||||
border: none;
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
transition: background-color 0.2s;
|
||||
margin-top: auto;
|
||||
}
|
||||
|
||||
.model-button:hover {
|
||||
background-color: var(--vscode-button-hoverBackground);
|
||||
}
|
||||
|
||||
/* Plan/Act Mode Section */
|
||||
.plan-act-container {
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.plan-act-heading {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.plan-act-description {
|
||||
font-size: 14px;
|
||||
color: var(--vscode-descriptionForeground);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.plan-act-content {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.plan-mode-container,
|
||||
.act-mode-container {
|
||||
background-color: var(--vscode-editor-background);
|
||||
border: 1px solid var(--vscode-panel-border);
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.mode-header {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.mode-title {
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.mode-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.mode-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mode-item.disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.mode-icon {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 12px;
|
||||
}
|
||||
|
||||
.plan-icon {
|
||||
color: #f5a524;
|
||||
}
|
||||
|
||||
.plan-icon-disabled {
|
||||
color: #f31260;
|
||||
}
|
||||
|
||||
.act-icon {
|
||||
color: #006fee;
|
||||
}
|
||||
|
||||
.line-icon {
|
||||
width: 14px;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.plan-line {
|
||||
background-image: url("../images/plan-line.svg");
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.act-line {
|
||||
background-image: url("../images/act-line.svg");
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.disabled-line {
|
||||
background-image: url("../images/disabled-line.svg");
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
}
|
||||
|
||||
.mode-text {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
/* MCP Servers Section */
|
||||
.mcp-servers-container {
|
||||
padding: 20px 0;
|
||||
}
|
||||
|
||||
.mcp-content-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mcp-text-container {
|
||||
text-align: center;
|
||||
max-width: 600px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.mcp-heading {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.mcp-description {
|
||||
font-size: 14px;
|
||||
color: var(--vscode-descriptionForeground);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.mcp-button {
|
||||
background-color: var(--vscode-button-background);
|
||||
color: var(--vscode-button-foreground);
|
||||
border: none;
|
||||
padding: 8px 16px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
transition: background-color 0.2s;
|
||||
}
|
||||
|
||||
.mcp-button:hover {
|
||||
background-color: var(--vscode-button-hoverBackground);
|
||||
}
|
||||
|
||||
.mcp-count {
|
||||
margin-top: 30px;
|
||||
width: 100%;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
/* Responsive Styles */
|
||||
@media (max-width: 768px) {
|
||||
.features-section-container {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.plan-act-content {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.models-section-container {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.feature-row {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.feature-row {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.buttons-container {
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.primary-button,
|
||||
.secondary-button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
<svg width="1048" height="187" viewBox="0 0 1048 187" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M64.0535 186.531C51.9601 186.531 41.2428 184.279 31.9016 179.775C22.6439 175.271 15.221 169.141 9.63304 161.385C4.12845 153.545 0.959134 144.704 0.125104 134.863L0 133.361H26.7724L26.8975 134.237C27.7315 139.658 29.8166 144.579 33.1527 148.999C36.5722 153.336 40.9509 156.798 46.2886 159.383C51.6264 161.885 57.5898 163.136 64.1786 163.136C71.7683 163.136 78.4822 161.51 84.3204 158.257C90.1586 155.004 94.7041 150.501 97.9568 144.746C101.21 138.991 102.836 132.402 102.836 124.979V124.729C102.836 117.39 101.168 110.884 97.8317 105.213C94.579 99.5414 90.0752 95.0794 84.3204 91.8267C78.5656 88.574 71.9768 86.9476 64.5539 86.9476C58.9659 86.9476 53.7949 87.7816 49.0409 89.4497C44.287 91.0343 40.0751 93.453 36.4054 96.7057C34.8207 98.1236 33.2778 99.7082 31.7765 101.46C30.3587 103.211 29.0659 105.088 27.8983 107.089H3.25272L12.1351 3.00251H119.85V26.6472H34.9041L29.3995 83.82H30.0251C32.694 79.7332 36.0718 76.272 40.1585 73.4363C44.3287 70.6006 48.9992 68.4738 54.1702 67.056C59.4246 65.5547 65.0126 64.8041 70.9342 64.8041C82.4438 64.8041 92.6607 67.3896 101.585 72.5606C110.509 77.6482 117.515 84.654 122.602 93.5781C127.773 102.502 130.359 112.719 130.359 124.229V124.479C130.359 136.656 127.523 147.415 121.852 156.756C116.18 166.097 108.34 173.395 98.3321 178.649C88.4071 183.904 76.9809 186.531 64.0535 186.531Z" fill="white"/>
|
||||
<path d="M218.933 186.531C204.587 186.531 192.244 182.736 181.902 175.146C171.643 167.557 163.762 156.798 158.257 142.869C152.753 128.941 150 112.427 150 93.3279V93.0777C150 73.9784 152.753 57.4646 158.257 43.5363C163.762 29.6081 171.643 18.8908 181.902 11.3845C192.244 3.79483 204.587 0 218.933 0C233.278 0 245.58 3.79483 255.839 11.3845C266.181 18.8908 274.104 29.6081 279.608 43.5363C285.196 57.4646 287.99 73.9784 287.99 93.0777V93.3279C287.99 112.427 285.196 128.941 279.608 142.869C274.104 156.798 266.181 167.557 255.839 175.146C245.58 182.736 233.278 186.531 218.933 186.531ZM218.933 163.011C227.523 163.011 234.821 160.217 240.826 154.629C246.914 149.041 251.543 141.034 254.713 130.609C257.965 120.184 259.592 107.757 259.592 93.3279V93.0777C259.592 78.649 257.965 66.2637 254.713 55.9217C251.543 45.4963 246.914 37.4896 240.826 31.9016C234.821 26.3136 227.523 23.5196 218.933 23.5196C210.342 23.5196 203.003 26.3136 196.914 31.9016C190.909 37.4896 186.322 45.4963 183.153 55.9217C179.984 66.2637 178.399 78.649 178.399 93.0777V93.3279C178.399 107.757 179.984 120.184 183.153 130.609C186.322 141.034 190.909 149.041 196.914 154.629C203.003 160.217 210.342 163.011 218.933 163.011Z" fill="white"/>
|
||||
<path d="M313.512 122.602V97.9568H443.745V122.602H313.512ZM366.306 173.019V47.5397H390.826V173.019H366.306Z" fill="white"/>
|
||||
<path d="M526.44 183.528V3.00251H558.842L617.265 146.998H618.016L676.44 3.00251H708.967V183.528H683.321V50.4171H670.435L699.709 8.00668L628.024 183.528H607.257L535.697 8.00668L564.972 50.4171H552.086V183.528H526.44Z" fill="white"/>
|
||||
<path d="M819.559 186.531C802.545 186.531 787.741 182.736 775.147 175.146C762.637 167.557 752.962 156.798 746.123 142.869C739.284 128.858 735.864 112.302 735.864 93.2028V93.0777C735.864 73.9784 739.284 57.4646 746.123 43.5363C752.962 29.6081 762.637 18.8908 775.147 11.3845C787.658 3.79483 802.462 0 819.559 0C832.82 0 844.789 2.54379 855.464 7.63137C866.14 12.719 874.939 19.7665 881.861 28.774C888.784 37.7815 893.162 48.2486 894.997 60.1752L895.122 61.4263H867.224L866.473 58.9242C864.555 51.8349 861.428 45.7465 857.091 40.6589C852.837 35.5714 847.541 31.6931 841.202 29.0242C834.947 26.2719 827.733 24.8958 819.559 24.8958C808.383 24.8958 798.667 27.6898 790.41 33.2778C782.236 38.8658 775.898 46.7474 771.394 56.9225C766.89 67.0977 764.638 79.1494 764.638 93.0777V93.2028C764.638 107.048 766.89 119.141 771.394 129.483C775.898 139.742 782.278 147.665 790.535 153.253C798.792 158.841 808.467 161.635 819.559 161.635C827.566 161.635 834.697 160.301 840.952 157.632C847.291 154.879 852.67 150.876 857.091 145.622C861.511 140.367 864.805 133.945 866.974 126.355L867.349 125.104H895.247L894.997 126.355C893.162 138.366 888.784 148.916 881.861 158.007C875.022 167.014 866.265 174.02 855.589 179.024C844.914 184.029 832.904 186.531 819.559 186.531Z" fill="white"/>
|
||||
<path d="M934.78 121.852V98.3321H981.069C993.163 98.3321 1002.55 95.2045 1009.22 88.9493C1015.97 82.6106 1019.35 73.8533 1019.35 62.6773V62.4271C1019.35 51.0843 1015.97 42.2853 1009.22 36.0301C1002.55 29.7749 993.163 26.6472 981.069 26.6472H934.78V3.00251H988.075C999.918 3.00251 1010.3 5.5046 1019.23 10.5088C1028.23 15.4295 1035.28 22.352 1040.37 31.2761C1045.46 40.1168 1048 50.4171 1048 62.1769V62.4271C1048 74.1869 1045.46 84.5706 1040.37 93.5781C1035.28 102.502 1028.23 109.466 1019.23 114.471C1010.3 119.391 999.918 121.852 988.075 121.852H934.78ZM920.769 183.528V3.00251H948.792V183.528H920.769Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.8 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 7H13" stroke="#006FEE" stroke-width="2.33333" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 214 B |
|
After Width: | Height: | Size: 225 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="11" height="20" viewBox="0 0 11 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.8648 9.99911L10.6222 18.7565L9.37867 20L-0.000461927 10.6209V9.37736L9.37867 -0.00177104L10.6222 1.24174L1.8648 9.99911Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 292 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="26" height="28" viewBox="0 0 26 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.14 0.28L25.7 6.88L26 7.6V27L25 28H18V26H24V10H17L16 9V2H4V10H2V1L3 0H18.44L19.14 0.28ZM18 8H24L18 2V8ZM15 12H1L0 13V27L1 28H15L16 27V13L15 12ZM14 26H2V14H14V26ZM12 17V23H9.99999V19.414L4.70799 24.708L3.29199 23.292L8.58599 18H5.05999V16H11L12 17Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 419 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="19" height="16" viewBox="0 0 19 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1.20874 8.03249L5.75511 13.5892L17.8788 1.08664" stroke="white" stroke-width="1.5"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 198 B |
|
After Width: | Height: | Size: 1.1 MiB |
|
After Width: | Height: | Size: 55 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="28" height="22" viewBox="0 0 28 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M0 8.38L13.28 21.66H14.72L28 8.38V6.94L21.36 0.3L20.64 0H7.36L6.64 0.3L0 6.94V8.38ZM14 19.5L2.16 7.66L7.78 2H20.22L25.84 7.66L14 19.5ZM14 4.04004H19.38L23 7.66004L14 16.46V4.04004Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 349 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 7H13" stroke="#F31260" stroke-width="2.33333" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 214 B |
|
After Width: | Height: | Size: 234 KiB |
|
After Width: | Height: | Size: 970 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="122" height="128" viewBox="0 0 122 128" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M121.441 72.2998L113.772 56.859V47.9663C113.772 33.2261 101.976 21.2884 87.4275 21.2884H74.3218C75.2704 19.3347 75.7914 17.1385 75.7914 14.8211C75.7914 6.62905 69.2185 0 61.096 0C52.9735 0 46.4006 6.62905 46.4006 14.8211C46.4006 17.1385 46.9217 19.3347 47.8702 21.2884H34.7646C20.2162 21.2884 8.41978 33.2261 8.41978 47.9663V56.859L0.591155 72.2594C-0.197052 73.8088 -0.197052 75.6547 0.591155 77.2042L8.41978 92.4295V101.322C8.41978 116.062 20.2162 128 34.7646 128H87.4275C101.976 128 113.772 116.062 113.772 101.322V92.4295L121.427 77.1503C122.189 75.6278 122.189 73.8358 121.441 72.2998ZM53.0804 84.8842C53.0804 91.5806 47.6965 97.0105 41.0569 97.0105C34.4172 97.0105 29.0334 91.5806 29.0334 84.8842V63.3263C29.0334 56.6299 34.4172 51.2 41.0569 51.2C47.6965 51.2 53.0804 56.6299 53.0804 63.3263V84.8842ZM91.8227 84.8842C91.8227 91.5806 86.4389 97.0105 79.7992 97.0105C73.1596 97.0105 67.7757 91.5806 67.7757 84.8842V63.3263C67.7757 56.6299 73.1596 51.2 79.7992 51.2C86.4389 51.2 91.8227 56.6299 91.8227 63.3263V84.8842Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 200 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1 7H13" stroke="#F5A524" stroke-width="2.33333" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 214 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="25" height="25" viewBox="0 0 25 25" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.8572 12.5L0 25V0L17.8572 12.5ZM1.99311 21.1699L14.3843 12.5L1.99311 3.83016V21.1699ZM7.01095 25V22.5375L21.3953 12.5L7.01095 2.46254V0L24.8681 12.5L7.01095 25Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 332 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="28" height="28" viewBox="0 0 28 28" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M26.982 0C19.7852 0.00900726 13.6746 3.96537 9.31269 8H1L0 9V15L0.294 15.708L2.27591 17.6899L2.27799 17.708L10.278 25.708L10.296 25.7101L12.294 27.7081L13 28.0001H19L20 27.0001V18.692C24.0381 14.3368 27.992 8.22601 27.984 1L26.982 0ZM2 10H7.28614C5.18494 12.208 3.6634 14.2399 2.83687 15.4219L2 14.586V10ZM13.4 26.0001L12.561 25.1531C13.7452 24.331 15.7799 22.8169 17.99 20.7222V26.0001H13.4ZM11.114 23.712L4.27199 16.874C6.25599 14 14.758 2.71 25.956 2.032C25.304 13.256 13.982 21.738 11.114 23.712ZM6 28V26H2V22H0V28H6ZM19.4951 12.6657C19.8243 12.1726 20 11.5929 20 11C20 10.6052 19.9221 10.2143 19.7707 9.84965C19.6193 9.48502 19.3974 9.15386 19.1178 8.87515C18.8382 8.59645 18.5063 8.37568 18.1411 8.2255C17.776 8.07533 17.3848 7.9987 16.99 8.00002C16.3971 8.00199 15.8181 8.17962 15.326 8.51046C14.834 8.84131 14.451 9.31053 14.2255 9.85888C14 10.4072 13.942 11.0101 14.0589 11.5914C14.1758 12.1727 14.4623 12.7063 14.8822 13.1248C15.3022 13.5434 15.8367 13.8281 16.4184 13.9431C17.0001 14.058 17.6028 13.998 18.1504 13.7707C18.6979 13.5433 19.1659 13.1588 19.4951 12.6657Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="26" height="27" viewBox="0 0 26 27" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M25.26 12L22 4H24V2H14V0H12V2H2V4H4L0.76 12H0V14H0.3C0.612778 14.9958 1.24551 15.8606 2.1 16.46C2.9433 17.0715 3.95832 17.4008 5 17.4008C6.04168 17.4008 7.0567 17.0715 7.9 16.46C8.75472 15.8563 9.39277 14.9939 9.72 14H10V12H9.1L5.76 4H12V20H8L7.22 20.36L3.22 25.38L4 27H22L22.78 25.38L18.78 20.36L18 20H14V4H20.26L16.92 12H16V14H16.3C16.6271 14.9909 17.2584 15.8534 18.104 16.4647C18.9496 17.0761 19.9665 17.4052 21.01 17.4052C22.0535 17.4052 23.0704 17.0761 23.916 16.4647C24.7616 15.8534 25.3929 14.9909 25.72 14H26V12H25.26ZM6.44 15.02C5.99893 15.2641 5.50408 15.3947 5 15.4C4.50189 15.3974 4.01284 15.2665 3.58 15.02C3.13862 14.7781 2.76675 14.4268 2.5 14H7.5C7.2355 14.4217 6.87151 14.7719 6.44 15.02ZM6.94 12H2.94L4.94 7.2L6.94 12ZM17.52 22L20 25H6L8.48 22H17.52ZM21.08 7.24L23.08 12.04H19.08L21.08 7.24ZM22.44 15.06C22.0027 15.3134 21.5054 15.4447 21 15.44C20.5006 15.4471 20.0091 15.3156 19.58 15.06C19.138 14.8013 18.7669 14.4371 18.5 14H23.5C23.2521 14.445 22.885 14.8121 22.44 15.06Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="27" height="27" viewBox="0 0 27 27" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.7866 27.0006H14.214L17.672 23.5426H22.4972L23.5024 22.5374V17.672L27.0006 14.214V12.7866L23.5627 9.32859V4.42304L22.5575 3.43791H17.672L14.214 0H12.7866L9.42911 3.43791H4.46325L3.3977 4.44314V9.32859L0 12.7866V14.214L3.3977 17.672V22.5374L4.46325 23.5426H9.42911L12.7866 27.0006ZM9.75079 21.5321H5.40817V17.2498L5.16691 16.5462L2.1311 13.4903L5.1066 10.4544L5.40817 9.75079V5.44838H9.75079L10.4746 5.16691L13.4501 2.1311L16.5462 5.16691L17.2498 5.44838H21.4919V9.75079L21.8337 10.4544L24.8896 13.4903L21.7734 16.5462L21.4919 17.2498V21.5321H17.2498L16.4859 21.8337L13.4501 24.8695L10.4746 21.8136L9.75079 21.5321ZM10.8968 18.476H12.3243L19.9036 10.8967L18.4762 9.46924L11.6206 16.3449L8.84607 13.5703L7.41864 14.9977L10.8968 18.476Z" fill="#E2D5FF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 907 B |
@@ -0,0 +1,58 @@
|
||||
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useEffect, useState } from "react"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { validateApiConfiguration } from "@/utils/validate"
|
||||
import { vscode } from "@/utils/vscode"
|
||||
import ApiOptions from "@/components/settings/ApiOptions"
|
||||
// import { WebviewType } from "@shared/WebviewMessage" // Removed duplicate
|
||||
|
||||
import { Dispatch, SetStateAction } from "react" // Added import
|
||||
import { WebviewType } from "@shared/WebviewMessage"
|
||||
|
||||
interface ApiOptionsSectionProps {
|
||||
showApiOptions: boolean
|
||||
webviewType: WebviewType
|
||||
setShowApiOptions?: Dispatch<SetStateAction<boolean>> // Added prop
|
||||
}
|
||||
|
||||
const ApiOptionsSection = ({ showApiOptions, webviewType, setShowApiOptions }: ApiOptionsSectionProps) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const [apiErrorMessage, setApiErrorMessage] = useState<string | undefined>(undefined)
|
||||
|
||||
const disableLetsGoButton = apiErrorMessage != null
|
||||
|
||||
const handleSubmit = () => {
|
||||
vscode.postMessage({ type: "apiConfiguration", apiConfiguration })
|
||||
const isConfigValid = validateApiConfiguration(apiConfiguration) === undefined
|
||||
if (setShowApiOptions && isConfigValid) {
|
||||
setShowApiOptions(false)
|
||||
}
|
||||
if (webviewType === "sidebar" && isConfigValid) {
|
||||
// This message should be handled by the Controller,
|
||||
// which can then send an appropriate ExtensionMessage back to the webview
|
||||
// to hide the welcome screen.
|
||||
vscode.postMessage({ type: "showChatView" })
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setApiErrorMessage(validateApiConfiguration(apiConfiguration))
|
||||
}, [apiConfiguration])
|
||||
|
||||
if (!showApiOptions) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mt-4.5 mb-8">
|
||||
<div>
|
||||
<ApiOptions showModelOptions={false} />
|
||||
<VSCodeButton onClick={handleSubmit} disabled={disableLetsGoButton} className="mt-0.75">
|
||||
Let's go!
|
||||
</VSCodeButton>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default ApiOptionsSection
|
||||
@@ -0,0 +1,470 @@
|
||||
import { useState, useRef, useEffect, memo, Dispatch, SetStateAction } from "react"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { AccountServiceClient } from "@/services/grpc-client"
|
||||
import { EmptyRequest } from "@shared/proto/common"
|
||||
import ClineLogoWhite from "@/assets/ClineLogoWhite"
|
||||
|
||||
// Import CSS styles
|
||||
import "@/assets/css/styles.css"
|
||||
import { validateApiConfiguration } from "@/utils/validate" // Added import
|
||||
|
||||
const WelcomeTabView = ({ showWelcome }: { showWelcome: boolean }) => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const isApiConfigValid = validateApiConfiguration(apiConfiguration) === undefined
|
||||
const [activeTab, setActiveTab] = useState("Key Features")
|
||||
const inputFieldRef = useRef<HTMLDivElement>(null)
|
||||
const inputRef = useRef<HTMLInputElement>(null)
|
||||
const [inputValue, setInputValue] = useState("")
|
||||
const [showPlaceholder, setShowPlaceholder] = useState(true)
|
||||
|
||||
const handleLogin = () => {
|
||||
AccountServiceClient.accountLoginClicked(EmptyRequest.create()).catch((err) =>
|
||||
console.error("Failed to get login URL:", err),
|
||||
)
|
||||
}
|
||||
|
||||
const handleTabClick = (tabName: string) => {
|
||||
setActiveTab(tabName)
|
||||
}
|
||||
|
||||
const handleInputFieldClick = () => {
|
||||
setShowPlaceholder(false)
|
||||
inputRef.current?.focus()
|
||||
}
|
||||
|
||||
const handleInputBlur = () => {
|
||||
if (!inputValue) {
|
||||
setShowPlaceholder(true)
|
||||
}
|
||||
}
|
||||
|
||||
const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setInputValue(e.target.value)
|
||||
}
|
||||
|
||||
const handleCreateProject = (model: string) => {
|
||||
console.log(`Creating project with ${model} model`)
|
||||
// Implement project creation logic
|
||||
}
|
||||
|
||||
// Equivalent to document.addEventListener("DOMContentLoaded", ...)
|
||||
useEffect(() => {
|
||||
// No need to implement DOM manipulation here as we're using React state
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="home">
|
||||
<div className="main-container">
|
||||
{/* Account Info */}
|
||||
<div className="account-info">
|
||||
<ClineLogoWhite className="vector-icon" />
|
||||
|
||||
<div className="welcome-message-container">
|
||||
<h1 className="welcome-message">Get Started on Cline</h1>
|
||||
<p className="description">Let's start and learn the basics of Cline</p>
|
||||
</div>
|
||||
|
||||
<div className="buttons-container">
|
||||
<button className="primary-button" onClick={handleLogin}>
|
||||
Let's Create your Account!
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Conditionally render features-container */}
|
||||
{isApiConfigValid && !showWelcome ? (
|
||||
<div className="features-container">
|
||||
<div className="feature-row">
|
||||
<div
|
||||
className="feature-card"
|
||||
style={{
|
||||
transition: "all 0.3s ease",
|
||||
cursor: "pointer",
|
||||
}}>
|
||||
<div className="feature-icon-container">
|
||||
<div className="feature-icon feature-icon-1"></div>
|
||||
<div className="feature-title">Snake game</div>
|
||||
</div>
|
||||
<div className="feature-description">> Build a Snake game...</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="feature-card"
|
||||
style={{
|
||||
transition: "all 0.3s ease",
|
||||
cursor: "pointer",
|
||||
}}>
|
||||
<div className="feature-icon-container">
|
||||
<div className="feature-icon feature-icon-2"></div>
|
||||
<div className="feature-title">To-do App</div>
|
||||
</div>
|
||||
<div className="feature-description">> Generate a to-do App...</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="feature-card"
|
||||
style={{
|
||||
transition: "all 0.3s ease",
|
||||
cursor: "pointer",
|
||||
}}>
|
||||
<div className="feature-icon-container">
|
||||
<div className="feature-icon feature-icon-3"></div>
|
||||
<div className="feature-title">Script</div>
|
||||
</div>
|
||||
<div className="feature-description">> Write a script and then...</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="feature-card"
|
||||
style={{
|
||||
transition: "all 0.3s ease",
|
||||
cursor: "pointer",
|
||||
}}>
|
||||
<div className="feature-icon-container">
|
||||
<div className="feature-icon feature-icon-4"></div>
|
||||
<div className="feature-title">New Feature</div>
|
||||
</div>
|
||||
<div className="feature-description">> Read my code & suggest...</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="footer">
|
||||
<div
|
||||
className="input-field"
|
||||
ref={inputFieldRef}
|
||||
onClick={handleInputFieldClick}
|
||||
style={{
|
||||
position: "relative",
|
||||
cursor: "text",
|
||||
}}>
|
||||
{showPlaceholder && <div className="input-placeholder">Type your prompt here...</div>}
|
||||
{!showPlaceholder && (
|
||||
<input
|
||||
ref={inputRef}
|
||||
type="text"
|
||||
value={inputValue}
|
||||
onChange={handleInputChange}
|
||||
onBlur={handleInputBlur}
|
||||
style={{
|
||||
width: "100%",
|
||||
background: "transparent",
|
||||
border: "none",
|
||||
outline: "none",
|
||||
color: "#FFFFFF",
|
||||
fontSize: "14px",
|
||||
fontFamily: "SF Pro, Inter, sans-serif",
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
<div className="input-actions-container">
|
||||
<div className="input-actions">
|
||||
<button
|
||||
className="action-button action-button-secondary"
|
||||
style={{
|
||||
transition: "all 0.2s ease",
|
||||
opacity: 0.5,
|
||||
}}>
|
||||
<div className="action-icon action-icon-1"></div>
|
||||
<span className="action-text">Improve prompt</span>
|
||||
</button>
|
||||
|
||||
<button
|
||||
className="action-button action-button-primary"
|
||||
style={{
|
||||
transition: "all 0.2s ease",
|
||||
opacity: 0.5,
|
||||
}}>
|
||||
<div className="action-icon action-icon-2"></div>
|
||||
<span className="action-text">Start construction</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
{/* End of conditional rendering for features-container */}
|
||||
</div>
|
||||
|
||||
<div className="divider"></div>
|
||||
|
||||
{/* Features Section */}
|
||||
<div className="features-section-container">
|
||||
<div className="features-text-container">
|
||||
<h2 className="features-heading">Work better with the best features of Cline</h2>
|
||||
<p className="features-description">
|
||||
It's easy to lose control as they make rapid changes to your codebase. That's why we built safe
|
||||
features to make the control on your code.
|
||||
</p>
|
||||
|
||||
<div className="divider-dashed"></div>
|
||||
|
||||
<div className="features-tabs-container">
|
||||
<button
|
||||
className={`tab-button ${activeTab === "Key Features" ? "active-tab" : ""}`}
|
||||
onClick={() => handleTabClick("Key Features")}>
|
||||
Key Features
|
||||
</button>
|
||||
<button
|
||||
className={`tab-button ${activeTab === "Tools" ? "active-tab" : ""}`}
|
||||
onClick={() => handleTabClick("Tools")}>
|
||||
Tools
|
||||
</button>
|
||||
<button
|
||||
className={`tab-button ${activeTab === "Checkpoints" ? "active-tab" : ""}`}
|
||||
onClick={() => handleTabClick("Checkpoints")}>
|
||||
Checkpoints
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{activeTab === "Key Features" && (
|
||||
<div className="feature-content">
|
||||
<div className="feature-selected">
|
||||
<div className="feature-check-icon">✓</div>
|
||||
<div className="feature-info">
|
||||
<h3 className="feature-title">File Editing</h3>
|
||||
<p className="feature-subtitle">Cline can write your code for you</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="feature-buttons-container">
|
||||
<button className="feature-action-button">
|
||||
<div className="feature-action-icon button-icon-1"></div>
|
||||
Create new files
|
||||
</button>
|
||||
|
||||
<button className="feature-action-button">
|
||||
<div className="feature-action-icon button-icon-1"></div>
|
||||
Modify existing code
|
||||
</button>
|
||||
|
||||
<button className="feature-action-button">
|
||||
<div className="feature-action-icon button-icon-1"></div>
|
||||
Search and replace across files
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="feature-options">
|
||||
<div className="feature-option">
|
||||
<div className="feature-circle"></div>
|
||||
<span>Terminal Commands</span>
|
||||
</div>
|
||||
|
||||
<div className="feature-option">
|
||||
<div className="feature-circle"></div>
|
||||
<span>Code Analysis</span>
|
||||
</div>
|
||||
|
||||
<div className="feature-option">
|
||||
<div className="feature-circle"></div>
|
||||
<span>Browser Integration</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === "Tools" && (
|
||||
<div className="feature-content">
|
||||
<p className="feature-description">Cline provides powerful tools to help you code faster</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === "Checkpoints" && (
|
||||
<div className="feature-content">
|
||||
<p className="feature-description">Cline creates checkpoints to help you track changes</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<img alt="Feature Background" className="feature-bg" />
|
||||
|
||||
<div className="divider"></div>
|
||||
|
||||
{/* Models Section */}
|
||||
<div className="models-container">
|
||||
<h2 className="models-heading">Top 3 models for coding</h2>
|
||||
|
||||
<div className="models-section-container">
|
||||
{/* Anthropic Model Card */}
|
||||
<div className="model-card">
|
||||
<div className="model-header">
|
||||
<div className="model-name">anthropic</div>
|
||||
<div className="model-badge best">Best</div>
|
||||
</div>
|
||||
|
||||
<div className="model-description">Leading model for agentic coding</div>
|
||||
|
||||
<div className="model-divider"></div>
|
||||
|
||||
<div className="model-image anthropic-model"></div>
|
||||
|
||||
<button className="model-button" onClick={() => handleCreateProject("anthropic")}>
|
||||
Create a new project
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Google Model Card */}
|
||||
<div className="model-card">
|
||||
<div className="model-header">
|
||||
<div className="model-name">google</div>
|
||||
<div className="model-badge trending">Trending</div>
|
||||
</div>
|
||||
|
||||
<div className="model-description">Large 1M context window, great value</div>
|
||||
|
||||
<div className="model-divider"></div>
|
||||
|
||||
<div className="model-image google-model"></div>
|
||||
|
||||
<button className="model-button" onClick={() => handleCreateProject("google")}>
|
||||
Create a new project
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Meta-Llama Model Card */}
|
||||
<div className="model-card">
|
||||
<div className="model-header">
|
||||
<div className="model-name">meta-llama</div>
|
||||
<div className="model-badge new">New</div>
|
||||
</div>
|
||||
|
||||
<div className="model-description">Efficient performance at lower cost</div>
|
||||
|
||||
<div className="model-divider"></div>
|
||||
|
||||
<div className="model-image meta-model"></div>
|
||||
|
||||
<button className="model-button" onClick={() => handleCreateProject("meta-llama")}>
|
||||
Create a new project
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="divider"></div>
|
||||
|
||||
{/* Plan/Act Mode Section */}
|
||||
<div className="plan-act-container">
|
||||
<h2 className="plan-act-heading">Plan/Act Mode</h2>
|
||||
<p className="plan-act-description">
|
||||
Switch between planning and execution modes to better control how Cline assists you. Plan mode helps you
|
||||
strategize while Act mode implements your solutions.
|
||||
</p>
|
||||
|
||||
<div className="divider-dashed"></div>
|
||||
|
||||
<div className="plan-act-content">
|
||||
{/* Plan Mode Column */}
|
||||
<div className="plan-mode-container">
|
||||
<div className="mode-header">
|
||||
<h3 className="mode-title">Plan Mode</h3>
|
||||
</div>
|
||||
<div className="mode-content">
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon plan-icon">
|
||||
<div className="line-icon plan-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Read files & Analysis</div>
|
||||
</div>
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon plan-icon">
|
||||
<div className="line-icon plan-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Strategy Development</div>
|
||||
</div>
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon plan-icon">
|
||||
<div className="line-icon plan-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Context Gathering</div>
|
||||
</div>
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon plan-icon">
|
||||
<div className="line-icon plan-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Requirements Analysis</div>
|
||||
</div>
|
||||
<div className="mode-item disabled">
|
||||
<div className="mode-icon plan-icon-disabled">
|
||||
<div className="line-icon disabled-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Code Modifications</div>
|
||||
</div>
|
||||
<div className="mode-item disabled">
|
||||
<div className="mode-icon plan-icon-disabled">
|
||||
<div className="line-icon disabled-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">File Creation/Deletion</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Act Mode Column */}
|
||||
<div className="act-mode-container">
|
||||
<div className="mode-header">
|
||||
<h3 className="mode-title">Act Mode</h3>
|
||||
</div>
|
||||
<div className="mode-content">
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon act-icon">
|
||||
<div className="line-icon act-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Read files & Analysis</div>
|
||||
</div>
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon act-icon">
|
||||
<div className="line-icon act-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Code Modifications</div>
|
||||
</div>
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon act-icon">
|
||||
<div className="line-icon act-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">File Creation/Deletion</div>
|
||||
</div>
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon act-icon">
|
||||
<div className="line-icon act-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Execute Commands</div>
|
||||
</div>
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon act-icon">
|
||||
<div className="line-icon act-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Run Tests</div>
|
||||
</div>
|
||||
<div className="mode-item">
|
||||
<div className="mode-icon act-icon">
|
||||
<div className="line-icon act-line"></div>
|
||||
</div>
|
||||
<div className="mode-text">Deploy Changes</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="divider"></div>
|
||||
|
||||
{/* MCP Servers Section */}
|
||||
<div className="mcp-servers-container">
|
||||
<div className="mcp-content-container">
|
||||
<div className="mcp-text-container">
|
||||
<h2 className="mcp-heading">The largest ecosystem of MCP Servers for VS Code</h2>
|
||||
<p className="mcp-description">
|
||||
The Model Context Protocol (MCP) allows seamless communication with locally running servers that
|
||||
extend Cline's functionality with additional tools and context-aware resources.
|
||||
</p>
|
||||
<button className="mcp-button">Add an MCP Server</button>
|
||||
</div>
|
||||
<div className="mcp-count"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default WelcomeTabView
|
||||
@@ -1,34 +1,24 @@
|
||||
import { VSCodeButton, VSCodeLink } from "@vscode/webview-ui-toolkit/react"
|
||||
import { useEffect, useState, memo } from "react"
|
||||
import { useExtensionState } from "@/context/ExtensionStateContext"
|
||||
import { validateApiConfiguration } from "@/utils/validate"
|
||||
import { vscode } from "@/utils/vscode"
|
||||
import ApiOptions from "@/components/settings/ApiOptions"
|
||||
import { memo, Dispatch, SetStateAction } from "react"
|
||||
import ClineLogoWhite from "@/assets/ClineLogoWhite"
|
||||
import { AccountServiceClient } from "@/services/grpc-client"
|
||||
import { EmptyRequest } from "@shared/proto/common"
|
||||
import ApiOptionsSection from "./ApiOptionsSection"
|
||||
import { WebviewType } from "@shared/WebviewMessage"
|
||||
|
||||
const WelcomeView = memo(() => {
|
||||
const { apiConfiguration } = useExtensionState()
|
||||
const [apiErrorMessage, setApiErrorMessage] = useState<string | undefined>(undefined)
|
||||
const [showApiOptions, setShowApiOptions] = useState(false)
|
||||
|
||||
const disableLetsGoButton = apiErrorMessage != null
|
||||
interface WelcomeViewProps {
|
||||
showApiOptions: boolean
|
||||
setShowApiOptions: Dispatch<SetStateAction<boolean>>
|
||||
webviewType: WebviewType
|
||||
}
|
||||
|
||||
const WelcomeView = memo(({ showApiOptions, setShowApiOptions, webviewType }: WelcomeViewProps) => {
|
||||
const handleLogin = () => {
|
||||
AccountServiceClient.accountLoginClicked(EmptyRequest.create()).catch((err) =>
|
||||
console.error("Failed to get login URL:", err),
|
||||
)
|
||||
}
|
||||
|
||||
const handleSubmit = () => {
|
||||
vscode.postMessage({ type: "apiConfiguration", apiConfiguration })
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setApiErrorMessage(validateApiConfiguration(apiConfiguration))
|
||||
}, [apiConfiguration])
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 p-0 flex flex-col">
|
||||
<div className="h-full px-5 overflow-auto">
|
||||
@@ -64,16 +54,11 @@ const WelcomeView = memo(() => {
|
||||
</VSCodeButton>
|
||||
)}
|
||||
|
||||
<div className="mt-4.5">
|
||||
{showApiOptions && (
|
||||
<div>
|
||||
<ApiOptions showModelOptions={false} />
|
||||
<VSCodeButton onClick={handleSubmit} disabled={disableLetsGoButton} className="mt-0.75">
|
||||
Let's go!
|
||||
</VSCodeButton>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<ApiOptionsSection
|
||||
showApiOptions={showApiOptions}
|
||||
webviewType={webviewType}
|
||||
setShowApiOptions={setShowApiOptions}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { useState, memo } from "react"
|
||||
import { WebviewType } from "@shared/WebviewMessage"
|
||||
import WelcomeView from "./WelcomeView"
|
||||
import WelcomeTabView from "./WelcomeTabView"
|
||||
|
||||
const WelcomeWrapper = memo(({ showWelcome }: { showWelcome: boolean }) => {
|
||||
const [showApiOptions, setShowApiOptions] = useState(false)
|
||||
|
||||
// Determine which welcome view to show based on webview type
|
||||
const webviewType = (document.querySelector('meta[name="webview-type"]')?.getAttribute("content") || "sidebar") as WebviewType
|
||||
|
||||
return (
|
||||
<>
|
||||
{webviewType === "sidebar" ? (
|
||||
<WelcomeView showApiOptions={showApiOptions} setShowApiOptions={setShowApiOptions} webviewType={webviewType} />
|
||||
) : (
|
||||
<WelcomeTabView showWelcome={showWelcome} />
|
||||
)}
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
export default WelcomeWrapper
|
||||
@@ -20,7 +20,6 @@ import { TelemetrySetting } from "@shared/TelemetrySetting"
|
||||
|
||||
interface ExtensionStateContextType extends ExtensionState {
|
||||
didHydrateState: boolean
|
||||
showWelcome: boolean
|
||||
theme: Record<string, string> | undefined
|
||||
openRouterModels: Record<string, ModelInfo>
|
||||
openAiModels: string[]
|
||||
@@ -32,6 +31,7 @@ interface ExtensionStateContextType extends ExtensionState {
|
||||
// View state
|
||||
showMcp: boolean
|
||||
mcpTab?: McpViewTab
|
||||
showWelcome: boolean
|
||||
|
||||
// Setters
|
||||
setApiConfiguration: (config: ApiConfiguration) => void
|
||||
@@ -41,6 +41,7 @@ interface ExtensionStateContextType extends ExtensionState {
|
||||
setPlanActSeparateModelsSetting: (value: boolean) => void
|
||||
setShellIntegrationTimeout: (value: number) => void
|
||||
setMcpServers: (value: McpServer[]) => void
|
||||
setShowWelcome: (value: boolean) => void
|
||||
|
||||
// Navigation
|
||||
setShowMcp: (value: boolean) => void
|
||||
@@ -74,8 +75,9 @@ export const ExtensionStateContextProvider: React.FC<{
|
||||
localWindsurfRulesToggles: {},
|
||||
shellIntegrationTimeout: 4000, // default timeout for shell integration
|
||||
})
|
||||
const [didHydrateState, setDidHydrateState] = useState(false)
|
||||
// UI state for welcome screen
|
||||
const [showWelcome, setShowWelcome] = useState(false)
|
||||
const [didHydrateState, setDidHydrateState] = useState(false)
|
||||
const [theme, setTheme] = useState<Record<string, string>>()
|
||||
const [filePaths, setFilePaths] = useState<string[]>([])
|
||||
const [openRouterModels, setOpenRouterModels] = useState<Record<string, ModelInfo>>({
|
||||
@@ -106,33 +108,6 @@ export const ExtensionStateContextProvider: React.FC<{
|
||||
: prevState.autoApprovalSettings,
|
||||
}
|
||||
})
|
||||
const config = message.state?.apiConfiguration
|
||||
const hasKey = config
|
||||
? [
|
||||
config.apiKey,
|
||||
config.openRouterApiKey,
|
||||
config.awsRegion,
|
||||
config.vertexProjectId,
|
||||
config.openAiApiKey,
|
||||
config.ollamaModelId,
|
||||
config.lmStudioModelId,
|
||||
config.liteLlmApiKey,
|
||||
config.geminiApiKey,
|
||||
config.openAiNativeApiKey,
|
||||
config.deepSeekApiKey,
|
||||
config.requestyApiKey,
|
||||
config.togetherApiKey,
|
||||
config.qwenApiKey,
|
||||
config.doubaoApiKey,
|
||||
config.mistralApiKey,
|
||||
config.vsCodeLmModelSelector,
|
||||
config.clineApiKey,
|
||||
config.asksageApiKey,
|
||||
config.xaiApiKey,
|
||||
config.sambanovaApiKey,
|
||||
].some((key) => key !== undefined)
|
||||
: false
|
||||
setShowWelcome(!hasKey)
|
||||
setDidHydrateState(true)
|
||||
break
|
||||
}
|
||||
@@ -196,6 +171,10 @@ export const ExtensionStateContextProvider: React.FC<{
|
||||
setTotalTasksSize(message.totalTasksSize ?? null)
|
||||
break
|
||||
}
|
||||
case "showWelcome": {
|
||||
setShowWelcome(true)
|
||||
break
|
||||
}
|
||||
}
|
||||
}, [])
|
||||
|
||||
@@ -208,7 +187,6 @@ export const ExtensionStateContextProvider: React.FC<{
|
||||
const contextValue: ExtensionStateContextType = {
|
||||
...state,
|
||||
didHydrateState,
|
||||
showWelcome,
|
||||
theme,
|
||||
openRouterModels,
|
||||
openAiModels,
|
||||
@@ -219,6 +197,7 @@ export const ExtensionStateContextProvider: React.FC<{
|
||||
totalTasksSize,
|
||||
showMcp,
|
||||
mcpTab,
|
||||
showWelcome,
|
||||
globalClineRulesToggles: state.globalClineRulesToggles || {},
|
||||
localClineRulesToggles: state.localClineRulesToggles || {},
|
||||
localCursorRulesToggles: state.localCursorRulesToggles || {},
|
||||
@@ -254,6 +233,7 @@ export const ExtensionStateContextProvider: React.FC<{
|
||||
shellIntegrationTimeout: value,
|
||||
})),
|
||||
setMcpServers: (mcpServers: McpServer[]) => setMcpServers(mcpServers),
|
||||
setShowWelcome,
|
||||
setShowMcp,
|
||||
setMcpTab,
|
||||
}
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
@config "../tailwind.config.js";
|
||||
|
||||
@config "../tailwind.config.js";
|
||||
|
||||
textarea:focus {
|
||||
outline: 1.5px solid var(--vscode-focusBorder, #007fd4);
|
||||
}
|
||||
|
||||