mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-09 22:31:08 +00:00
This commit is contained in:
parent
d1eecb9084
commit
9a5f6ce7ea
9 changed files with 137 additions and 22 deletions
|
|
@ -23,6 +23,7 @@ import {
|
|||
type TerminalActionPromptType,
|
||||
type HistoryItem,
|
||||
type CloudUserInfo,
|
||||
type MarketplaceItem,
|
||||
requestyDefaultModelId,
|
||||
openRouterDefaultModelId,
|
||||
glamaDefaultModelId,
|
||||
|
|
@ -37,7 +38,7 @@ import { Package } from "../../shared/package"
|
|||
import { findLast } from "../../shared/array"
|
||||
import { supportPrompt } from "../../shared/support-prompt"
|
||||
import { GlobalFileNames } from "../../shared/globalFileNames"
|
||||
import { ExtensionMessage } from "../../shared/ExtensionMessage"
|
||||
import { ExtensionMessage, MarketplaceInstalledMetadata } from "../../shared/ExtensionMessage"
|
||||
import { Mode, defaultModeSlug } from "../../shared/modes"
|
||||
import { experimentDefault, experiments, EXPERIMENT_IDS } from "../../shared/experiments"
|
||||
import { formatLanguage } from "../../shared/language"
|
||||
|
|
@ -1254,6 +1255,46 @@ export class ClineProvider
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches marketplace data on demand to avoid blocking main state updates
|
||||
*/
|
||||
async fetchMarketplaceData() {
|
||||
try {
|
||||
const [marketplaceItems, marketplaceInstalledMetadata] = await Promise.all([
|
||||
this.marketplaceManager.getCurrentItems().catch((error) => {
|
||||
console.error("Failed to fetch marketplace items:", error)
|
||||
return [] as MarketplaceItem[]
|
||||
}),
|
||||
this.marketplaceManager.getInstallationMetadata().catch((error) => {
|
||||
console.error("Failed to fetch installation metadata:", error)
|
||||
return { project: {}, global: {} } as MarketplaceInstalledMetadata
|
||||
}),
|
||||
])
|
||||
|
||||
// Send marketplace data separately
|
||||
this.postMessageToWebview({
|
||||
type: "marketplaceData",
|
||||
marketplaceItems: marketplaceItems || [],
|
||||
marketplaceInstalledMetadata: marketplaceInstalledMetadata || { project: {}, global: {} },
|
||||
})
|
||||
} catch (error) {
|
||||
console.error("Failed to fetch marketplace data:", error)
|
||||
// Send empty data on error to prevent UI from hanging
|
||||
this.postMessageToWebview({
|
||||
type: "marketplaceData",
|
||||
marketplaceItems: [],
|
||||
marketplaceInstalledMetadata: { project: {}, global: {} },
|
||||
})
|
||||
|
||||
// Show user-friendly error notification for network issues
|
||||
if (error instanceof Error && error.message.includes("timeout")) {
|
||||
vscode.window.showWarningMessage(
|
||||
"Marketplace data could not be loaded due to network restrictions. Core functionality remains available.",
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if there is a file-based system prompt override for the given mode
|
||||
*/
|
||||
|
|
@ -1342,21 +1383,12 @@ export class ClineProvider
|
|||
const allowedCommands = vscode.workspace.getConfiguration(Package.name).get<string[]>("allowedCommands") || []
|
||||
const cwd = this.cwd
|
||||
|
||||
// Fetch marketplace data
|
||||
let marketplaceItems: any[] = []
|
||||
let marketplaceInstalledMetadata: any = { project: {}, global: {} }
|
||||
|
||||
marketplaceItems = (await this.marketplaceManager.getCurrentItems()) || []
|
||||
marketplaceInstalledMetadata = await this.marketplaceManager.getInstallationMetadata()
|
||||
|
||||
// Check if there's a system prompt override for the current mode
|
||||
const currentMode = mode ?? defaultModeSlug
|
||||
const hasSystemPromptOverride = await this.hasFileBasedSystemPromptOverride(currentMode)
|
||||
|
||||
return {
|
||||
version: this.context.extension?.packageJSON?.version ?? "",
|
||||
marketplaceItems,
|
||||
marketplaceInstalledMetadata,
|
||||
apiConfiguration,
|
||||
customInstructions,
|
||||
alwaysAllowReadOnly: alwaysAllowReadOnly ?? false,
|
||||
|
|
|
|||
|
|
@ -1508,6 +1508,12 @@ export const webviewMessageHandler = async (
|
|||
break
|
||||
}
|
||||
|
||||
case "fetchMarketplaceData": {
|
||||
// Fetch marketplace data on demand
|
||||
await provider.fetchMarketplaceData()
|
||||
break
|
||||
}
|
||||
|
||||
case "installMarketplaceItem": {
|
||||
if (marketplaceManager && message.mpItem && message.mpInstallOptions) {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,12 @@ import { Mode } from "./modes"
|
|||
import { RouterModels } from "./api"
|
||||
import type { MarketplaceItem } from "@roo-code/types"
|
||||
|
||||
// Type for marketplace installed metadata
|
||||
export interface MarketplaceInstalledMetadata {
|
||||
project: Record<string, { type: string }>
|
||||
global: Record<string, { type: string }>
|
||||
}
|
||||
|
||||
// Indexing status types
|
||||
export interface IndexingStatus {
|
||||
systemStatus: string
|
||||
|
|
@ -90,6 +96,7 @@ export interface ExtensionMessage {
|
|||
| "indexCleared"
|
||||
| "codebaseIndexConfig"
|
||||
| "marketplaceInstallResult"
|
||||
| "marketplaceData"
|
||||
text?: string
|
||||
payload?: any // Add a generic payload for now, can refine later
|
||||
action?:
|
||||
|
|
@ -136,6 +143,8 @@ export interface ExtensionMessage {
|
|||
userInfo?: CloudUserInfo
|
||||
organizationAllowList?: OrganizationAllowList
|
||||
tab?: string
|
||||
marketplaceItems?: MarketplaceItem[]
|
||||
marketplaceInstalledMetadata?: MarketplaceInstalledMetadata
|
||||
}
|
||||
|
||||
export type ExtensionState = Pick<
|
||||
|
|
|
|||
|
|
@ -167,6 +167,7 @@ export interface WebviewMessage {
|
|||
| "cancelMarketplaceInstall"
|
||||
| "removeInstalledMarketplaceItem"
|
||||
| "marketplaceInstallResult"
|
||||
| "fetchMarketplaceData"
|
||||
| "switchTab"
|
||||
text?: string
|
||||
tab?: "settings" | "history" | "mcp" | "modes" | "chat" | "marketplace" | "account"
|
||||
|
|
|
|||
|
|
@ -33,14 +33,10 @@ export function MarketplaceView({ stateManager, onDone }: MarketplaceViewProps)
|
|||
// a filter message with empty filters, which will cause the extension to
|
||||
// send back the full state including all marketplace items.
|
||||
if (!hasReceivedInitialState && state.allItems.length === 0) {
|
||||
// Send empty filter to trigger state update
|
||||
// Fetch marketplace data on demand
|
||||
// Note: isFetching is already true by default for initial load
|
||||
vscode.postMessage({
|
||||
type: "filterMarketplaceItems",
|
||||
filters: {
|
||||
type: "",
|
||||
search: "",
|
||||
tags: [],
|
||||
},
|
||||
type: "fetchMarketplaceData",
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ export class MarketplaceViewStateManager {
|
|||
return {
|
||||
allItems: [],
|
||||
displayItems: [], // Always initialize as empty array, not undefined
|
||||
isFetching: false,
|
||||
isFetching: true, // Start with loading state for initial load
|
||||
activeTab: "mcp",
|
||||
filters: {
|
||||
type: "",
|
||||
|
|
@ -148,8 +148,12 @@ export class MarketplaceViewStateManager {
|
|||
public async transition(transition: ViewStateTransition): Promise<void> {
|
||||
switch (transition.type) {
|
||||
case "FETCH_ITEMS": {
|
||||
// Fetch functionality removed - data comes automatically from extension
|
||||
// No manual fetching needed since we removed caching
|
||||
// Set fetching state to show loading indicator
|
||||
this.state = {
|
||||
...this.state,
|
||||
isFetching: true,
|
||||
}
|
||||
this.notifyStateChange()
|
||||
break
|
||||
}
|
||||
|
||||
|
|
@ -225,12 +229,21 @@ export class MarketplaceViewStateManager {
|
|||
tags: filters.tags !== undefined ? filters.tags : this.state.filters.tags,
|
||||
}
|
||||
|
||||
// Update state
|
||||
// Update filters first
|
||||
this.state = {
|
||||
...this.state,
|
||||
filters: updatedFilters,
|
||||
}
|
||||
|
||||
// Apply filters to displayItems with the updated filters
|
||||
const newDisplayItems = this.filterItems(this.state.allItems)
|
||||
|
||||
// Update state with filtered items
|
||||
this.state = {
|
||||
...this.state,
|
||||
displayItems: newDisplayItems,
|
||||
}
|
||||
|
||||
// Send filter message
|
||||
vscode.postMessage({
|
||||
type: "filterMarketplaceItems",
|
||||
|
|
@ -341,5 +354,28 @@ export class MarketplaceViewStateManager {
|
|||
void this.transition({ type: "FETCH_ITEMS" })
|
||||
}
|
||||
}
|
||||
|
||||
// Handle marketplace data updates (fetched on demand)
|
||||
if (message.type === "marketplaceData") {
|
||||
const marketplaceItems = message.marketplaceItems
|
||||
|
||||
if (marketplaceItems !== undefined) {
|
||||
// Always use the marketplace items from the extension when they're provided
|
||||
// This ensures fresh data is always displayed
|
||||
const items = [...marketplaceItems]
|
||||
const newDisplayItems = this.isFilterActive() ? this.filterItems(items) : items
|
||||
|
||||
// Update state in a single operation
|
||||
this.state = {
|
||||
...this.state,
|
||||
isFetching: false,
|
||||
allItems: items,
|
||||
displayItems: newDisplayItems,
|
||||
}
|
||||
}
|
||||
|
||||
// Notify state change
|
||||
this.notifyStateChange()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -136,6 +136,11 @@ export const MarketplaceInstallModal: React.FC<MarketplaceInstallModalProps> = (
|
|||
// Installation succeeded - show success state
|
||||
setInstallationComplete(true)
|
||||
setValidationError(null)
|
||||
|
||||
// Request fresh marketplace data to update installed status
|
||||
vscode.postMessage({
|
||||
type: "fetchMarketplaceData",
|
||||
})
|
||||
} else {
|
||||
// Installation failed - show error
|
||||
setValidationError(message.error || "Installation failed")
|
||||
|
|
|
|||
|
|
@ -94,6 +94,11 @@ export const MarketplaceItemCard: React.FC<MarketplaceItemCardProps> = ({ item,
|
|||
mpItem: item,
|
||||
mpInstallOptions: { target },
|
||||
})
|
||||
|
||||
// Request fresh marketplace data to update installed status
|
||||
vscode.postMessage({
|
||||
type: "fetchMarketplaceData",
|
||||
})
|
||||
}}>
|
||||
{t("marketplace:items.card.remove")}
|
||||
</Button>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import {
|
|||
ORGANIZATION_ALLOW_ALL,
|
||||
} from "@roo-code/types"
|
||||
|
||||
import { ExtensionMessage, ExtensionState } from "@roo/ExtensionMessage"
|
||||
import { ExtensionMessage, ExtensionState, MarketplaceInstalledMetadata } from "@roo/ExtensionMessage"
|
||||
import { findLastIndex } from "@roo/array"
|
||||
import { McpServer } from "@roo/mcp"
|
||||
import { checkExistKey } from "@roo/checkExistApiConfig"
|
||||
|
|
@ -42,6 +42,8 @@ export interface ExtensionStateContextType extends ExtensionState {
|
|||
setCondensingApiConfigId: (value: string) => void
|
||||
customCondensingPrompt?: string
|
||||
setCustomCondensingPrompt: (value: string) => void
|
||||
marketplaceItems?: any[]
|
||||
marketplaceInstalledMetadata?: MarketplaceInstalledMetadata
|
||||
setApiConfiguration: (config: ProviderSettings) => void
|
||||
setCustomInstructions: (value?: string) => void
|
||||
setAlwaysAllowReadOnly: (value: boolean) => void
|
||||
|
|
@ -217,6 +219,11 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
const [mcpServers, setMcpServers] = useState<McpServer[]>([])
|
||||
const [currentCheckpoint, setCurrentCheckpoint] = useState<string>()
|
||||
const [extensionRouterModels, setExtensionRouterModels] = useState<RouterModels | undefined>(undefined)
|
||||
const [marketplaceItems, setMarketplaceItems] = useState<any[]>([])
|
||||
const [marketplaceInstalledMetadata, setMarketplaceInstalledMetadata] = useState<MarketplaceInstalledMetadata>({
|
||||
project: {},
|
||||
global: {},
|
||||
})
|
||||
|
||||
const setListApiConfigMeta = useCallback(
|
||||
(value: ProviderSettingsEntry[]) => setState((prevState) => ({ ...prevState, listApiConfigMeta: value })),
|
||||
|
|
@ -242,6 +249,13 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
setState((prevState) => mergeExtensionState(prevState, newState))
|
||||
setShowWelcome(!checkExistKey(newState.apiConfiguration))
|
||||
setDidHydrateState(true)
|
||||
// Handle marketplace data if present in state message
|
||||
if (newState.marketplaceItems !== undefined) {
|
||||
setMarketplaceItems(newState.marketplaceItems)
|
||||
}
|
||||
if (newState.marketplaceInstalledMetadata !== undefined) {
|
||||
setMarketplaceInstalledMetadata(newState.marketplaceInstalledMetadata)
|
||||
}
|
||||
break
|
||||
}
|
||||
case "theme": {
|
||||
|
|
@ -288,6 +302,15 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
setExtensionRouterModels(message.routerModels)
|
||||
break
|
||||
}
|
||||
case "marketplaceData": {
|
||||
if (message.marketplaceItems !== undefined) {
|
||||
setMarketplaceItems(message.marketplaceItems)
|
||||
}
|
||||
if (message.marketplaceInstalledMetadata !== undefined) {
|
||||
setMarketplaceInstalledMetadata(message.marketplaceInstalledMetadata)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
[setListApiConfigMeta],
|
||||
|
|
@ -320,6 +343,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
screenshotQuality: state.screenshotQuality,
|
||||
routerModels: extensionRouterModels,
|
||||
cloudIsAuthenticated: state.cloudIsAuthenticated ?? false,
|
||||
marketplaceItems,
|
||||
marketplaceInstalledMetadata,
|
||||
setExperimentEnabled: (id, enabled) =>
|
||||
setState((prevState) => ({ ...prevState, experiments: { ...prevState.experiments, [id]: enabled } })),
|
||||
setApiConfiguration,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue