pub mod actions;
pub mod apps;
pub mod chat_attachments;
pub mod config;
pub mod content;
pub mod email_attachments;
pub mod email_listener;
pub mod email_mime;
pub mod email_pipeline;
pub mod email_send;
pub mod entities;
pub mod forms;
pub mod genai;
pub mod handlers;
pub mod keys;
pub mod live_turn;
pub mod migrations;
pub mod preferences;
pub mod routes;
pub mod rune_engine;
pub mod serve_startup;
pub mod skill_hints;
pub mod skill_zip;
pub mod state;
pub mod templates;
pub mod tools;
pub mod ws;
use std::sync::Arc;
use frunk::{HCons, HNil, hlist::HList};
use crate::plugin_install::define_plugin_install;
use crate::{
app::App,
capability::{ApplyHooks, CapStore, define_passthrough_cap},
config::{ConfigCap, ConfigTag},
db::{DbCap, DbTag},
hooks::AttachState,
llm_tools::{LlmToolsCap, LlmToolsCapability, LlmToolsTag},
plugins::filesystem::{
config::{FilesystemConfig, FilesystemConfigTag},
storage::{DynFilestore, filestore_from_config},
},
rune_env::{RuneEnvCap, RuneEnvCapability, RuneEnvTag},
traits::{
add::{AddCapability, CapTagAbsent},
get::{GetByCapTag, GetByTag},
},
};
use config::{LlmAssistantConfig, LlmAssistantConfigTag};
use state::{EmailAutomationDeps, LlmAssistantState};
pub struct LlmAssistantTag;
define_passthrough_cap!(LlmAssistantStateCap, LlmAssistantTag, LlmAssistantState);
define_plugin_install! {
plugin: LlmAssistantTag;
steps: [
apps(apps::Hook),
tools(tools::Hook),
migrations(migrations::Hook),
templates(templates::Hook),
slots(templates::SlotsHook),
config(LlmAssistantConfigTag, LlmAssistantConfig),
http(routes::Hook),
state(StateHook),
serve_startup(serve_startup::ServeStartupHook),
]
}
#[derive(Clone, Copy, Default)]
pub struct StateHook;
impl<
L,
DbIdx,
CfgIdx,
Configs,
AsstCfgIdx,
FsCfgIdx,
ToolsIdx,
ToolsHooks,
ToolsProof,
RuneEnvIdx,
RuneEnvHooks,
RuneProof,
TagProof,
>
AttachState<
L,
(
DbIdx,
CfgIdx,
Configs,
AsstCfgIdx,
FsCfgIdx,
ToolsIdx,
ToolsProof,
RuneEnvIdx,
RuneProof,
TagProof,
),
> for StateHook
where
L: GetByCapTag<DbTag, DbIdx, Value = DbCap>,
L: GetByCapTag<ConfigTag, CfgIdx, Value = ConfigCap<HNil, Configs>>,
Configs: GetByTag<LlmAssistantConfigTag, AsstCfgIdx, Value = LlmAssistantConfig>,
Configs: GetByTag<FilesystemConfigTag, FsCfgIdx, Value = FilesystemConfig>,
L: GetByCapTag<LlmToolsTag, ToolsIdx, Value = LlmToolsCap<ToolsHooks>>,
ToolsHooks: Clone + ApplyHooks<LlmToolsCapability, ToolsProof, Output = LlmToolsCapability>,
L: GetByCapTag<RuneEnvTag, RuneEnvIdx, Value = RuneEnvCap<RuneEnvHooks>>,
RuneEnvHooks: Clone + ApplyHooks<RuneEnvCapability, RuneProof, Output = RuneEnvCapability>,
L: HList + CapTagAbsent<LlmAssistantTag, TagProof>,
{
type Output = HCons<LlmAssistantStateCap, L>;
fn attach_state(app: App<L>) -> App<Self::Output> {
let conn = app.get_capability::<DbTag, DbIdx>().items.conn.clone();
let configs = &app.get_capability::<ConfigTag, CfgIdx>().items;
let config =
<Configs as GetByTag<LlmAssistantConfigTag, AsstCfgIdx>>::get_by_tag(configs).clone();
let fs_config =
<Configs as GetByTag<FilesystemConfigTag, FsCfgIdx>>::get_by_tag(configs).clone();
let store: Arc<DynFilestore> = filestore_from_config(&fs_config);
let tools_cap = app.get_capability::<LlmToolsTag, ToolsIdx>();
let tools = Arc::new(tools_cap.hooks.clone().apply_hooks(tools_cap.items.clone()));
let rune_cap = app.get_capability::<RuneEnvTag, RuneEnvIdx>();
let rune_env = Arc::new(rune_cap.hooks.clone().apply_hooks(rune_cap.items.clone()));
let email_automation = EmailAutomationDeps {
store,
tools,
rune_env,
};
let state = LlmAssistantState::new(conn, config, email_automation).bind_email_listener();
app.add_capability(CapStore::with_items(state))
}
}