//! # Fluent Command Line Interface (CLI) Application.
//!
//! This crate is the entry point for the Fluent CLI, enabling interaction with Flowise AI workflows
//! via the command line. The application handles all facets of user interaction, including parsing command-line
//! arguments, managing configurations, initializing logging features, and executing the core application logic.
//!
//! # Workflow
//!
//! The execution flow of the main function in `main.rs` is as follows:
//!
//! 1. **Command-line Parsing**: Utilizes the `CliOpts` struct from the `cli` module to parse the command-line
//! arguments provided by the user.
//! 2. **Configuration Reading**: Reads the configuration file using `read_config` function from the `config` module.
//! 3. **Verbosity Calculation**: Determines the appropriate level of verbosity for logging by examining
//! the `--quiet` and `--verbose` command-line options.
//! 4. **Logging Initialization**: Sets up logging based on the verbosity level using the `stderrlog` crate,
//! and considers the `--timestamp` option if provided.
//! 5. **Shell Completions Generation**: If the `--generate-completions` flag is supplied, the application
//! will generate completion scripts for the shell specified and then exit.
//! 6. **Application Execution**: Executes the core application logic by invoking the `run` function from the
//! `app` module, with the parsed `CliOpts` passed as an argument.
//!
//! Errors encountered during these steps are handled using the `anyhow` crate which provides a convenient
//! way to return errors with context. Any errors will cause the application to terminate with a non-zero status code.
//!
//! # Modules
//!
//! This application is composed of multiple modules, each responsible for a distinct aspect of the functionality:
//!
//! - `app`: The nucleus of the application logic; includes functions related to configuration parsing, HTTP request
//! formation, command-line option handling, and interpreting responses from AI workflows.
//! - `cli`: Houses the definitions for parsing command-line arguments, including the `CliOpts` struct.
//! - `config`: Focuses on accessing and parsing the application's configuration file.
//! - `http`: Defines abstractions for performing HTTP requests to the AI workflow services.
//! - `utils`: A collection of auxiliary functions for file manipulation, path operations, string processing, and more.
//! - `helpers`: Provides supplementary functions and constants essential throughout the application, including template
//! helpers for the CLI interface.
//!
//! # Logging
//!
//! The logging is facilitated by the `stderrlog` crate which provides a simple logger configured via environment variables
//! and command-line options. It is set up to log to `stderr` with varying verbosity levels controlled by the user at runtime.
//!
//! # Panics
//!
//! Panics are a Rust mechanism for handling unexpected situations. This application is designed to avoid situations
//! that might cause panics and does not intentionally contain any code that would cause unwinding (panic! functionality).
//! The `panic = 'abort'` directive could potentially be enabled for release builds to reduce binary size at the cost of
//! panicking cleanup capabilities; the directive is currently commented out.
//!
//! # Error Handling
//!
//! Error handling is critically managed via the `anyhow` crate, which provides idiomatic ways of propagating errors.
//! If errors occur during the startup or running phases of the application, they will be returned and cause the binary to
//! exit with an error status code.
//!
//! # Safety
//!
//! This application takes Rust's safety guarantees seriously. As such, the use of `unsafe` code blocks is explicitly forbidden
//! through the `#![forbid(unsafe_code)]` attribute.
//!
//! # Compiler Directives
//!
//! The application uses several compiler directives (attributes) to maintain code quality and safety:
//!
//! - `warn(warnings, rust_2018_idioms)`: Enables certain compiler warnings to encourage idiomatic Rust code.
//! - `warn(clippy::all, clippy::pedantic, clippy::restriction)`: Enables various levels of Clippy lints which are checks
//! for common mistakes and improvements for Rust code.
//! - `allow(clippy::float_arithmetic, clippy::implicit_return, clippy::needless_return)`: Disables specific Clippy lints
//! that are overly pedantic for this project's scope.
//!
//! # Features
//!
//! The `Cargo.toml` file specifies the application's metadata, dependencies, development dependencies, and build profiles.
//! Notable dependencies include `structopt`, `anyhow`, `tokio`, `clap`, among others, to handle asynchronous runtime, command-line
//! parsing, error handling, and HTTP requests. The `[profile.release]` section contains configuration to optimize the release
//! builds for size and performance.
//!
//! # Usage
//!
//! To run the Fluent CLI, you must first compile the application with Cargo, then you may use the following command to interact
//! with the application:
//!
//! ```
//! fluent [FLAGS] [OPTIONS]
//! ```
//!
//! Flags and options can be determined by running `fluent --help`.
//!
//! Please consult the specific module documentation for deeper insight into each module's responsibilities and usage.
//! # Fluent Command Line Interface (CLI) Application.
//!
//! This crate is the entry point for the Fluent CLI, enabling interaction with Flowise AI workflows
//! via the command line. The application handles all facets of user interaction, including parsing command-line
//! arguments, managing configurations, initializing logging features, and executing the core application logic.
//!
//! # Workflow
//!
//! The execution flow of the main function in `main.rs` is as follows:
//!
//! 1. **Command-line Parsing**: Utilizes the `CliOpts` struct from the `cli` module to parse the command-line
//! arguments provided by the user.
//! 2. **Configuration Reading**: Reads the configuration file using `read_config` function from the `config` module.
//! 3. **Verbosity Calculation**: Determines the appropriate level of verbosity for logging by examining
//! the `--quiet` and `--verbose` command-line options.
//! 4. **Logging Initialization**: Sets up logging based on the verbosity level using the `stderrlog` crate,
//! and considers the `--timestamp` option if provided.
//! 5. **Shell Completions Generation**: If the `--generate-completions` flag is supplied, the application
//! will generate completion scripts for the shell specified and then exit.
//! 6. **Application Execution**: Executes the core application logic by invoking the `run` function from the
//! `app` module, with the parsed `CliOpts` passed as an argument.
//!
//! Errors encountered during these steps are handled using the `anyhow` crate which provides a convenient
//! way to return errors with context. Any errors will cause the application to terminate with a non-zero status code.
//!
//! # Modules
//!
//! This application is composed of multiple modules, each responsible for a distinct aspect of the functionality:
//!
//! - `app`: The nucleus of the application logic; includes functions related to configuration parsing, HTTP request
//! formation, command-line option handling, and interpreting responses from AI workflows.
//! - `cli`: Houses the definitions for parsing command-line arguments, including the `CliOpts` struct.
//! - `config`: Focuses on accessing and parsing the application's configuration file.
//! - `http`: Defines abstractions for performing HTTP requests to the AI workflow services.
//! - `utils`: A collection of auxiliary functions for file manipulation, path operations, string processing, and more.
//! - `helpers`: Provides supplementary functions and constants essential throughout the application, including template
//! helpers for the CLI interface.
//!
//! # Logging
//!
//! The logging is facilitated by the `stderrlog` crate which provides a simple logger configured via environment variables
//! and command-line options. It is set up to log to `stderr` with varying verbosity levels controlled by the user at runtime.
//!
//! # Panics
//!
//! Panics are a Rust mechanism for handling unexpected situations. This application is designed to avoid situations
//! that might cause panics and does not intentionally contain any code that would cause unwinding (panic! functionality).
//! The `panic = 'abort'` directive could potentially be enabled for release builds to reduce binary size at the cost of
//! panicking cleanup capabilities; the directive is currently commented out.
//!
//! # Error Handling
//!
//! Error handling is critically managed via the `anyhow` crate, which provides idiomatic ways of propagating errors.
//! If errors occur during the startup or running phases of the application, they will be returned and cause the binary to
//! exit with an error status code.
//!
//! # Safety
//!
//! This application takes Rust's safety guarantees seriously. As such, the use of `unsafe` code blocks is explicitly forbidden
//! through the `#![forbid(unsafe_code)]` attribute.
//!
//! # Compiler Directives
//!
//! The application uses several compiler directives (attributes) to maintain code quality and safety:
//!
//! - `warn(warnings, rust_2018_idioms)`: Enables certain compiler warnings to encourage idiomatic Rust code.
//! - `warn(clippy::all, clippy::pedantic, clippy::restriction)`: Enables various levels of Clippy lints which are checks
//! for common mistakes and improvements for Rust code.
//! - `allow(clippy::float_arithmetic, clippy::implicit_return, clippy::needless_return)`: Disables specific Clippy lints
//! that are overly pedantic for this project's scope.
//!
//! # Features
//!
//! The `Cargo.toml` file specifies the application's metadata, dependencies, development dependencies, and build profiles.
//! Notable dependencies include `structopt`, `anyhow`, `tokio`, `clap`, among others, to handle asynchronous runtime, command-line
//! parsing, error handling, and HTTP requests. The `[profile.release]` section contains configuration to optimize the release
//! builds for size and performance.
//!
//! # Usage
//!
//! To run the Fluent CLI, you must first compile the application with Cargo, then you may use the following command to interact
//! with the application:
//!
//! ```
//! fluent [FLAGS] [OPTIONS]
//! ```
//!
//! Flags and options can be determined by running `fluent --help`.
//!
//! Please consult the specific module documentation for deeper insight into each module's responsibilities and usage.
//! # Fluent Command Line Interface (CLI) Application.
//!
//! This crate is the entry point for the Fluent CLI, enabling interaction with Flowise AI workflows
//! via the command line. The application handles all facets of user interaction, including parsing command-line
//! arguments, managing configurations, initializing logging features, and executing the core application logic.
//!
//! # Workflow
//!
//! The execution flow of the main function in `main.rs` is as follows:
//!
//! 1. **Command-line Parsing**: Utilizes the `CliOpts` struct from the `cli` module to parse the command-line
//! arguments provided by the user.
//! 2. **Configuration Reading**: Reads the configuration file using `read_config` function from the `config` module.
//! 3. **Verbosity Calculation**: Determines the appropriate level of verbosity for logging by examining
//! the `--quiet` and `--verbose` command-line options.
//! 4. **Logging Initialization**: Sets up logging based on the verbosity level using the `stderrlog` crate,
//! and considers the `--timestamp` option if provided.
//! 5. **Shell Completions Generation**: If the `--generate-completions` flag is supplied, the application
//! will generate completion scripts for the shell specified and then exit.
//! 6. **Application Execution**: Executes the core application logic by invoking the `run` function from the
//! `app` module, with the parsed `CliOpts` passed as an argument.
//!
//! Errors encountered during these steps are handled using the `anyhow` crate which provides a convenient
//! way to return errors with context. Any errors will cause the application to terminate with a non-zero status code.
//!
//! # Modules
//!
//! This application is composed of multiple modules, each responsible for a distinct aspect of the functionality:
//!
//! - `app`: The nucleus of the application logic; includes functions related to configuration parsing, HTTP request
//! formation, command-line option handling, and interpreting responses from AI workflows.
//! - `cli`: Houses the definitions for parsing command-line arguments, including the `CliOpts` struct.
//! - `config`: Focuses on accessing and parsing the application's configuration file.
//! - `http`: Defines abstractions for performing HTTP requests to the AI workflow services.
//! - `utils`: A collection of auxiliary functions for file manipulation, path operations, string processing, and more.
//! - `helpers`: Provides supplementary functions and constants essential throughout the application, including template
//! helpers for the CLI interface.
//!
//! # Logging
//!
//! The logging is facilitated by the `stderrlog` crate which provides a simple logger configured via environment variables
//! and command-line options. It is set up to log to `stderr` with varying verbosity levels controlled by the user at runtime.
//!
//! # Panics
//!
//! Panics are a Rust mechanism for handling unexpected situations. This application is designed to avoid situations
//! that might cause panics and does not intentionally contain any code that would cause unwinding (panic! functionality).
//! The `panic = 'abort'` directive could potentially be enabled for release builds to reduce binary size at the cost of
//! panicking cleanup capabilities; the directive is currently commented out.
//!
//! # Error Handling
//!
//! Error handling is critically managed via the `anyhow` crate, which provides idiomatic ways of propagating errors.
//! If errors occur during the startup or running phases of the application, they will be returned and cause the binary to
//! exit with an error status code.
//!
//! # Safety
//!
//! This application takes Rust's safety guarantees seriously. As such, the use of `unsafe` code blocks is explicitly forbidden
//! through the `#![forbid(unsafe_code)]` attribute.
//!
//! # Compiler Directives
//!
//! The application uses several compiler directives (attributes) to maintain code quality and safety:
//!
//! - `warn(warnings, rust_2018_idioms)`: Enables certain compiler warnings to encourage idiomatic Rust code.
//! - `warn(clippy::all, clippy::pedantic, clippy::restriction)`: Enables various levels of Clippy lints which are checks
//! for common mistakes and improvements for Rust code.
//! - `allow(clippy::float_arithmetic, clippy::implicit_return, clippy::needless_return)`: Disables specific Clippy lints
//! that are overly pedantic for this project's scope.
//! - `forbid(unsafe_code)`: Prohibits the use of unsafe Rust code blocks to ensure safety.
//!
//! # Features
//!
//! The `Cargo.toml` file specifies the application's metadata, dependencies, development dependencies, and build profiles.
//! Notable dependencies include `structopt`, `anyhow`, `tokio`, `clap`, among others, to handle asynchronous runtime, command-line
//! parsing, error handling, and HTTP requests. The `[profile.release]` section contains configuration to optimize the release
//! builds for size and performance.
//!
//! # Usage
//!
//! To run the Fluent CLI, you must first compile the application with Cargo, then you may use the following command to interact
//! with the application:
//!
//! ```
//! fluent [FLAGS] [OPTIONS]
//! ```
//!
//! Flags and options can be determined by running `fluent --help`.
//!
//! Please consult the specific module documentation for deeper insight into each module's responsibilities and usage.
//! # fluent
//!
//! `fluent` is a command-line utility that interacts with Flowise AI workflows, providing a Rust
//! implementation of various features including configuration management, HTTP requests to call AI
//! workflows, command-line interface (CLI) processing, response handling, and output formatting.
//!
//! ## Features
//!
//! - Read and parse the configuration from a JSON file
//! - Generate bash completion scripts for command-line options
//! - Handle completions for shells like Bash by parsing configured workflow names
//! - Process command-line input and environment variables to execute workflows
//! - Construct and send HTTP POST requests with configurable headers and query parameters
//! - Download and rename image files referenced in Markdown content
//! - Generate an HTML client for interactive conversations with the Flowise AI chatbot
//! - Format input from various sources such as text files or standard input
//!
//! ## Usage
//!
//! The `run` function is the primary entry point for using the tool. It takes parsed CLI
//! options and performs the necessary actions to interact with the Flowise AI workflows.
//!
//! ```rust,no_run
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let opts = CliOpts::from_args();
//! if let Err(e) = run(opts).await {
//! eprintln!("Application error: {}", e);
//! std::process::exit(1);
//! }
//! Ok(())
//! }
//! ```
//!
//! ## Configuration
//!
//! `Config` is a struct that represents application configuration loaded from a JSON file. It
//! includes workflow definitions, HTTP request settings, and formatting options.
//!
//! ## Command-Line Options
//!
//! `CliOpts` is a struct that represents the parsed command-line options. It includes flags for
//! generating completions, specifying the workflow, and providing inputs such as questions and
//! context.
//!
//! ## Error Handling
//!
//! All functions return `Result` types, and any errors are handled using the `anyhow` crate,
//! which provides context and error chains for easier debugging.
//!
//! ## Dependencies
//!
//! This module depends on several external crates such as `anyhow`, `reqwest`, `clap`, `tokio`,
//! `config`, `serde_json`, and others for handling JSON parsing, HTTP requests, CLI processing, and
//! asynchronous execution.
//!
//! ## Examples
//!
//! ### Generate Completion Script
//!
//! Generate a Bash completion script for the `fluent` CLI tool:
//!
//! ```rust,no_run
//! async fn generate_completion_script() -> Result<()> {
//! handle_completions().await
//! }
//! ```
//!
//! ### Call Fluent AI Workflow
//!
//! Create and send an HTTP POST request to call a Fluent AI workflow and handle the response:
//!
//! ```rust,no_run
//! async fn call_fluent_workflow() -> Result<()> {
//! let config = read_config()?;
//! let opts = CliOpts::from_args();
//! let combined_input = "Your input goes here";
//! let skin = configure_skin(&config.skin_config);
//! call_and_handle_flow(&config, &opts, &combined_input, &skin, String::new(), String::new()).await
//! }
//! ```
//!
//! ### Download Images from Markdown
//!
//! Extract and download image files from Markdown content to a specified directory:
//!
//! ```rust,no_run
//! async fn download_images(content: &str, destination_folder: &PathBuf) -> Result<()> {
//! download_images_from_markdown(content, destination_folder).await
//! }
//! ```
//!
//! ## Testing
//!
//! Unit tests are provided for key functionalities such as configuration parsing and HTTP request
//! handling.
//!
//! To run tests, use the `cargo test` command.
//!
//! ### Example Test
//!
//! ```rust,no_run
//! #[cfg(test)]
//! mod tests {
//! use super::*;
//!
//! #[tokio::test]
//! async fn test_valid_configuration() -> Result<()> {
//! let config = read_config()?;
//! assert!(config.flows.len() > 0, "No workflows configured.");
//! Ok(())
//! }
//! }
//! ```
//!
//! ## License
//!
//! This project is licensed under [MIT License](https://opensource.org/licenses/MIT).
//!
//! ## Contribution
//!
//! Contributions are welcome through pull requests and issues on GitHub. Please adhere to the
//! project's [code of conduct](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html).
Installation
Prerequisites
Before installing fluent
, ensure you have the following prerequisites installed on your system:
- Rust (latest stable version): https://www.rust-lang.org/tools/install
- Git (for cloning the repository): https://git-scm.com/downloads
System Requirements
- Operating System: Linux, macOS, or Windows
- Minimum RAM: 512MB
- Disk Space: 50MB
Installation Guide
Downloading the Source Code
To get the latest version of fluent
, clone the repository from GitHub:
git clone https://github.com/yourusername/fluent.git
cd fluent
Building from Source
fluent
is written in Rust, so you will need to compile it from source:
cargo build --release
This command compiles the application in release mode, optimizing the binary for performance. The compiled binary will be located in ./target/release/fluent
.
Installing the Binary
After building fluent
, you can install it to your system path to make it easily accessible from the command line:
sudo cp ./target/release/fluent /usr/local/bin/
This command copies the fluent
binary to /usr/local/bin/
, a common directory for user-installed binaries. You may need to adjust the destination directory based on your system configuration and preferences.
Verifying the Installation
To verify that fluent
has been installed correctly, you can run:
fluent --version
This command should output the version number of fluent
, indicating that it is correctly installed and accessible from your system path.
//! # fluent
//!
//! `fluent` is a command-line utility that interacts with Flowise AI workflows, providing a Rust
//! implementation of various features including configuration management, HTTP requests to call AI
//! workflows, command-line interface (CLI) processing, response handling, and output formatting.
//!
//! ## Features
//!
//! - Read and parse the configuration from a JSON file
//! - Generate bash completion scripts for command-line options
//! - Handle completions for shells like Bash by parsing configured workflow names
//! - Process command-line input and environment variables to execute workflows
//! - Construct and send HTTP POST requests with configurable headers and query parameters
//! - Download and rename image files referenced in Markdown content
//! - Generate an HTML client for interactive conversations with the Flowise AI chatbot
//! - Format input from various sources such as text files or standard input
//!
//! ## Usage
//!
//! The `run` function is the primary entry point for using the tool. It takes parsed CLI
//! options and performs the necessary actions to interact with the Flowise AI workflows.
//!
//! ```rust,no_run
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let opts = CliOpts::from_args();
//! if let Err(e) = run(opts).await {
//! eprintln!("Application error: {}", e);
//! std::process::exit(1);
//! }
//! Ok(())
//! }
//! ```
//!
//! ## Configuration
//!
//! `Config` is a struct that represents application configuration loaded from a JSON file. It
//! includes workflow definitions, HTTP request settings, and formatting options.
//!
//! ## Command-Line Options
//!
//! `CliOpts` is a struct that represents the parsed command-line options. It includes flags for
//! generating completions, specifying the workflow, and providing inputs such as questions and
//! context.
//!
//! ## Error Handling
//!
//! All functions return `Result` types, and any errors are handled using the `anyhow` crate,
//! which provides context and error chains for easier debugging.
//!
//! ## Dependencies
//!
//! This module depends on several external crates such as `anyhow`, `reqwest`, `clap`, `tokio`,
//! `config`, `serde_json`, and others for handling JSON parsing, HTTP requests, CLI processing, and
//! asynchronous execution.
//!
//! ## Examples
//!
//! ### Generate Completion Script
//!
//! Generate a Bash completion script for the `fluent` CLI tool:
//!
//! ```rust,no_run
//! async fn generate_completion_script() -> Result<()> {
//! handle_completions().await
//! }
//! ```
//!
//! ### Call Fluent AI Workflow
//!
//! Create and send an HTTP POST request to call a Fluent AI workflow and handle the response:
//!
//! ```rust,no_run
//! async fn call_fluent_workflow() -> Result<()> {
//! let config = read_config()?;
//! let opts = CliOpts::from_args();
//! let combined_input = "Your input goes here";
//! let skin = configure_skin(&config.skin_config);
//! call_and_handle_flow(&config, &opts, &combined_input, &skin, String::new(), String::new()).await
//! }
//! ```
//!
//! ### Download Images from Markdown
//!
//! Extract and download image files from Markdown content to a specified directory:
//!
//! ```rust,no_run
//! async fn download_images(content: &str, destination_folder: &PathBuf) -> Result<()> {
//! download_images_from_markdown(content, destination_folder).await
//! }
//! ```
//!
//! ## Testing
//!
//! Unit tests are provided for key functionalities such as configuration parsing and HTTP request
//! handling.
//!
//! To run tests, use the `cargo test` command.
//!
//! ### Example Test
//!
//! ```rust,no_run
//! #[cfg(test)]
//! mod tests {
//! use super::*;
//!
//! #[tokio::test]
//! async fn test_valid_configuration() -> Result<()> {
//! let config = read_config()?;
//! assert!(config.flows.len() > 0, "No workflows configured.");
//! Ok(())
//! }
//! }
//! ```
//!
//! ## License
//!
//! This project is licensed under [MIT License](https://opensource.org/licenses/MIT).
//!
//! ## Contribution
//!
//! Contributions are welcome through pull requests and issues on GitHub. Please adhere to the
//! project's [code of conduct](https://www.contributor-covenant.org/version/1/4/code-of-conduct.html).
#[derive(Debug, StructOpt)]
#[structopt(
= "Fluent",
name = HELP_TEMPLATE,
template = "Interacts with Flowise AI workflows",
about = structopt::clap::AppSettings::ColoredHelp
global_setting )]
pub struct CliOpts {
#[allow(clippy::missing_docs_in_private_items)]
#[structopt(flatten)]
pub boilerplate: BoilerplateOpts,
#[structopt(required = true)]
pub name: String,
#[structopt()]
pub question: Option<String>,
#[structopt(parse(from_os_str))]
pub outline_path_positional: Option<std::path::PathBuf>,
#[structopt()]
pub context: Option<String>,
#[structopt(short = "o", long = "outline-path", parse(from_os_str))]
pub outline_path_flag: Option<std::path::PathBuf>,
/// Generate Bash Shell Autocompletion script to source from config
#[structopt(long = "generate-completions")]
pub generate_completions: bool,
/// Write a completion definition for the specified shell to stdout (bash, zsh, etc.)
#[structopt(long, value_name = "shell")]
pub(crate) dump_completions: Option<structopt::clap::Shell>,
#[structopt(short = "p", long = "parse-structured")]
pub parse_structured: bool,
#[structopt(short = "s",long = "system-prompt-override")]
pub system_prompt_override: Option<String>,
#[structopt(short = "f", long = "system-prompt-override-file", parse(from_os_str))]
pub system_prompt_override_file: Option<std::path::PathBuf>,
#[structopt(short = "i", long = "image-folder-path", parse(from_os_str))]
pub image_folder_path: Option<std::path::PathBuf>,
#[structopt(short = "m",long = "markdown")]
pub markdown: bool,
/// Include extra data in the HTTP request
#[structopt(short = "h", long = "include-extra")]
pub include_extra_data: bool,
/// Generate HTML chat client
#[structopt(short = "g", long = "generate-html-chat-client")]
pub generate_html_chat_client: bool,
}
//! Configuration module for the Fluent application.
//!
//! This module provides structures and functions for handling the various
//! configuration options available to the Fluent app. It allows the application
//! to manage different aspects of the configuration such as HTTP requests,
//! paths, regular expressions, defaults, styling, and skin configurations.
//! The configuration can be read from a JSON file whose path is specified via
//! an environment variable, and used to modify the behaviour of the application.
use anyhow::{Result, Context};
use serde::{Deserialize, Serialize};
use std::{fs};
use std::path::Path;
/// Structure representing the configuration for HTTP requests.
#[derive(Debug, Deserialize, Serialize)]
pub struct HttpRequestConfig {
pub timeout: u64,
}
/// Structure representing different file paths used in the application.
#[derive(Debug, Deserialize, Serialize)]
pub struct PathsConfig {
pub config_path: String,
}
/// Structure for regex pattern configuration.
#[derive(Debug, Deserialize, Serialize)]
pub struct RegexConfig {
pub url_regex: String,
}
/// Structure for default configuration values.
#[derive(Debug, Deserialize, Serialize)]
pub struct DefaultsConfig {
pub verbosity: u64,
}
/// Configuration for styling console output.
#[derive(Debug, Deserialize, Serialize)]
pub struct StylingConfig {
pub error: String,
pub success: String,
}
/// Configuration for customizing the appearance ("skin") of console output.
#[derive(Debug, Deserialize, Serialize)]
pub struct SkinConfig {
pub headers_fg: String,
pub bold_fg: String,
pub italic_fg: String, // Added
pub italic_bg: String, // Added
pub bullet: String,
pub bullet_char: char,
pub quote_mark_fg: String, // Added
pub code_block_margin: u8,
pub code_block_align: String,
pub code_block_bg: String,
pub italic_attrs: Vec<String>,
pub bold_attrs: Vec<String>, // Added
pub bold_bg: String, // Added
pub list_indent: u8, // Added
pub list_start: String, // Added
pub list_spacing: u8, // Added
pub list_char: String, // Added
pub list_margin: u8, // Added
pub list_align: String, // Added
pub list_bg: String, // Added
pub list_fg: String, // Added
pub list_padding: u8, // Added
pub italic_fg_bg: Vec<String>,
pub quote_mark: String,
}
/// Main configuration object that encapsulates all the settings.
#[derive(Debug, Deserialize, Serialize)]
pub struct Config {
pub flows: Vec<Flow>,
: HttpRequestConfig,
http_requestpub(crate) combined_input_format: String,
pub(crate) processing_message: String,
pub paths: PathsConfig,
: RegexConfig,
regex: DefaultsConfig,
defaults: StylingConfig,
stylingpub(crate) skin_config: SkinConfig,
}
/// Represents the flow of operations, which includes HTTP requests and configuration overrides.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Flow {
pub name: String,
pub url: String,
pub method: String,
pub headers: serde_json::Value,
#[serde(rename = "overrideConfig")]
pub override_config: Option<serde_json::Value>,
}
/// Reads the configuration from a JSON file whose path is specified by the `FLUENT_CONFIG_PATH` environment variable.
///
/// # Errors
///
/// Returns an `Err` variant of `anyhow::Result` if:
/// - `FLUENT_CONFIG_PATH` environment variable is not set.
/// - The configuration file does not exist at the specified path.
/// - There is a failure reading the configuration file.
/// - There is an error parsing the JSON content into the `Config` structure.
///
/// # Examples
///
/// ```
/// let config = read_config().expect("Failed to read the configuration.");
/// ```
pub fn read_config() -> anyhow::Result<Config> {
let config_path = std::env::var("FLUENT_CONFIG_PATH").expect("FLUENT_CONFIG_PATH environment variable is not set.");
if !Path::new(&config_path).exists() {
return Err(anyhow::anyhow!("Configuration file does not exist at {}", config_path));
}
let config_content = fs::read_to_string(&config_path)
.with_context(|| format!("Failed to read config file at {}", config_path))?;
match serde_json::from_str::<Config>(&config_content) {
Ok(config) => {
// Add a debug print or log here to inspect the loaded config
//println!("Loaded config: {:?}", config);
Ok(config)
},
Err(e) => {
eprintln!("Failed to parse the configuration file: {}", e);
// Directly print line and column information
eprintln!("Error on line: {}, column: {}", e.line(), e.column());
Err(e.into()) // Explicitly convert serde_json::Error into anyhow::Error
}
}
}
//! # Examples
//!
//! ### Call Fluent AI Workflow
//!
//! Create and send an HTTP POST request to call a Fluent AI workflow and handle the response:
//!
//! ```rust,no_run
//! async fn call_fluent_workflow() -> Result<()> {
//! let config = read_config()?;
//! let opts = CliOpts::from_args();
//! let combined_input = "Your input goes here";
//! let skin = configure_skin(&config.skin_config);
//! call_and_handle_flow(&config, &opts, &combined_input, &skin, String::new(), String::new()).await
//! }
//! ```
//!
//! ### Generate Completion Script
//!
//! Generate a Bash completion script for the `fluent` CLI tool:
//!
//! ```rust,no_run
//! async fn generate_completion_script() -> Result<()> {
//! handle_completions().await
//! }
//! ```
//!
//! ### Download Images from Markdown
//!
//! Extract and download image files from Markdown content to a specified directory:
//!
//! ```rust,no_run
//! async fn download_images(content: &str, destination_folder: &PathBuf) -> Result<()> {
//! download_images_from_markdown(content, destination_folder).await
//! }
//! ```
//!
//! ### Generate HTML Chat Client
//!
//! Generate an HTML file for interacting with the Flowise AI chatbot:
//!
//! ```rust,no_run
//! fn generate_html_chat_client(flow_url: &str, flow_name: &str, output_dir: &Path) -> Result<(), std::io::Error> {
//! let chatflowid = flow_url.split("/").last().ok_or_else(|| std::io::Error::new(std::io::ErrorKind::Other, "Failed to extract chatflowid"))?;
//!
//! let html_content = format!(r#"<!DOCTYPE html>
//! <html lang="en">
//! <head>
//! <meta charset="UTF-8">
//! <meta name="viewport" content="width=device-width, initial-scale=1.0">
//! <title>{flow_name} Chatbot</title>
//! </head>
//! <body>
//! <!-- Embedded Chatbot -->
//! <flowise-fullchatbot></flowise-fullchatbot>
//! <script type="module">
//! import Chatbot from "https://cdn.jsdelivr.net/npm/flowise-embed/dist/web.js"
//! Chatbot.initFull({{
//! chatflowid: "{chatflowid}",
//! apiHost: "http://127.0.0.1:3000",
//! }})
//! </script>
//! </body>
//! </html>"#, flow_name=flow_name, chatflowid=chatflowid);
//!
//! // Sanitize the flow name to create a valid filename
//! let sanitized_flow_name = flow_name.replace(|c: char| !c.is_alphanumeric(), "_");
//! let file_path = output_dir.join(format!("chatbot_{}.html", sanitized_flow_name));
//! let file_path_clone = file_path.clone();
//! let mut file = File::create(file_path)?;
//!
//! file.write_all(html_content.as_bytes())?;
//! eprintln!("HTML chat client file generated successfully at {}.", file_path_clone.display());
//! Ok(())
//! }
//! ```

## Contributing
, and they are greatly appreciated! Every little bit helps, and credit will always be given.
Contributions are welcome
### Types of Contributions
#### Report Bugs
://github.com/yourproject/yourproject/issues.
Report bugs at https
, please include:
If you are reporting a bug
- Your operating system name and version.
- Any details about your local setup that might be helpful in troubleshooting.
- Detailed steps to reproduce the bug.
#### Fix Bugs
for bugs. Anything tagged with "bug" and "help wanted" is open to whoever wants to implement it.
Look through the GitHub issues
#### Implement Features
for features. Anything tagged with "enhancement" and "help wanted" is open to whoever wants to implement it.
Look through the GitHub issues
Write Documentation
####
use more documentation, whether as part of the official Fluent docs, in docstrings, or even on the web in blog posts, articles, and such.
Fluent could always
#### Submit Feedback
://github.com/yourproject/yourproject/issues.
The best way to send feedback is to file an issue at https
:
If you are proposing a feature
- Explain in detail how it would work.
- Keep the scope as narrow as possible, to make it easier to implement.
- Remember that this is a volunteer-driven project, and that contributions are welcome :)
Started!
### Get
? Here's how to set up `fluent` for local development.
Ready to contribute
1. Fork the `fluent` repo on GitHub.
2. Clone your fork locally:
git clone git@github.com:yourname/fluent.git 3. Create a branch for local development:
git checkout -b name-of-your-bugfix-or-feature Now you can make your changes locally. 4. When you're done making changes, check that your changes pass the tests:
cargo test 5. Commit your changes and push your branch to GitHub:
git add . git commit -m “Your detailed description of your changes.” git push origin name-of-your-bugfix-or-feature ``` 6. Submit a pull request through the GitHub website.
Pull Request Guidelines
Before you submit a pull request, check that it meets these guidelines:
- The pull request should include tests that cover the new functionality or fixes any issues.
- If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the README.md.
- The pull request should work for Rust. Check https://github.com/yourname/fluent/actions and make sure that the tests pass for all supported Rust versions.
Tips
To run a subset of tests:
cargo test test_module::test_function
Code of Conduct
Please note that the fluent
project is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms.
// License
//
// FluentCLI is licensed under the MIT License. This license allows you to use and modify the software
// for personal and commercial purposes with only a few restrictions.
//
// ## License Text
//
// ```text
// MIT License
//
// Copyright (c) 2023 by FluentCLI Contributors
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ```
//
// ## Complying with the License
//
// To comply with the MIT License when using or contributing to FluentCLI, you must:
//
// - Include the full text of the license in your distribution. This is typically done by including
// the LICENSE file in the root of your project or distribution.
// - Maintain the copyright notice and permission notice in all copies or substantial portions of
// the Software that you distribute or use.
// - Understand that the software is provided "as is", without any warranty. You use the software
// at your own risk.
//
// Contributions to FluentCLI are accepted under the same license.