1mod bound;
19mod client;
20mod error;
21mod fake;
22mod model;
23mod stream;
24
25pub use bound::{AiBound, AiExt};
26pub use client::{Ai, AiClient};
27pub use error::AiError;
28pub use fake::FakeAi;
29pub use model::SharedModel;
30pub use stream::stream_to_response;
31
32pub use aisdk;
34
35pub mod prelude {
37 pub use aisdk::core::{
38 utils::step_count_is, GenerateTextResponse, LanguageModel, LanguageModelRequest,
39 LanguageModelStreamChunkType, Message, Messages, Tool,
40 };
41 pub use aisdk::macros::tool;
42 pub use aisdk::{Error as AisdkError, Result as AisdkResult};
43
44 pub use crate::{Ai, AiBound, AiClient, AiError, AiExt, FakeAi, SharedModel};
45}
46
47use sova_core::{App, Plugin};
48
49impl Plugin for Ai {
50 fn id(&self) -> &'static str {
51 "ai"
52 }
53
54 fn meta(&self) -> sova_core::PluginMeta {
55 sova_core::PluginMeta::new("Ai")
56 .description("AISDK language models (chat, tools, stream, fake)")
57 .version(env!("CARGO_PKG_VERSION"))
58 }
59
60 fn install(self, app: &mut App) {
61 let mut ai = self;
62 if ai.default_system().is_none() {
63 if let Some(doc) = app.config_doc() {
64 if let Some(section) = doc.section("ai") {
65 if let Some(system) = section.get("system").and_then(|v| v.as_str()) {
66 ai = ai.system(system);
67 }
68 }
69 }
70 }
71 let client = match ai.into_client() {
72 Ok(c) => c,
73 Err(err) => {
74 tracing::error!(error = %err, "ai plugin install failed");
75 panic!("ai install failed: {err}");
76 }
77 };
78 app.state(client);
79 }
80}