fix(extensions): use provider-aware runtime copy
This commit is contained in:
parent
0287f83274
commit
767dfde4cb
4 changed files with 58 additions and 11 deletions
|
|
@ -100,21 +100,21 @@ export const ExtensionStoreView = (): React.JSX.Element => {
|
||||||
label: 'Plugins',
|
label: 'Plugins',
|
||||||
icon: Puzzle,
|
icon: Puzzle,
|
||||||
description:
|
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,
|
value: 'mcp-servers' as const,
|
||||||
label: 'MCP Servers',
|
label: 'MCP Servers',
|
||||||
icon: Server,
|
icon: Server,
|
||||||
description:
|
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,
|
value: 'skills' as const,
|
||||||
label: 'Skills',
|
label: 'Skills',
|
||||||
icon: BookOpen,
|
icon: BookOpen,
|
||||||
description:
|
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,
|
value: 'api-keys' as const,
|
||||||
|
|
|
||||||
|
|
@ -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">
|
<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" />
|
<AlertTriangle className="mt-0.5 size-4 shrink-0 text-amber-400" />
|
||||||
<div>
|
<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">
|
<p className="mt-0.5 text-xs text-text-muted">
|
||||||
MCP health checks require Claude CLI. Go to the Dashboard to install it
|
{cliStatus?.flavor === 'agent_teams_orchestrator'
|
||||||
automatically.
|
? '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>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -261,11 +261,11 @@ export const SkillsPanel = ({
|
||||||
<div className="min-w-0 flex-1 space-y-1 xl:max-w-2xl">
|
<div className="min-w-0 flex-1 space-y-1 xl:max-w-2xl">
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center gap-2">
|
||||||
<BookOpen className="size-4 text-text-muted" />
|
<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>
|
</div>
|
||||||
<p className="max-w-2xl text-sm leading-5 text-text-muted">
|
<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
|
Skills are reusable instructions that help the runtime handle the same kind of task
|
||||||
consistently.{' '}
|
more consistently.{' '}
|
||||||
{projectPath
|
{projectPath
|
||||||
? `You are seeing skills for ${projectLabel ?? projectPath} plus your personal skills.`
|
? `You are seeing skills for ${projectLabel ?? projectPath} plus your personal skills.`
|
||||||
: 'You are seeing only your personal skills right now.'}
|
: 'You are seeing only your personal skills right now.'}
|
||||||
|
|
@ -428,7 +428,7 @@ export const SkillsPanel = ({
|
||||||
<p className="text-xs text-text-muted">
|
<p className="text-xs text-text-muted">
|
||||||
{skillsSearchQuery
|
{skillsSearchQuery
|
||||||
? 'Try a different search term or switch filters.'
|
? '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>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
@ -527,7 +527,7 @@ export const SkillsPanel = ({
|
||||||
<div>
|
<div>
|
||||||
<h3 className="text-sm font-semibold text-text">Personal skills</h3>
|
<h3 className="text-sm font-semibold text-text">Personal skills</h3>
|
||||||
<p className="text-xs text-text-muted">
|
<p className="text-xs text-text-muted">
|
||||||
Habits and instructions you want Claude to remember everywhere.
|
Habits and instructions you want available everywhere.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Badge variant="secondary" className="font-normal">
|
<Badge variant="secondary" className="font-normal">
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,8 @@ import React, { act } from 'react';
|
||||||
import { createRoot } from 'react-dom/client';
|
import { createRoot } from 'react-dom/client';
|
||||||
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
|
||||||
|
|
||||||
|
import { CLI_NOT_FOUND_MARKER } from '@shared/constants/cli';
|
||||||
|
|
||||||
interface StoreState {
|
interface StoreState {
|
||||||
mcpBrowseCatalog: Array<{
|
mcpBrowseCatalog: Array<{
|
||||||
id: string;
|
id: string;
|
||||||
|
|
@ -32,6 +34,9 @@ interface StoreState {
|
||||||
mcpDiagnosticsLastCheckedAt: number | null;
|
mcpDiagnosticsLastCheckedAt: number | null;
|
||||||
mcpDiagnosticsLastCheckedAtByProjectPath?: Record<string, number | null>;
|
mcpDiagnosticsLastCheckedAtByProjectPath?: Record<string, number | null>;
|
||||||
runMcpDiagnostics: ReturnType<typeof vi.fn>;
|
runMcpDiagnostics: ReturnType<typeof vi.fn>;
|
||||||
|
cliStatus?: {
|
||||||
|
flavor?: 'claude' | 'agent_teams_orchestrator';
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const storeState = {} as StoreState;
|
const storeState = {} as StoreState;
|
||||||
|
|
@ -139,6 +144,7 @@ describe('McpServersPanel initial browse loading', () => {
|
||||||
storeState.mcpDiagnosticsLastCheckedAt = null;
|
storeState.mcpDiagnosticsLastCheckedAt = null;
|
||||||
storeState.mcpDiagnosticsLastCheckedAtByProjectPath = undefined;
|
storeState.mcpDiagnosticsLastCheckedAtByProjectPath = undefined;
|
||||||
storeState.runMcpDiagnostics = vi.fn();
|
storeState.runMcpDiagnostics = vi.fn();
|
||||||
|
storeState.cliStatus = undefined;
|
||||||
});
|
});
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
|
|
@ -267,4 +273,40 @@ describe('McpServersPanel initial browse loading', () => {
|
||||||
await Promise.resolve();
|
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();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue