Skip to content

Feature/520 short human in the loop#523

Merged
felix-schultz merged 5 commits intodevfrom
feature/520-short-human-in-the-loop
Feb 17, 2026
Merged

Feature/520 short human in the loop#523
felix-schultz merged 5 commits intodevfrom
feature/520-short-human-in-the-loop

Conversation

@felix-schultz
Copy link
Copy Markdown
Member

This pull request introduces support for human-in-the-loop interactions in both the backend and frontend, along with several dependency and configuration updates. The main changes include the addition of a new Interaction model in the Prisma schema, backend and Tauri API wiring for responding to interactions, improvements to SSE parsing in the web frontend, and dependency upgrades and feature enhancements across multiple crates.

Interaction model and backend support:

  • Added a new Interaction model and InteractionStatus enum to the Prisma schema, representing lean, ephemeral human-in-the-loop interaction records, and created relations to App and User models. [1] [2] [3]
  • Implemented a new Tauri command respond_to_interaction in interaction.rs to allow desktop clients to respond to interactions, and registered this command in the Tauri app. [1] [2] [3]

Frontend improvements:

  • Improved SSE event parsing in both WebBoardState and WebEventState to properly handle multi-line data: fields, fixing potential issues with event data integrity. [1] [2]

Dependency and configuration updates:

  • Upgraded tracing-subscriber to version 0.3.22 and standardized its usage via workspace features in several crates. [1] [2] [3] [4]
  • Expanded features for the lettre crate to include builder, hostname, pool, and smtp-transport.
  • Added the remote or local feature to flow-like-catalog dependencies in multiple backend and desktop crates to enable new catalog capabilities. [1] [2] [3] [4] [5] [6]

Code cleanup and refactoring:

  • Removed unused token fields from job processing and execution logic in backend runtimes, streamlining the job payload structure. [1] [2] [3]

- Introduced interaction types (single choice, multiple choice, form) and their respective schemas.
- Implemented interaction request processing in the chat component.
- Enhanced chat UI to display interactions alongside messages.
- Created a new Interaction component for rendering interaction requests.
- Added countdown functionality for pending interactions.
- Updated event processor to handle interaction events.
- Refactored chat component to utilize new interaction logic.
- Added necessary types and interfaces for interactions in the schema.
- Introduced a comprehensive styling guide covering theme variables, component styles, spacing, sizing, borders, shadows, responsive design, typography, flexbox utilities, common component patterns, animation classes, z-index, overflow, position, and custom CSS injection.
- Emphasized the use of theme variables over hardcoded colors for better dark/light mode support.
- Provided examples and best practices for implementing styles in A2UI components.
@felix-schultz felix-schultz linked an issue Feb 17, 2026 that may be closed by this pull request
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello @felix-schultz, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a robust human-in-the-loop interaction system, enabling dynamic user engagement within workflows. It establishes the foundational database models, API endpoints with real-time event streaming, and client-side components necessary for both desktop and web applications to facilitate these interactions. The changes also encompass significant dependency updates, authentication enhancements, and general code cleanup, contributing to a more interactive and efficient system.

Highlights

  • Human-in-the-Loop (HITL) Interaction System: Introduced comprehensive support for human-in-the-loop interactions across the backend, desktop (Tauri), and web frontend, allowing workflows to solicit user input through various interactive forms.
  • New Interaction Data Model and API: Added a new Interaction model to the Prisma schema, along with corresponding SeaORM entities, and implemented API endpoints for creating and responding to interactions using Server-Sent Events (SSE) for real-time updates.
  • Interactive Catalog Nodes: Developed new catalog nodes, including FormInteraction, SingleChoiceInteraction, and MultipleChoiceInteraction, enabling workflows to generate dynamic forms and choice selections for user input.
  • Frontend Integration and Response Mechanisms: Enhanced the web frontend chat interface to display and manage active user interactions, and integrated interaction response handling for both local (Tauri command) and remote (API) execution environments.
  • Authentication and Dependency Updates: Refactored JWT authentication to include a new InteractionResponder token type and ExecutorUser for improved security, alongside upgrades to tracing-subscriber and expanded features for the lettre crate.
  • Codebase Cleanup: Removed unused token fields from job processing payloads in various executor runtimes, streamlining data structures and improving code clarity.
Changelog
  • Cargo.toml
    • Upgraded 'tracing-subscriber' to version 0.3.22.
    • Expanded 'lettre' crate features to include 'builder', 'hostname', 'pool', and 'smtp-transport'.
  • apps/backend/aws/executor-async/Cargo.toml
    • Added the 'remote' feature to 'flow-like-catalog'.
  • apps/backend/aws/executor-async/src/execution.rs
    • Removed the 'token' field from the 'RunPayload' construction.
  • apps/backend/aws/executor/Cargo.toml
    • Added the 'remote' feature to 'flow-like-catalog'.
  • apps/backend/docker-compose/runtime/Cargo.toml
    • Added the 'remote' feature to 'flow-like-catalog'.
  • apps/backend/docker-compose/runtime/src/main.rs
    • Removed the 'token' field from the 'RunPayload' construction.
  • apps/backend/docker-compose/sink-services/Cargo.toml
    • Standardized 'tracing-subscriber' to use workspace version.
  • apps/backend/kubernetes/executor/Cargo.toml
    • Added the 'remote' feature to 'flow-like-catalog'.
  • apps/backend/kubernetes/sink-trigger/Cargo.toml
    • Standardized 'tracing-subscriber' to use workspace version.
  • apps/backend/local/runtime/Cargo.toml
    • Added the 'remote' feature to 'flow-like-catalog'.
  • apps/backend/local/runtime/src/main.rs
    • Removed the 'token' field from the 'RunPayload' construction.
  • apps/desktop/public/flow/icons/interaction.svg
    • Added a new SVG icon for interactions.
  • apps/desktop/src-tauri/Cargo.toml
    • Added the 'local' feature to 'flow-like-catalog'.
    • Standardized 'tracing-subscriber' to use workspace version.
  • apps/desktop/src-tauri/src/functions.rs
    • Added the 'interaction' module.
  • apps/desktop/src-tauri/src/functions/interaction.rs
    • Added a new file implementing the 'respond_to_interaction' Tauri command.
  • apps/desktop/src-tauri/src/lib.rs
    • Registered the 'respond_to_interaction' Tauri command.
  • apps/web/lib/web-states/board-state.ts
    • Improved SSE event parsing to correctly handle multi-line 'data:' fields.
  • apps/web/lib/web-states/event-state.ts
    • Improved SSE event parsing to correctly handle multi-line 'data:' fields.
  • apps/web/public/flow/icons/interaction.svg
    • Added a new SVG icon for interactions.
  • packages/api/prisma/schema/app.prisma
    • Added a relation for 'Interaction' to the 'App' model.
  • packages/api/prisma/schema/interaction.prisma
    • Added a new Prisma schema file defining the 'Interaction' model and 'InteractionStatus' enum.
  • packages/api/prisma/schema/user.prisma
    • Added a relation for 'Interaction' to the 'User' model.
  • packages/api/src/backend_jwt.rs
    • Introduced 'InteractionResponder' as a new token type with a 5-minute TTL.
  • packages/api/src/entity/app.rs
    • Added 'Interaction' as a related entity.
  • packages/api/src/entity/interaction.rs
    • Added a new SeaORM entity file for the 'Interaction' model.
  • packages/api/src/entity/mod.rs
    • Exported the new 'interaction' module.
  • packages/api/src/entity/prelude.rs
    • Exported the 'Interaction' entity.
  • packages/api/src/entity/sea_orm_active_enums.rs
    • Added the 'InteractionStatus' enum.
  • packages/api/src/entity/user.rs
    • Added 'Interaction' as a related entity.
  • packages/api/src/execution/interaction_jwt.rs
    • Added a new file defining JWTs for interaction responders.
  • packages/api/src/execution/mod.rs
    • Exported the new 'interaction_jwt' module and its functions.
  • packages/api/src/lib.rs
    • Nested '/interaction' routes into the main router.
  • packages/api/src/middleware/error_reporting.rs
    • Included 'AppUser::Executor' in user ID extraction for error reporting.
  • packages/api/src/middleware/jwt.rs
    • Introduced 'ExecutorUser' struct and 'AppUser::Executor' enum variant.
    • Modified user and tier retrieval methods to use 'executor_scoped_sub()'.
    • Updated JWT middleware to handle and cache 'Executor' JWTs.
  • packages/api/src/routes.rs
    • Exported the new 'interaction' module.
  • packages/api/src/routes/ai/copilot.rs
    • Included 'AppUser::Executor' in user access token logic.
  • packages/api/src/routes/chat/completions.rs
    • Updated user subscription check to use 'executor_scoped_sub()'.
  • packages/api/src/routes/embeddings/embed.rs
    • Removed a comment regarding embedding tiers.
  • packages/api/src/routes/interaction.rs
    • Added a new file implementing API endpoints for creating and responding to human-in-the-loop interactions.
  • packages/api/src/state.rs
    • Added 'CachedAuth::Executor' variant for caching executor JWTs.
  • packages/catalog/Cargo.toml
    • Added 'local' and 'remote' features to control interaction handling based on execution environment.
  • packages/catalog/data/Cargo.toml
    • Added 'local' and 'remote' features for interaction handling.
  • packages/catalog/data/src/interaction/form.rs
    • Added a new file defining the 'FormInteraction' node logic, including JSON schema generation and value coercion.
  • packages/catalog/data/src/interaction/mod.rs
    • Added a new module for interaction nodes, including 'form', 'multiple_choice', 'single_choice', and 'wait'.
  • packages/catalog/data/src/interaction/multiple_choice.rs
    • Added a new file defining the 'MultipleChoiceInteraction' node logic.
  • packages/catalog/data/src/interaction/single_choice.rs
    • Added a new file defining the 'SingleChoiceInteraction' node logic.
  • packages/catalog/data/src/interaction/wait.rs
    • Added a new file implementing 'wait_for_interaction_response' with conditional logic for local vs. remote execution.
  • packages/catalog/data/src/lib.rs
    • Exported the new 'interaction' module.
  • packages/catalog/llm/src/agent/helpers.rs
    • Introduced 'pin_to_schema_define' to convert 'Pin' to 'HistoryJSONSchemaDefine' for LLM tools.
    • Updated 'generate_tool_from_function' to utilize 'pin_to_schema_define'.
  • packages/core/src/flow/execution/context.rs
    • Added a 'callback()' method to 'ExecutionContext'.
  • packages/executor/src/execute.rs
    • Configured 'profile.hub' from 'claims.callback_url' for remote interactions.
    • Updated token usage from 'request.token' to 'request.executor_jwt'.
  • packages/executor/src/streaming.rs
    • Passed 'claims.callback_url' to 'run_execution' for remote interactions.
    • Updated 'execute_inner' to use 'callback_url' for 'profile.hub'.
    • Updated token usage from 'request.token' to 'request.executor_jwt'.
  • packages/executor/src/types.rs
    • Removed the 'token' field from 'ExecutionRequest'.
  • packages/model-provider/src/llm.rs
    • Refactored 'DynamicCompletionModel' to lazily create models, resolving lifetime issues.
  • packages/types/src/interaction.rs
    • Added a new file defining TypeScript interfaces and helper functions for human-in-the-loop interactions.
  • packages/types/src/lib.rs
    • Exported the new 'interaction' module.
  • packages/ui/components/flow/flow-node.tsx
    • Added 'props.data.node.hash' to the dependency array for 'useEffect' to ensure updates on node hash changes.
  • packages/ui/components/flow/flow-pin.tsx
    • Expanded 'pinPropsAreEqual' to include 'pin.index', 'pin.name', 'pin.friendly_name', and 'pin.schema' for more accurate memoization.
  • packages/ui/components/interfaces/chat-default.tsx
    • Imported 'IInteractionRequest' for interaction handling.
    • Added 'onInteractions' callback to 'handleStreamCompletion'.
    • Implemented 'activeInteractions' state and 'addInteractions' callback.
    • Added 'handleRespondToInteraction' for both remote and local interaction responses.
    • Ensured cleanup of 'activeInteractions' on session changes.
    • Passed interaction-related props to child components.
  • packages/ui/components/interfaces/chat-default/chat.tsx
    • Imported 'IInteractionRequest' and defined 'ChatItem' types.
    • Added 'getInteractionCreatedAt' helper function.
    • Included 'activeInteractions' and 'onRespondToInteraction' props.
    • Utilized 'useMemo' to sort and group chat items and interaction items.
    • Integrated 'Interaction' and 'InteractionGroup' components for rendering.
  • packages/ui/components/interfaces/chat-default/event-processor.ts
    • Imported 'IInteractionRequest' and added 'interactions' to 'ProcessChatEventsResult'.
    • Processed 'interaction_request' events and appended them to the 'interactions' array.
  • packages/ui/components/interfaces/chat-default/interaction.tsx
    • Added a new file implementing UI components for various interaction types, including forms, choice selections, status badges, and response displays.
  • packages/ui/hooks/use-theme-gradient.ts
    • Updated iteration over 'document.styleSheets' and 'sheet.cssRules' to use 'Array.from' for improved compatibility.
  • packages/ui/lib/schema/index.ts
    • Exported the new 'interaction' schema.
  • packages/ui/lib/schema/interaction.ts
    • Added a new file defining TypeScript interfaces for human-in-the-loop interaction data structures.
  • thirdparty/frontend-builder/claude/flow-like-ui/SKILL.md
    • Added new documentation for the frontend builder skill.
  • thirdparty/frontend-builder/claude/flow-like-ui/references/bound-value-guide.md
    • Added new documentation for BoundValue and data binding.
  • thirdparty/frontend-builder/claude/flow-like-ui/references/components-reference.md
    • Added new documentation for A2UI components.
  • thirdparty/frontend-builder/claude/flow-like-ui/references/layout-examples.md
    • Added new documentation for A2UI layout examples.
  • thirdparty/frontend-builder/claude/flow-like-ui/references/styling-guide.md
    • Added new documentation for A2UI styling guide.
Activity
  • No human activity has been recorded on this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

| { type: "interaction"; data: IInteractionRequest; timestamp: number }
| { type: "interaction-group"; data: IInteractionRequest[]; timestamp: number };

function getInteractionCreatedAt(interaction: IInteractionRequest): number {
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../ui/select";
import { Switch } from "../../ui/switch";
import { Textarea } from "../../ui/textarea";
import { AlertCircle, CheckCircle2, ChevronDown, ChevronRight, ChevronUp, Clock, Plus, Trash2, XCircle } from "lucide-react";
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This is a substantial and well-executed pull request that introduces a powerful human-in-the-loop (HITL) interaction system. The changes span the entire stack, from the database schema and backend APIs to the frontend components and execution logic. The new interaction nodes in the catalog are a great addition, and the implementation of both local (polling) and remote (SSE) interaction handling is well-thought-out. The refactoring of the SSE parsing and the DynamicCompletionModel are also significant improvements to code quality and safety. My review includes a few suggestions for improving robustness and maintainability.

Comment on lines +211 to +212
let created_json = serde_json::to_string(&created_payload).unwrap_or_default();
yield Ok(Event::default().event("created").data(created_json));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using unwrap_or_default() on serde_json::to_string can hide potential serialization errors, which would result in an empty string being sent over SSE. While serialization of SseCreatedPayload is unlikely to fail, it's safer to handle the Result explicitly. Logging the error would be helpful for debugging if such an issue ever occurs. This also applies to line 235.

        let created_json = match serde_json::to_string(&created_payload) {
            Ok(json) => json,
            Err(e) => {
                tracing::error!("Failed to serialize SseCreatedPayload: {}", e);
                String::new()
            }
        };
        yield Ok(Event::default().event("created").data(created_json));

@@ -0,0 +1,1210 @@
use flow_like::flow::{
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This file is over 1200 lines long and contains a lot of distinct logic: schema generation from pins, extensive type coercion functions, node definition, and a large test suite. For better maintainability and readability, consider splitting this file into smaller, more focused modules. For example, you could have schema_builder.rs, coercion.rs, and node.rs within an interaction/form/ directory.

Comment on lines +154 to +159
pub async fn submit_interaction_response(interaction_id: &str, value: Value) -> bool {
let mut responses = INTERACTION_RESPONSES.lock().await;
if responses.contains_key(interaction_id) {
return false;
}
responses.insert(interaction_id.to_string(), value);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There's a potential race condition here. The check if responses.contains_key(interaction_id) and the subsequent responses.insert(...) are not an atomic operation. If two threads call this function concurrently for the same interaction_id, both could pass the contains_key check before either inserts the value, leading to one response being overwritten. Using the entry API would make this operation atomic and more robust.

Suggested change
pub async fn submit_interaction_response(interaction_id: &str, value: Value) -> bool {
let mut responses = INTERACTION_RESPONSES.lock().await;
if responses.contains_key(interaction_id) {
return false;
}
responses.insert(interaction_id.to_string(), value);
pub async fn submit_interaction_response(interaction_id: &str, value: Value) -> bool {
let mut responses = INTERACTION_RESPONSES.lock().await;
if let std::collections::hash_map::Entry::Vacant(e) = responses.entry(interaction_id.to_string()) {
e.insert(value);
} else {
// Already responded
return false;
}
drop(responses);

const id = `schema-${path.join("-")}`;
const label = property.title ?? path[path.length - 1] ?? "field";
const description = property.description;
const required = false;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The required variable is hardcoded to false inside renderSchemaField. This means that for forms generated from a JSON schema, the UI will not display the required field indicator (asterisk) next to the label, even if the schema specifies that a field is required. The missingRequired logic in FormInteractionForm correctly identifies required fields, but this isn't reflected visually at the field level. The isRequired status should be passed down as a prop to renderSchemaField.

@felix-schultz felix-schultz merged commit 1360536 into dev Feb 17, 2026
11 of 17 checks passed
@felix-schultz felix-schultz deleted the feature/520-short-human-in-the-loop branch February 17, 2026 14:09
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request introduces comprehensive support for human-in-the-loop interactions across the FlowLike platform, enabling workflows to pause and request user input through single choice, multiple choice, and form-based interactions. The implementation spans backend infrastructure, desktop/web frontends, and node execution logic.

Changes:

  • Added Interaction database model with SSE-based lifecycle management and JWT-secured response endpoints
  • Implemented three interaction node types (single choice, multiple choice, form) with JSON Schema-based form generation
  • Enhanced chat interface to display and handle interaction requests with countdown timers and response submission
  • Added Tauri command for desktop interaction responses and improved SSE parsing for multi-line data fields

Reviewed changes

Copilot reviewed 68 out of 71 changed files in this pull request and generated no comments.

Show a summary per file
File Description
packages/api/prisma/schema/interaction.prisma Defines lean interaction model with status tracking and expiration indices
packages/api/src/routes/interaction.rs SSE streaming endpoint for interaction lifecycle and JWT-secured response handler
packages/api/src/execution/interaction_jwt.rs JWT signing/verification for interaction responders
packages/catalog/data/src/interaction/form.rs Form interaction node with JSON Schema generation from callback function pins
packages/catalog/data/src/interaction/single_choice.rs Single choice interaction with freeform option support
packages/catalog/data/src/interaction/multiple_choice.rs Multiple choice with min/max selection constraints
packages/ui/components/interfaces/chat-default/interaction.tsx React components for rendering and responding to interactions
packages/ui/components/interfaces/chat-default.tsx Integration of interaction state and response handling
apps/desktop/src-tauri/src/functions/interaction.rs Tauri command for submitting interaction responses
apps/web/lib/web-states/board-state.ts Fixed SSE parsing for multi-line data fields
packages/executor/src/types.rs Removed unused token field from execution requests
Comments suppressed due to low confidence (7)

thirdparty/frontend-builder/claude/flow-like-ui/SKILL.md:1

  • Corrected spelling of 'recieve' to 'receive' in flow-like-ui/references/styling-guide.md
    packages/ui/hooks/use-theme-gradient.ts:1
  • Converting iterables to arrays with Array.from() is unnecessary when iterating with for-of loops, as they work directly with iterables. The original code was correct.
    packages/model-provider/src/llm.rs:1
  • Changing dynamic_model from &self to self breaks the API by consuming the ModelConstructor. This prevents reusing the same constructor for multiple models, which is a common use case.
    packages/api/src/routes/chat/completions.rs:1
  • Switching from sub() to executor_scoped_sub() allows Executor JWTs to invoke LLM endpoints. Verify this is intentional and that executor tokens have appropriate usage tracking/billing, as they bypass normal user auth.
    packages/api/src/middleware/jwt.rs:1
  • The tracking_id method now accepts Executor JWTs via executor_scoped_sub(). Ensure usage tracking correctly attributes executor-initiated requests, as they may have different billing implications than user-initiated requests.
    packages/catalog/data/src/interaction/wait.rs:1
  • The function returns an empty string if execution_cache is None, which may cause unclear errors downstream. Consider returning a Result with a descriptive error message like "No app_id available in execution context for remote interaction".
    packages/catalog/data/src/interaction/form.rs:1
  • The warning about multiple callback functions is logged but not visible to users who didn't enable debug logging. Consider adding a clearer indicator in the UI or returning this as part of the validation result.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Short] Human in the Loop

2 participants