Differentiate unavailable tools by reason (#4916)

## Summary
- track endpoint disable reasons server-side and expose them through a
new `/api/v1/config/endpoints-availability` API that the frontend can
consume
- refresh the web UI tool management logic to cache endpoint details,
compute per-tool availability metadata, and show reason-specific
messaging (admin disabled vs missing dependency) when a tool cannot be
launched
- add the missing en-GB translations for the new unavailability labels
so the UI copy reflects the new distinction
<img width="1156" height="152" alt="image"
src="https://github.com/user-attachments/assets/b54eda37-fe5c-42f9-bd5f-9ee00398d1ae"
/>


<img width="930" height="168" alt="image"
src="https://github.com/user-attachments/assets/47c07ffa-adb7-4ce3-910c-b6ff73f6f993"
/>


## Testing
- `npm run typecheck:core` *(fails:
frontend/src/core/components/shared/LocalIcon.tsx expects
../../../assets/material-symbols-icons.json, which is not present in
this environment)*

------
[Codex
Task](https://chatgpt.com/codex/tasks/task_b_6919af7a493c8328bb5ac3d07e65452b)
This commit is contained in:
Anthony Stirling
2025-11-21 13:19:53 +00:00
committed by GitHub
parent 4fd336c26c
commit e1a879a5f6
19 changed files with 542 additions and 182 deletions

View File

@@ -4,7 +4,7 @@
*/
import React, { createContext, useContext, useReducer, useCallback, useMemo, useEffect } from 'react';
import { useToolManagement } from '@app/hooks/useToolManagement';
import { useToolManagement, type ToolAvailabilityMap } from '@app/hooks/useToolManagement';
import { PageEditorFunctions } from '@app/types/pageEditor';
import { ToolRegistryEntry, ToolRegistry } from '@app/data/toolsTaxonomy';
import { useNavigationActions, useNavigationState } from '@app/contexts/NavigationContext';
@@ -44,6 +44,7 @@ interface ToolWorkflowContextValue extends ToolWorkflowState {
selectedTool: ToolRegistryEntry | null;
toolRegistry: Partial<ToolRegistry>;
getSelectedTool: (toolId: ToolId | null) => ToolRegistryEntry | null;
toolAvailability: ToolAvailabilityMap;
// UI Actions
setSidebarsVisible: (visible: boolean) => void;
@@ -112,7 +113,7 @@ export function ToolWorkflowProvider({ children }: ToolWorkflowProviderProps) {
const navigationState = useNavigationState();
// Tool management hook
const { toolRegistry, getSelectedTool } = useToolManagement();
const { toolRegistry, getSelectedTool, toolAvailability } = useToolManagement();
const { allTools } = useToolRegistry();
// Tool history hook
@@ -258,6 +259,11 @@ export function ToolWorkflowProvider({ children }: ToolWorkflowProviderProps) {
// Workflow actions (compound actions that coordinate multiple state changes)
const handleToolSelect = useCallback((toolId: ToolId) => {
const availabilityInfo = toolAvailability[toolId];
const isExplicitlyDisabled = availabilityInfo ? availabilityInfo.available === false : false;
if (toolId !== 'read' && toolId !== 'multiTool' && isExplicitlyDisabled) {
return;
}
// If we're currently on a custom workbench (e.g., Validate Signature report),
// selecting any tool should take the user back to the default file manager view.
const wasInCustomWorkbench = !isBaseWorkbench(navigationState.workbench);
@@ -299,7 +305,7 @@ export function ToolWorkflowProvider({ children }: ToolWorkflowProviderProps) {
setSearchQuery('');
setLeftPanelView('toolContent');
setReaderMode(false); // Disable read mode when selecting tools
}, [actions, getSelectedTool, navigationState.workbench, setLeftPanelView, setReaderMode, setSearchQuery]);
}, [actions, getSelectedTool, navigationState.workbench, setLeftPanelView, setReaderMode, setSearchQuery, toolAvailability]);
const handleBackToTools = useCallback(() => {
setLeftPanelView('toolPicker');
@@ -354,6 +360,7 @@ export function ToolWorkflowProvider({ children }: ToolWorkflowProviderProps) {
toolResetFunctions,
registerToolReset,
resetTool,
toolAvailability,
// Workflow Actions
handleToolSelect,
@@ -381,6 +388,7 @@ export function ToolWorkflowProvider({ children }: ToolWorkflowProviderProps) {
selectedTool,
toolRegistry,
getSelectedTool,
toolAvailability,
setSidebarsVisible,
setLeftPanelView,
setReaderMode,