feat(studio): n8n-endpoints editor in Settings (v0.23.0)

Mirror of the MCP-clients panel: Add / Remove / Refresh
with last-discovery health (workflow count or error_kind),
sister Add-dialog with name + base_url + optional
api_key_env + notes. HubService gains the four passthroughs
(`listN8nEndpoints`, `refreshN8nEndpoints`,
`addN8nEndpoint`, `removeN8nEndpoint`) and a
`N8nEndpointInfo` data class.

Settings dialog now hosts: hub endpoint, channels,
system AI, MCP clients, n8n endpoints — all behind the
existing 520×640 SingleChildScrollView so the layout
doesn't crowd.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-05-08 01:00:17 +02:00
parent 9ef32df31e
commit d2a6ed32e2
5 changed files with 435 additions and 3 deletions

View file

@ -388,6 +388,53 @@ class HubService {
.toList();
}
/// Snapshot of every configured n8n endpoint.
Future<List<N8nEndpointInfo>> listN8nEndpoints() async {
final r = await _client.listN8nEndpoints();
return _mapN8nEndpoints(r);
}
Future<List<N8nEndpointInfo>> refreshN8nEndpoints() async {
final r = await _client.refreshN8nEndpoints();
return _mapN8nEndpoints(r);
}
Future<List<N8nEndpointInfo>> addN8nEndpoint({
required String name,
required String baseUrl,
String apiKeyEnv = '',
String description = '',
}) async {
final r = await _client.addN8nEndpoint(
name: name,
baseUrl: baseUrl,
apiKeyEnv: apiKeyEnv,
description: description,
);
return _mapN8nEndpoints(r);
}
Future<List<N8nEndpointInfo>> removeN8nEndpoint(String name) async {
final r = await _client.removeN8nEndpoint(name);
return _mapN8nEndpoints(r);
}
List<N8nEndpointInfo> _mapN8nEndpoints(ListN8nEndpointsResponse r) {
return r.endpoints
.map(
(s) => N8nEndpointInfo(
name: s.config.name,
baseUrl: s.config.baseUrl,
apiKeyEnv: s.config.apiKeyEnv,
description: s.config.description,
workflowCount: s.workflowCount,
errorKind: s.errorKind,
message: s.message,
),
)
.toList();
}
/// Active channel + per-channel daemon status snapshot.
Future<ChannelStatusSnapshot> channelStatus() async {
final r = await _client.channelStatus();
@ -975,6 +1022,30 @@ class ChannelStatusSnapshot {
});
}
/// One configured n8n endpoint plus the last-discovery
/// report. Sister of [`McpClientInfo`].
class N8nEndpointInfo {
final String name;
final String baseUrl;
final String apiKeyEnv;
final String description;
final int workflowCount;
final String errorKind;
final String message;
const N8nEndpointInfo({
required this.name,
required this.baseUrl,
required this.apiKeyEnv,
required this.description,
required this.workflowCount,
required this.errorKind,
required this.message,
});
bool get healthy => errorKind.isEmpty && workflowCount > 0;
}
/// One configured MCP server plus the last-discovery report.
/// Surfaced by Studio's MCP-clients editor in Settings.
class McpClientInfo {