feat(studio): MCP suggestions + Approvals/Audit/Settings i18n (v0.26.0)
- Add curated catalogue of 9 official Anthropic MCP servers as click-to-prefill chips in the Add-MCP-server dialog. Operator still confirms via "Add + discover"; nothing is auto-spawned, preserving the regulated-environment trust model. - Localize Approvals page: pending/history empty states, status pills, payload preview, approve/reject toasts, reject dialog, history detail dialog, expires-in pill. - Localize Audit page: filter chips, clear-log dialog and toasts, no-events / hub-unreachable empty states, live-status bar with pluralized event count, hash-chain-verified badge, System AI panel (cached pill, latency, regenerate tooltip, asking state), event-detail dialog actions. - Localize Settings dialog: hub-endpoint section, channel blurb + popup-menu items, System AI panel headers and off-blurb, MCP/N8N panel headers + pluralized counts + refresh/add/remove tooltips, Add-MCP and Add-n8n dialogs (intro, suggestions label, all field labels and hints, save buttons, toasts). Field labels that map directly to JSON keys (event_id, flow, step, module, provider, endpoint, model) stay English by design — they're technical identifiers, not UI copy. Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
parent
349619d68e
commit
d25b4c87ae
9 changed files with 2022 additions and 209 deletions
|
|
@ -102,6 +102,194 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
String get settingsLanguageHint =>
|
||||
'App language. Affects every page; bilingual store entries also flip via this toggle.';
|
||||
|
||||
@override
|
||||
String get settingsHubEndpointHint =>
|
||||
'Where should Studio connect? Default is the local hub at 127.0.0.1:50051.';
|
||||
|
||||
@override
|
||||
String get settingsTlsSubtitle => 'https/grpc-secure';
|
||||
|
||||
@override
|
||||
String get settingsPortError => 'port must be 1–65535';
|
||||
|
||||
@override
|
||||
String get channelsBlurb =>
|
||||
'Switch hub channel (writes ~/.fai/current-channel and restarts the daemon). Connect just changes Studio\'s wire.';
|
||||
|
||||
@override
|
||||
String get channelsActionsTooltip => 'Channel actions';
|
||||
|
||||
@override
|
||||
String get systemAiHeader => 'SYSTEM AI';
|
||||
|
||||
@override
|
||||
String get systemAiEnabled => 'enabled';
|
||||
|
||||
@override
|
||||
String get systemAiOff => 'off';
|
||||
|
||||
@override
|
||||
String get systemAiEdit => 'Edit…';
|
||||
|
||||
@override
|
||||
String get systemAiConfigure => 'Configure…';
|
||||
|
||||
@override
|
||||
String get systemAiOffBlurb =>
|
||||
'Off — failure explanations on the audit page are disabled. Click Configure… to pick a provider (Ollama / OpenAI / LM Studio / vLLM / Custom). Operator config is rewritten in place; no daemon restart needed.';
|
||||
|
||||
@override
|
||||
String mcpServersCount(int n) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
n,
|
||||
locale: localeName,
|
||||
other: 'servers',
|
||||
one: 'server',
|
||||
);
|
||||
return '$n $_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
String get mcpRediscoverTooltip => 'Re-run discovery';
|
||||
|
||||
@override
|
||||
String get mcpAddTooltip => 'Add MCP server';
|
||||
|
||||
@override
|
||||
String get mcpRemoveTooltip => 'Remove server';
|
||||
|
||||
@override
|
||||
String mcpToolsCount(int n) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
n,
|
||||
locale: localeName,
|
||||
other: 'tools',
|
||||
one: 'tool',
|
||||
);
|
||||
return '$n $_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
String n8nEndpointsCount(int n) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
n,
|
||||
locale: localeName,
|
||||
other: 'endpoints',
|
||||
one: 'endpoint',
|
||||
);
|
||||
return '$n $_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
String n8nWorkflowsCount(int n) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
n,
|
||||
locale: localeName,
|
||||
other: 'workflows',
|
||||
one: 'workflow',
|
||||
);
|
||||
return '$n $_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
String get n8nRediscoverTooltip => 'Re-run discovery';
|
||||
|
||||
@override
|
||||
String get n8nAddTooltip => 'Add n8n endpoint';
|
||||
|
||||
@override
|
||||
String get n8nRemoveTooltip => 'Remove endpoint';
|
||||
|
||||
@override
|
||||
String get addMcpTitle => 'Add MCP server';
|
||||
|
||||
@override
|
||||
String get addMcpIntro =>
|
||||
'Tools the server advertises via `tools/list` appear in the Store as `mcp.<name>.<tool>` capabilities.';
|
||||
|
||||
@override
|
||||
String get addMcpSuggestionsLabel => 'Suggested servers — click to pre-fill';
|
||||
|
||||
@override
|
||||
String get addMcpNameLabel => 'Name (no dots)';
|
||||
|
||||
@override
|
||||
String get addMcpNameHint => 'filesystem';
|
||||
|
||||
@override
|
||||
String get addMcpEndpointLabel => 'Endpoint';
|
||||
|
||||
@override
|
||||
String get addMcpEndpointHint => 'http://127.0.0.1:3001/mcp';
|
||||
|
||||
@override
|
||||
String get addMcpApiKeyLabel => 'API key env var (optional)';
|
||||
|
||||
@override
|
||||
String get addMcpApiKeyHint => 'MCP_FILESYSTEM_TOKEN';
|
||||
|
||||
@override
|
||||
String get addMcpNotesLabel => 'Notes (optional)';
|
||||
|
||||
@override
|
||||
String get addMcpAddButton => 'Add + discover';
|
||||
|
||||
@override
|
||||
String get addN8nTitle => 'Add n8n endpoint';
|
||||
|
||||
@override
|
||||
String get addN8nIntro =>
|
||||
'Active workflows surface in the Store as `n8n.<name>.<workflow_slug>` capabilities.';
|
||||
|
||||
@override
|
||||
String get addN8nNameLabel => 'Name (no dots)';
|
||||
|
||||
@override
|
||||
String get addN8nNameHint => 'ops';
|
||||
|
||||
@override
|
||||
String get addN8nBaseUrlLabel => 'Base URL (without /api/v1)';
|
||||
|
||||
@override
|
||||
String get addN8nBaseUrlHint => 'https://n8n.example.com';
|
||||
|
||||
@override
|
||||
String get addN8nApiKeyLabel => 'API key env var (optional)';
|
||||
|
||||
@override
|
||||
String get addN8nApiKeyHint => 'N8N_OPS_KEY';
|
||||
|
||||
@override
|
||||
String get addN8nNotesLabel => 'Notes (optional)';
|
||||
|
||||
@override
|
||||
String get addN8nAddButton => 'Add + discover';
|
||||
|
||||
@override
|
||||
String addedMcpToast(String name) {
|
||||
return 'Added MCP server \"$name\".';
|
||||
}
|
||||
|
||||
@override
|
||||
String addedN8nToast(String name) {
|
||||
return 'Added n8n endpoint \"$name\".';
|
||||
}
|
||||
|
||||
@override
|
||||
String addFailedToast(String error) {
|
||||
return 'Add failed: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String removeFailedToast(String error) {
|
||||
return 'Remove failed: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String refreshFailedToast(String error) {
|
||||
return 'Refresh failed: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get channelsHeader => 'CHANNELS';
|
||||
|
||||
|
|
@ -192,6 +380,126 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
String get auditNoEventsHint =>
|
||||
'Run a flow to populate the audit stream.\nEvents appear here within seconds.';
|
||||
|
||||
@override
|
||||
String get auditFilterAll => 'all';
|
||||
|
||||
@override
|
||||
String get auditFilterFlow => 'flow';
|
||||
|
||||
@override
|
||||
String get auditFilterStep => 'step';
|
||||
|
||||
@override
|
||||
String get auditFilterModule => 'module';
|
||||
|
||||
@override
|
||||
String get auditClearLogTooltip => 'Clear log (local/dev channels only)';
|
||||
|
||||
@override
|
||||
String auditClearedToast(int n, String channel) {
|
||||
return 'Cleared $n events on channel \"$channel\". Chain reseeded with marker.';
|
||||
}
|
||||
|
||||
@override
|
||||
String auditClearFailed(String detail) {
|
||||
return 'Clear failed: $detail';
|
||||
}
|
||||
|
||||
@override
|
||||
String get auditExplain => 'Explain';
|
||||
|
||||
@override
|
||||
String get auditReask => 'Re-ask';
|
||||
|
||||
@override
|
||||
String get auditAsking => 'Asking…';
|
||||
|
||||
@override
|
||||
String get auditSystemAi => 'SYSTEM AI';
|
||||
|
||||
@override
|
||||
String get auditCachedPill => 'cached';
|
||||
|
||||
@override
|
||||
String auditOriginalLatency(int ms) {
|
||||
return 'orig $ms ms';
|
||||
}
|
||||
|
||||
@override
|
||||
String auditLatency(int ms) {
|
||||
return '$ms ms';
|
||||
}
|
||||
|
||||
@override
|
||||
String get auditRegenerateTooltip =>
|
||||
'Regenerate — skip cache, ask the model again';
|
||||
|
||||
@override
|
||||
String auditLiveStatus(int n) {
|
||||
String _temp0 = intl.Intl.pluralLogic(
|
||||
n,
|
||||
locale: localeName,
|
||||
other: 'events',
|
||||
one: 'event',
|
||||
);
|
||||
return 'live · polling 2s · $n $_temp0';
|
||||
}
|
||||
|
||||
@override
|
||||
String auditDisconnected(String error) {
|
||||
return 'disconnected · $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get auditHashChainVerified => 'hash chain verified';
|
||||
|
||||
@override
|
||||
String get auditDetailHeader => 'DETAIL';
|
||||
|
||||
@override
|
||||
String get auditAskingFull => 'Asking the configured System AI…';
|
||||
|
||||
@override
|
||||
String get auditFixLabel => 'FIX';
|
||||
|
||||
@override
|
||||
String auditCachedTooltipKnown(String at, String hits) {
|
||||
return 'Served from the local cache. Originally generated on $at$hits.';
|
||||
}
|
||||
|
||||
@override
|
||||
String auditCachedTooltipUnknown(String hits) {
|
||||
return 'Served from the local cache. Originally generated at unknown time$hits.';
|
||||
}
|
||||
|
||||
@override
|
||||
String auditCachedTooltipHits(int n) {
|
||||
return ' · $n hits';
|
||||
}
|
||||
|
||||
@override
|
||||
String get auditConfigureSystemAi =>
|
||||
'Configure System AI in Settings (Cmd+,)';
|
||||
|
||||
@override
|
||||
String get auditClearDialogTitle => 'Clear audit log?';
|
||||
|
||||
@override
|
||||
String get auditClearDialogBody =>
|
||||
'Wipes every audit event on the active channel and seeds a fresh chain.reset marker carrying reviewer + reason. Refused on beta / production. Irreversible.';
|
||||
|
||||
@override
|
||||
String get auditClearReviewerLabel => 'Reviewer';
|
||||
|
||||
@override
|
||||
String get auditClearReasonLabel => 'Reason (recorded in chain.reset marker)';
|
||||
|
||||
@override
|
||||
String get auditClearReasonHelper => 'Required — auditors will read this.';
|
||||
|
||||
@override
|
||||
String get auditClearLogButton => 'Clear log';
|
||||
|
||||
@override
|
||||
String get modulesTitle => 'Modules';
|
||||
|
||||
|
|
@ -259,6 +567,85 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||
String get approvalsInboxHint =>
|
||||
'All caught up. New `system.approval@^0` steps land here automatically.';
|
||||
|
||||
@override
|
||||
String get approvalsReloadTooltip => 'Reload';
|
||||
|
||||
@override
|
||||
String get approvalsPillPending => 'pending';
|
||||
|
||||
@override
|
||||
String get approvalsPillApproved => 'approved';
|
||||
|
||||
@override
|
||||
String get approvalsPillRejected => 'rejected';
|
||||
|
||||
@override
|
||||
String get approvalsPillExpired => 'expired';
|
||||
|
||||
@override
|
||||
String get approvalsPayloadPreview => 'PAYLOAD PREVIEW';
|
||||
|
||||
@override
|
||||
String get approvalsApproveButton => 'Approve';
|
||||
|
||||
@override
|
||||
String get approvalsRejectButton => 'Reject';
|
||||
|
||||
@override
|
||||
String get approvalsRejectDialogTitle => 'Reject approval';
|
||||
|
||||
@override
|
||||
String get approvalsRejectReasonLabel => 'Reason (recorded in audit log)';
|
||||
|
||||
@override
|
||||
String approvalsApprovedToast(String flow, String step) {
|
||||
return 'approved · $flow › $step';
|
||||
}
|
||||
|
||||
@override
|
||||
String approvalsRejectedToast(String flow, String step) {
|
||||
return 'rejected · $flow › $step';
|
||||
}
|
||||
|
||||
@override
|
||||
String approvalsApproveFailed(String error) {
|
||||
return 'approve failed: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String approvalsRejectFailed(String error) {
|
||||
return 'reject failed: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get approvalsHistoryEmpty => 'No history yet';
|
||||
|
||||
@override
|
||||
String get approvalsHistoryEmptyHint =>
|
||||
'Decided approvals (approved / rejected / expired) appear here.\nThe audit log keeps the full hash-chained record.';
|
||||
|
||||
@override
|
||||
String get approvalsDialogDecided => 'decided';
|
||||
|
||||
@override
|
||||
String get approvalsDialogCreated => 'created';
|
||||
|
||||
@override
|
||||
String get approvalsDialogReason => 'reason';
|
||||
|
||||
@override
|
||||
String get approvalsDialogPrompt => 'PROMPT';
|
||||
|
||||
@override
|
||||
String approvalsExpiresIn(int minutes) {
|
||||
return '${minutes}m';
|
||||
}
|
||||
|
||||
@override
|
||||
String approvalsExpiresInHours(int hours) {
|
||||
return '${hours}h';
|
||||
}
|
||||
|
||||
@override
|
||||
String get doctorTitle => 'Doctor';
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue