feat(studio): friendlyError catches hub-specific patterns
Some checks failed
Security / Security check (push) Failing after 1s

Generic gRPC-code mapping was right but not specific enough.
A flow failing with an approval-timeout used to land on
'Deadline exceeded — try again later'; now it reads 'Freigabe-
Timeout abgelaufen — entweder timeout_seconds erhöhen oder
den Reviewer informieren.'

New pattern matchers in _matchHubPattern, runs before the
gRPC-code switch. Six FlowExecutionError shapes covered:

  - approval rejected ("rejected by")
  - approval timeout
  - output too large ("exceeding the X MB cap")
  - host service not declared
  - missing value reference
  - MCP endpoint unreachable
  - capability not installed (NotFound fallback)

Every match comes with a localised hint pointing at the
concrete fix path (audit log / timeout config / Integrations
panel / Text-tab Fix button).

Five new tests pin the matchers — would catch a silent
regression when the hub renames a variant Display string.
All 11 friendly_error tests + 19 Studio tests green.

Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
This commit is contained in:
flemming-it 2026-06-09 02:01:36 +02:00
parent 28fafce7dc
commit 971196518c
8 changed files with 370 additions and 4 deletions

View file

@ -278,6 +278,90 @@ abstract class AppLocalizations {
/// **'Help'**
String get helpTooltip;
/// No description provided for @errApprovalRejected.
///
/// In en, this message translates to:
/// **'Approval rejected by reviewer.'**
String get errApprovalRejected;
/// No description provided for @errApprovalRejectedHint.
///
/// In en, this message translates to:
/// **'The reviewer marked this step as rejected. Check the audit log for the reviewer\'s reason.'**
String get errApprovalRejectedHint;
/// No description provided for @errApprovalTimedOut.
///
/// In en, this message translates to:
/// **'Approval timed out.'**
String get errApprovalTimedOut;
/// No description provided for @errApprovalTimedOutHint.
///
/// In en, this message translates to:
/// **'No reviewer decided within the configured time. Raise `timeout_seconds` on the approval step or alert the reviewer.'**
String get errApprovalTimedOutHint;
/// No description provided for @errOutputTooLarge.
///
/// In en, this message translates to:
/// **'Step output exceeded the size limit.'**
String get errOutputTooLarge;
/// No description provided for @errOutputTooLargeHint.
///
/// In en, this message translates to:
/// **'Either trim the output (truncate text, downsample bytes) or raise `max_output_size_mb` in the operator config.'**
String get errOutputTooLargeHint;
/// No description provided for @errServiceUnavailableForStep.
///
/// In en, this message translates to:
/// **'Host service not configured.'**
String get errServiceUnavailableForStep;
/// No description provided for @errServiceUnavailableForStepHint.
///
/// In en, this message translates to:
/// **'The module requires a service (e.g. ollama, playwright) the operator hasn\'t declared. Add it under `services:` in ~/.fai/config.yaml.'**
String get errServiceUnavailableForStepHint;
/// No description provided for @errMissingValue.
///
/// In en, this message translates to:
/// **'Required value is missing.'**
String get errMissingValue;
/// No description provided for @errMissingValueHint.
///
/// In en, this message translates to:
/// **'The step expected an input that wasn\'t wired up — either supply it at run time or fix the upstream `\$ref`.'**
String get errMissingValueHint;
/// No description provided for @errMcpUnreachable.
///
/// In en, this message translates to:
/// **'MCP endpoint unreachable.'**
String get errMcpUnreachable;
/// No description provided for @errMcpUnreachableHint.
///
/// In en, this message translates to:
/// **'The MCP server didn\'t respond. Check the endpoint in Settings → Integrations and confirm it\'s running.'**
String get errMcpUnreachableHint;
/// No description provided for @errCapabilityNotInstalled.
///
/// In en, this message translates to:
/// **'Required capability is not installed.'**
String get errCapabilityNotInstalled;
/// No description provided for @errCapabilityNotInstalledHint.
///
/// In en, this message translates to:
/// **'Open the flow\'s Text tab — the analyzer\'s Fix button installs the capability if it\'s in the store.'**
String get errCapabilityNotInstalledHint;
/// No description provided for @welcomeDocClose.
///
/// In en, this message translates to: