fix(extensions): use provider-aware runtime copy

This commit is contained in:
777genius 2026-04-17 20:51:25 +03:00
parent 0287f83274
commit 767dfde4cb
4 changed files with 58 additions and 11 deletions

View file

@ -100,21 +100,21 @@ export const ExtensionStoreView = (): React.JSX.Element => {
label: 'Plugins',
icon: Puzzle,
description:
'Small add-ons for Claude. They give the app extra features and integrations you can install when you need them.',
'Small add-ons for the runtime. In multimodel mode they currently apply to Anthropic sessions when supported.',
},
{
value: 'mcp-servers' as const,
label: 'MCP Servers',
icon: Server,
description:
'Connections to outside tools and apps. They let Claude read data or do actions beyond this app.',
'Connections to outside tools and apps. They let the runtime read data or do actions beyond this app.',
},
{
value: 'skills' as const,
label: 'Skills',
icon: BookOpen,
description:
'Ready-made instructions for common jobs. They help Claude do specific tasks better and more consistently.',
'Ready-made instructions for common jobs. They help the runtime handle repeatable tasks more consistently.',
},
{
value: 'api-keys' as const,

View file

@ -385,10 +385,15 @@ export const McpServersPanel = ({
<div className="flex items-start gap-3 rounded-md border border-amber-500/30 bg-amber-500/5 px-4 py-3">
<AlertTriangle className="mt-0.5 size-4 shrink-0 text-amber-400" />
<div>
<p className="text-sm font-medium text-amber-300">Claude CLI not installed</p>
<p className="text-sm font-medium text-amber-300">
{cliStatus?.flavor === 'agent_teams_orchestrator'
? 'Configured runtime not available'
: 'Claude CLI not installed'}
</p>
<p className="mt-0.5 text-xs text-text-muted">
MCP health checks require Claude CLI. Go to the Dashboard to install it
automatically.
{cliStatus?.flavor === 'agent_teams_orchestrator'
? 'MCP health checks require the configured runtime. Go to the Dashboard to install or repair it.'
: 'MCP health checks require Claude CLI. Go to the Dashboard to install or repair it.'}
</p>
</div>
</div>

View file

@ -261,11 +261,11 @@ export const SkillsPanel = ({
<div className="min-w-0 flex-1 space-y-1 xl:max-w-2xl">
<div className="flex items-center gap-2">
<BookOpen className="size-4 text-text-muted" />
<h2 className="text-sm font-semibold text-text">Teach Claude repeatable work</h2>
<h2 className="text-sm font-semibold text-text">Teach repeatable work</h2>
</div>
<p className="max-w-2xl text-sm leading-5 text-text-muted">
Skills are reusable instructions that help Claude handle the same kind of task more
consistently.{' '}
Skills are reusable instructions that help the runtime handle the same kind of task
more consistently.{' '}
{projectPath
? `You are seeing skills for ${projectLabel ?? projectPath} plus your personal skills.`
: 'You are seeing only your personal skills right now.'}
@ -428,7 +428,7 @@ export const SkillsPanel = ({
<p className="text-xs text-text-muted">
{skillsSearchQuery
? 'Try a different search term or switch filters.'
: 'Create your first skill to teach Claude a repeatable workflow, or import one you already use.'}
: 'Create your first skill to teach a repeatable workflow, or import one you already use.'}
</p>
</div>
)}
@ -527,7 +527,7 @@ export const SkillsPanel = ({
<div>
<h3 className="text-sm font-semibold text-text">Personal skills</h3>
<p className="text-xs text-text-muted">
Habits and instructions you want Claude to remember everywhere.
Habits and instructions you want available everywhere.
</p>
</div>
<Badge variant="secondary" className="font-normal">

View file

@ -2,6 +2,8 @@ import React, { act } from 'react';
import { createRoot } from 'react-dom/client';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import { CLI_NOT_FOUND_MARKER } from '@shared/constants/cli';
interface StoreState {
mcpBrowseCatalog: Array<{
id: string;
@ -32,6 +34,9 @@ interface StoreState {
mcpDiagnosticsLastCheckedAt: number | null;
mcpDiagnosticsLastCheckedAtByProjectPath?: Record<string, number | null>;
runMcpDiagnostics: ReturnType<typeof vi.fn>;
cliStatus?: {
flavor?: 'claude' | 'agent_teams_orchestrator';
};
}
const storeState = {} as StoreState;
@ -139,6 +144,7 @@ describe('McpServersPanel initial browse loading', () => {
storeState.mcpDiagnosticsLastCheckedAt = null;
storeState.mcpDiagnosticsLastCheckedAtByProjectPath = undefined;
storeState.runMcpDiagnostics = vi.fn();
storeState.cliStatus = undefined;
});
afterEach(() => {
@ -267,4 +273,40 @@ describe('McpServersPanel initial browse loading', () => {
await Promise.resolve();
});
});
it('uses runtime-aware missing-runtime copy for multimodel diagnostics failures', async () => {
storeState.mcpDiagnosticsError = `${CLI_NOT_FOUND_MARKER}: missing runtime`;
storeState.cliStatus = {
flavor: 'agent_teams_orchestrator',
};
const host = document.createElement('div');
document.body.appendChild(host);
const root = createRoot(host);
await act(async () => {
root.render(
React.createElement(McpServersPanel, {
projectPath: null,
mcpSearchQuery: '',
mcpSearch: vi.fn(),
mcpSearchResults: [],
mcpSearchLoading: false,
mcpSearchWarnings: [],
selectedMcpServerId: null,
setSelectedMcpServerId: vi.fn(),
})
);
await Promise.resolve();
});
expect(host.textContent).toContain('Configured runtime not available');
expect(host.textContent).toContain('MCP health checks require the configured runtime');
expect(host.textContent).not.toContain('Claude CLI not installed');
await act(async () => {
root.unmount();
await Promise.resolve();
});
});
});