Splits channel construction into two files selected at
compile-time via `if (dart.library.html)`:
channel_factory_io.dart — native ClientChannel (HTTP/2)
channel_factory_web.dart — GrpcWebClientChannel.xhr (HTTP/1.1)
HubClient._channel is now `ClientChannelBase` so both
implementations satisfy the same field type. dart:html-only
imports (`package:grpc/grpc_web.dart`) stay isolated from the
native compile path.
Pairs with the hub-side `fai_grpc_web` adapter crate
(fai/platform 0d07892) — `tonic-web` on the same port as
native gRPC, so one `fai serve` listener handles both
surfaces.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Adds HubClient.invokePluginTranslate as a typed method.
Same shape as invokePluginTheme: capability + args in,
typed response out.
Signed-off-by: flemming-it <sf@flemming.it>
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Tracks the platform's hub.proto v0.11 update — adds the new
fields to the generated Dart bindings:
- `CapabilityEntry.kind` (string) — wasm / builtin / federated.
Studio uses it to gate the Install button so built-ins like
`system.approval` and federated MCP/n8n tools never get
offered an install path that doesn't exist.
- `ModuleInfoResponse.accepts_mime` (repeated string) — MIME
allow-list declared in `module.yaml`. Studio reads it for
file-picker filtering.
No hand-edited code in this commit — `tools/generate.sh`
output only.
Signed-off-by: flemming-it <sf@flemming.it>
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
- New getInstalledModuleDocs(name, locale) wraps the new gRPC
RPC; callers get text + source path + a not-installed flag so
Studio can decide whether to show a Documentation section at
all.
- runSavedFlow gains an optional fileMimeTypes map keyed
parallel to fileInputs. Hard-coded application/octet-stream
remains as the fallback, but text.extract and other
MIME-gating modules now get an accurate type when the caller
knows one.
- fetchModuleDocs is marked @Deprecated; it still works for
older consumers but Studio no longer calls it.
- Proto bindings regenerated against fai/platform proto.
Signed-off-by: flemming-it <sf@flemming.it>
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Hub now accepts a locale field on FetchModuleDocsRequest so
README.<locale>.md (e.g. README.de.md) gets tried before the
generic README.md. SDK passes it via an optional named param;
empty string keeps the previous behaviour.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
`pb.FlowSummary.requiredCapabilities` flows through the
existing typedef untouched, so callers see the new field
without a wrapper change.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Surface the new platform RPC `GetFlowDefinition` as a typed
Dart method so Studio (and other GUI clients) can render an
input form before calling `runSavedFlow`. Each declared input
arrives as a `FlowInputDef` with the verbatim type tag from
the flow YAML — usually `text`, `bytes`, `json`, or `file`.
Regenerated proto bindings to pick up the new
`GetFlowDefinitionRequest`, `FlowDefinition`, and
`FlowInputSpec` message types.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Studio's Flows tab couldn't run any sample flow with a
binary input (extract / extract-summarize / …) because
runSavedFlow only knew how to wrap textInputs as text
Payloads. Operators saw the hub return
"step references missing value '\$inputs.document'" because
the document key never made it into the request.
`runSavedFlow` is now mixed-mode:
Future<SubmitResponse> runSavedFlow({
required String name,
Map<String, String> textInputs = const {},
Map<String, Uint8List> fileInputs = const {},
})
Both maps default to empty so existing text-only callers
keep working without code changes — the previous required
`textInputs:` parameter is now optional with a default. File
entries get wrapped as `Bytes` Payloads with
`application/octet-stream` MIME — good enough for the
text.extract / text.summarize chain that the bundled flows
exercise. Per-file MIME-type override is a follow-up if any
operator workflow ever needs it.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Sister of the MCP-client surface — four new HubAdmin RPCs
(`ListN8nEndpoints`, `RefreshN8nEndpoints`, `AddN8nEndpoint`,
`RemoveN8nEndpoint`) plus the matching typedefs so callers
read configuration off `N8nEndpointStatus` without importing
generated/.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Picks up the four new HubAdmin RPCs that drive Studio's
MCP-clients editor:
- `listMcpClients()` — config + last-discovery snapshot.
- `refreshMcpClients()` — re-run discovery against the live
daemon.
- `addMcpClient(name, endpoint, apiKeyEnv?, description?)` —
persist + refresh in one round-trip.
- `removeMcpClient(name)` — drop persisted entry and live
synthetic capabilities.
Typedefs for `ListMcpClientsResponse`, `McpClientStatus`,
`McpClientConfigEntry` so callers don't import generated/.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Picks up the three new optional fields on the StoreEntry
proto. No new client method — fields are plumbed through
SearchStore. Studio reads them off the entry directly.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Picks up the new `featured: bool` field in the StoreEntry
proto. No new client method — the flag is plumbed through
SearchStore. Studio reads it directly off the entry.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Picks up HubAdmin.FetchModuleDocs. HubClient exposes it as
fetchModuleDocs(name) returning the FetchModuleDocsResponse
verbatim — Studio maps the error_kind to friendly copy.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Picks up cache-related additions in HubAdmin:
- AskAi gains `forceFresh` request flag and `cached` /
`cachedAt` / `cacheHits` response fields.
- New ClearSystemLlmCache + ForgetCachedExplanation RPCs.
- SystemAiStatus carries `cacheCount` so the UI can render
"Cache: N cached explanations".
HubClient exposes `clearSystemLlmCache()` returning the
purged count and `forgetCachedExplanation(prompt)` for the
Regenerate flow.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Picks up the new HubAdmin.ClearEventLog RPC. Exposed as
HubClient.clearEventLog(reviewer:, reason:) returning the
purged count + active channel for the caller to confirm.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Regenerated protos pick up the two new HubAdmin RPCs. HubClient
exposes them as hardwareInfo() and listSystemAiCuratedModels(),
with HardwareInfoResponse, ListSystemAiCuratedModelsResponse,
CuratedModel re-exported as typedefs so callers don't import
the generated/ directory directly.
Studio uses the pair to colour-code models in the System-AI
editor against the operator's actual hardware.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
`testSystemAi` now takes optional provider/endpoint/model/
apiKeyEnv/privacyMode params; the editor passes form values so
Test Connection works before Save. New `listSystemAiModels`
fetches the provider's `/v1/models` listing, `pullSystemAiModel`
calls Ollama's `/api/pull` synchronously.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
`HubClient.updateSystemAi(...)` persists a new System-AI config
to ~/.fai/config.yaml AND hot-reloads the live hub state in one
round-trip; returns the resulting SystemAiStatus so the UI
refreshes without a second call.
`HubClient.testSystemAi()` probes the configured provider with
a tiny ping and returns the same error-kind taxonomy as askAi.
Studio's "Test connection" button uses this.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
`HubClient.systemAiStatus()` reports whether the hub-internal LLM
hook is configured and which provider / privacy mode is active.
`HubClient.askAi(prompt)` issues a one-shot prompt and returns
the answer or a structured error kind so the UI can map each
failure to its inline-fix copy.
LoggedEvent gains `detail` upstream (no SDK change required).
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Catches the Dart bindings up to the platform's gRPC additions:
* `searchStore({query, category, tag, status, limit})` — wraps
HubAdmin.SearchStore so Studio can build a Store browser
page.
* `installModule({source, expectedSha256})` — wraps
HubAdmin.InstallModule so the operator can one-click install
a `.fai` bundle from the UI.
* `channelStatus()` — new HubAdmin.ChannelStatus RPC. Returns
active channel name + per-channel running flag + endpoint.
Re-exports the new proto types (StoreEntry,
StoreSearchResponse, InstallModuleResponse, ChannelStatusResponse,
ChannelEntry) so callers don't import protobuf directly.
LoggedEvent gains a `detail` field (free-form JSON string)
upstream; the regenerated bindings expose it without further
work — Studio's audit drill-down renders it pretty-printed.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Adds `checkUpdate()` to HubClient and re-exports
`CheckUpdateResponse` so callers (Studio Doctor page) can render
update + offline states without importing protobuf directly.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Two more wrappers for Studio's new Flows page. Saved flows can
be listed (FlowSummary: name + path + size) and executed by
name with a map of named text inputs. Returns a SubmitResponse
whose `outputs` map carries the flow's declared outputs as
Payloads.
Common payload type re-exposed via the `Payload` typedef from
common.pb.dart so the Studio side can pattern-match on
text/json/bytes/file without dragging in proto imports.
Bumps fai_dart_sdk 0.4.0 -> 0.5.0.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Initial scaffold accidentally created three separate gRPC
channels (one for each of `_channel`, `_hub`, `_admin`).
Refactor to a single shared channel — cleaner, fewer file
descriptors, and `close()` actually closes everything now.
Idle timeout raised to 5 minutes so polling-style page loops
don't keep reconnecting.
No public-API change.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Wraps the existing HubAdmin.ModuleInfo RPC so Studio can
render a detail panel for one module without re-implementing
the proto types.
Bumps fai_dart_sdk 0.3.0 -> 0.4.0.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Mirrors the two new HubAdmin RPCs in fai_platform 0.10.44.
Studio's Doctor page consumes these directly. Generated proto
bindings refreshed to include VerifyEventChainResponse,
ServiceList, DeclaredService.
Bumps fai_dart_sdk 0.2.0 -> 0.3.0.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Proto codegen wired in. tools/generate.sh wraps protoc against
../fai_platform/proto/, including the well-known types (Empty,
Struct, Timestamp) so they are generated alongside fai's own
messages — protobuf 4.x doesn't ship them as importable Dart
types, so we have to generate them ourselves.
HubClient now exposes typed methods backed by real RPCs:
- healthy() — Hub.Health probe (returns false on connect refused).
- listCapabilities() — HubAdmin.ListCapabilities.
- eventLog() — HubAdmin.EventLog with type filter.
- listApprovals() — HubAdmin.ListApprovals (status filter).
- approve() / reject() — HubAdmin.DecideApproval.
Generated bindings under lib/src/generated/ are excluded from
analyze (out of our style control). protoc_plugin pinned to
22.2.0 in tools/generate.sh comment because newer plugins
generate code against protobuf 6.x, while grpc 4.x still
constrains us to protobuf 4.x.
Bumps fai_dart_sdk 0.1.0 -> 0.2.0.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>
Dart package skeleton for the F∆I gRPC client. Used by F∆I
Studio (Tier-2) and Tier-3 domain apps (DigiScout / J∆I /
Scout). Public surface — HubClient, HubEndpoint — is committed
as a typed stub so downstream apps can compile against it
immediately. Generated proto bindings land in a follow-up
commit once the codegen step (planned: tools/generate.sh
wrapping protoc-gen-dart against ../fai_platform/proto) is
wired in.
Future Forgejo path: fai/dart-sdk.
dart analyze: clean. dart test: 4/4.
Signed-off-by: flemming-it <stefan.a.flemming@googlemail.com>