From 193f59302a2c5033e135ead3427a456cb85c1d87 Mon Sep 17 00:00:00 2001 From: flemming-it Date: Sat, 9 May 2026 02:07:07 +0200 Subject: [PATCH] feat: runSavedFlow accepts file (bytes) inputs (v0.14.0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 runSavedFlow({ required String name, Map textInputs = const {}, Map 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 --- lib/src/hub_client.dart | 28 +++++++++++++++++++++++----- pubspec.yaml | 2 +- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/lib/src/hub_client.dart b/lib/src/hub_client.dart index 673cc70..c1fb367 100644 --- a/lib/src/hub_client.dart +++ b/lib/src/hub_client.dart @@ -4,6 +4,8 @@ // public method maps onto exactly one RPC on Hub or HubAdmin, so // callers don't have to know which service hosts which call. +import 'dart:typed_data'; + import 'package:grpc/grpc.dart'; import 'generated/fai/v1/common.pb.dart' as pb_common; @@ -465,18 +467,34 @@ class HubClient { } /// Run a saved flow by name with the supplied named inputs. - /// Each input value is wrapped as a text Payload — the most - /// common case for human-driven runs from Studio. Callers - /// that need bytes / file payloads use the lower-level - /// SubmitRequest path. + /// Two input shapes are supported in the same call so a + /// flow that mixes text and binary inputs (e.g. extract + /// taking a `document: bytes`) flows through one RPC: + /// * [textInputs] — string values wrapped as text Payloads + /// * [fileInputs] — raw bytes wrapped as bytes Payloads, + /// with `application/octet-stream` MIME + /// type. Caller can override the MIME by + /// passing a [bytePayloads] entry instead. + /// Both maps default to empty so existing text-only callers + /// are backward-compatible. Keys must not collide between + /// the maps; on collision the bytes-shaped entry wins (the + /// less-common case is more likely to be the operator's + /// intent). Future runSavedFlow({ required String name, - required Map textInputs, + Map textInputs = const {}, + Map fileInputs = const {}, }) async { final req = pb.RunSavedFlowRequest()..name = name; for (final entry in textInputs.entries) { req.inputs[entry.key] = pb_common.Payload()..text = entry.value; } + for (final entry in fileInputs.entries) { + final bytes = pb_common.Bytes() + ..mimeType = 'application/octet-stream' + ..data = entry.value; + req.inputs[entry.key] = pb_common.Payload()..bytes = bytes; + } return _admin.runSavedFlow(req); } diff --git a/pubspec.yaml b/pubspec.yaml index 800ed01..021eb88 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: fai_dart_sdk description: gRPC client SDK for the F∆I Platform hub. Used by F∆I Studio and Tier-3 domain apps. -version: 0.13.0 +version: 0.14.0 publish_to: 'none' repository: https://git.flemming.ws/fai/dart-sdk