Split each flow's missing capabilities into store-resolvable ones (amber chip + Install link, which now installs only those) and a quiet 'not in store' chip whose tooltip explains the three recovery paths in place: local install via chain install --link, adding the providing store, or configuring the MCP/n8n integration. The analyzer's not-in-store message names the same three paths (EN+DE). Previously the list's Install action covered every missing capability and could end in the hub's 'no store entry' error. Also replace a private-looking capability example name in a doc comment and test with a neutral placeholder. (0.25.0) Signed-off-by: flemming-it <sf@flemming.it>
141 lines
4.9 KiB
Dart
141 lines
4.9 KiB
Dart
// Quick-fix model for the flow editor's diagnostics.
|
|
//
|
|
// Each analyzer issue can carry one or more `QuickFix` records
|
|
// describing a one-click remediation. The editor renders these
|
|
// as action buttons on the hover tooltip and inside the bottom
|
|
// diagnostic strip. Two categories exist today:
|
|
//
|
|
// * `ReplaceLineValueFix` — purely textual; the editor
|
|
// applies it directly by mutating the controller's
|
|
// buffer.
|
|
// * `InstallCapabilityFix` — needs the host (Studio) to talk
|
|
// to the Hub. The editor invokes the host-provided
|
|
// callback and reanalyzes once it returns.
|
|
//
|
|
// New fix kinds can be added by extending the sealed base; both
|
|
// surfaces (tooltip + strip) switch on the runtime type, so
|
|
// adding a kind also means adding a case there.
|
|
|
|
import 'dart:ui' show Offset;
|
|
|
|
import 'package:flutter/foundation.dart';
|
|
|
|
@immutable
|
|
sealed class QuickFix {
|
|
/// One-line button label rendered in the UI (verb-first,
|
|
/// imperative). Kept short so the strip layout doesn't reflow
|
|
/// when multiple fixes are present.
|
|
final String label;
|
|
const QuickFix(this.label);
|
|
}
|
|
|
|
/// Replace the trailing value of `[line]` with [replacement].
|
|
/// Used by the unknown-type warning to offer the closest
|
|
/// matching valid type token (e.g. `byes` → `bytes`).
|
|
@immutable
|
|
class ReplaceLineValueFix extends QuickFix {
|
|
/// Zero-based line index inside the document.
|
|
final int line;
|
|
|
|
/// The token to substitute for the existing value (the
|
|
/// substring after the colon, with surrounding whitespace
|
|
/// preserved by the applier).
|
|
final String replacement;
|
|
|
|
const ReplaceLineValueFix({
|
|
required this.line,
|
|
required this.replacement,
|
|
required String label,
|
|
}) : super(label);
|
|
}
|
|
|
|
/// Ask the host (Studio) to install the named capability via
|
|
/// the Hub's store-backed install. The editor delegates to the
|
|
/// [InstallCapabilityCallback] passed into `FlowEditorPage`
|
|
/// and reanalyzes the document once the host returns.
|
|
@immutable
|
|
class InstallCapabilityFix extends QuickFix {
|
|
/// The capability spec the operator wrote (with or without an
|
|
/// `@version` tail). The host is responsible for parsing the
|
|
/// version part if it matters; the editor never strips it.
|
|
final String capability;
|
|
|
|
const InstallCapabilityFix({
|
|
required this.capability,
|
|
required String label,
|
|
}) : super(label);
|
|
}
|
|
|
|
/// Ask the host to register a new module source for an unknown
|
|
/// capability — used when the capability isn't in the public
|
|
/// store. The host's handler typically prompts the operator
|
|
/// for a local path (`chain install --link`) or a URL
|
|
/// (`chain install <url>`), then installs and reanalyzes.
|
|
///
|
|
/// This is the recovery path for private modules: the public
|
|
/// store doesn't know about `acme.internal/directory-lookup`,
|
|
/// but the operator can point the hub at the local clone.
|
|
@immutable
|
|
class AddModuleSourceFix extends QuickFix {
|
|
/// The capability the operator wrote — the host uses it to
|
|
/// pre-fill its prompt ("Where can `<capability>` be
|
|
/// installed from?").
|
|
final String capability;
|
|
|
|
const AddModuleSourceFix({
|
|
required this.capability,
|
|
required String label,
|
|
}) : super(label);
|
|
}
|
|
|
|
/// Host-side install handler signature. Returns the new
|
|
/// installed-capability list after the install completes (used
|
|
/// by the editor to refresh its analyzer without round-tripping
|
|
/// through the parent widget tree). Returns `null` on failure;
|
|
/// in that case the editor keeps the prior list and the issue
|
|
/// stays visible.
|
|
typedef InstallCapabilityCallback =
|
|
Future<List<String>?> Function(String capability);
|
|
|
|
/// Host-side "add module source" handler. Receives the bare
|
|
/// capability spec the operator typed; expected to prompt the
|
|
/// operator for a local path / URL and then install it.
|
|
/// Same return contract as [InstallCapabilityCallback].
|
|
typedef AddModuleSourceCallback =
|
|
Future<List<String>?> Function(String capability);
|
|
|
|
/// Hover-tooltip request — the controller emits one of these
|
|
/// via a ValueNotifier when the pointer enters an issue range,
|
|
/// and clears it when the pointer leaves both the range and the
|
|
/// tooltip. The editor host listens and renders an overlay.
|
|
@immutable
|
|
class IssueHoverRequest {
|
|
/// Zero-based line of the issue the pointer is over.
|
|
final int line;
|
|
|
|
/// Human-readable issue message (lifted from
|
|
/// `Issue.message`).
|
|
final String message;
|
|
|
|
/// Issue severity. Drives the dot colour in the tooltip.
|
|
final IssueHoverSeverity severity;
|
|
|
|
/// Pre-computed quick fixes the tooltip should render as
|
|
/// action buttons. Empty when the editor has nothing
|
|
/// actionable to offer.
|
|
final List<QuickFix> fixes;
|
|
|
|
/// Global cursor position at hover time — the host overlay
|
|
/// uses it to anchor the tooltip near the pointer.
|
|
final Offset globalPosition;
|
|
|
|
const IssueHoverRequest({
|
|
required this.line,
|
|
required this.message,
|
|
required this.severity,
|
|
required this.fixes,
|
|
required this.globalPosition,
|
|
});
|
|
}
|
|
|
|
enum IssueHoverSeverity { error, warning, info }
|