add TimeContext: 25 pre-computed time values for the model
midnight-based day boundaries (today, yesterday, 2 days ago),
week/month boundaries, rolling offsets (1h to 30d). injected
into system prompt via {time_block} and per-message via compact
time line. models no longer need to compute epoch timestamps.
This commit is contained in:
@@ -21,6 +21,7 @@ use crate::config::Config;
|
||||
use crate::context::ResponseContext;
|
||||
use crate::conversations::ConversationRegistry;
|
||||
use crate::memory;
|
||||
use crate::time_context::TimeContext;
|
||||
use crate::tools::ToolRegistry;
|
||||
|
||||
/// Run a Mistral chat completion on a blocking thread.
|
||||
@@ -146,7 +147,7 @@ impl Responder {
|
||||
messages.push(ChatMessage::new_user_message(&trigger));
|
||||
}
|
||||
|
||||
let tool_defs = ToolRegistry::tool_definitions(self.tools.has_gitea());
|
||||
let tool_defs = ToolRegistry::tool_definitions(self.tools.has_gitea(), self.tools.has_kratos());
|
||||
let model = Model::new(&self.config.mistral.default_model);
|
||||
let max_iterations = self.config.mistral.max_tool_iterations;
|
||||
|
||||
@@ -280,6 +281,7 @@ impl Responder {
|
||||
conversation_registry: &ConversationRegistry,
|
||||
image_data_uri: Option<&str>,
|
||||
context_hint: Option<String>,
|
||||
event_id: ruma::OwnedEventId,
|
||||
) -> Option<String> {
|
||||
// Apply response delay
|
||||
if !self.config.behavior.instant_responses {
|
||||
@@ -302,24 +304,16 @@ impl Responder {
|
||||
// Pre-response memory query (same as legacy path)
|
||||
let memory_notes = self.load_memory_notes(response_ctx, trigger_body).await;
|
||||
|
||||
// Build the input message with dynamic context header.
|
||||
// Build the input message with dynamic context.
|
||||
// Agent instructions are static (set at creation), so per-message context
|
||||
// (timestamps, room, members, memory) is prepended to each user message.
|
||||
let now = chrono::Utc::now();
|
||||
let epoch_ms = now.timestamp_millis();
|
||||
let ts_1h = (now - chrono::Duration::hours(1)).timestamp_millis();
|
||||
let ts_yesterday = (now - chrono::Duration::days(1)).timestamp_millis();
|
||||
let ts_last_week = (now - chrono::Duration::days(7)).timestamp_millis();
|
||||
let tc = TimeContext::now();
|
||||
|
||||
let mut context_header = format!(
|
||||
"[context: date={}, epoch_ms={}, ts_1h_ago={}, ts_yesterday={}, ts_last_week={}, room={}, room_name={}]",
|
||||
now.format("%Y-%m-%d"),
|
||||
epoch_ms,
|
||||
ts_1h,
|
||||
ts_yesterday,
|
||||
ts_last_week,
|
||||
room_id,
|
||||
"{}\n[room: {} ({})]",
|
||||
tc.message_line(),
|
||||
room_name,
|
||||
room_id,
|
||||
);
|
||||
|
||||
if let Some(ref notes) = memory_notes {
|
||||
@@ -352,9 +346,12 @@ impl Responder {
|
||||
// Check for function calls — execute locally and send results back
|
||||
let function_calls = response.function_calls();
|
||||
if !function_calls.is_empty() {
|
||||
// Agent UX: reactions + threads require the user's event ID
|
||||
// which we don't have in the responder. For now, log tool calls
|
||||
// and skip UX. TODO: pass event_id through ResponseContext.
|
||||
// Agent UX: react with 🔍 and post tool details in a thread
|
||||
let mut progress = crate::agent_ux::AgentProgress::new(
|
||||
room.clone(),
|
||||
event_id.clone(),
|
||||
);
|
||||
progress.start().await;
|
||||
|
||||
let max_iterations = self.config.mistral.max_tool_iterations;
|
||||
let mut current_response = response;
|
||||
@@ -376,13 +373,30 @@ impl Responder {
|
||||
"Executing tool call (conversations)"
|
||||
);
|
||||
|
||||
|
||||
|
||||
let result = self
|
||||
.tools
|
||||
.execute(&fc.name, &fc.arguments, response_ctx)
|
||||
// Post tool call to thread
|
||||
progress
|
||||
.post_step(&crate::agent_ux::AgentProgress::format_tool_call(
|
||||
&fc.name,
|
||||
&fc.arguments,
|
||||
))
|
||||
.await;
|
||||
|
||||
let result = if fc.name == "research" {
|
||||
self.tools
|
||||
.execute_research(
|
||||
&fc.arguments,
|
||||
response_ctx,
|
||||
room,
|
||||
&event_id,
|
||||
0, // depth 0 — orchestrator level
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
self.tools
|
||||
.execute(&fc.name, &fc.arguments, response_ctx)
|
||||
.await
|
||||
};
|
||||
|
||||
let result_str = match result {
|
||||
Ok(s) => {
|
||||
let preview: String = s.chars().take(500).collect();
|
||||
@@ -427,6 +441,9 @@ impl Responder {
|
||||
debug!(iteration, "Tool iteration complete (conversations)");
|
||||
}
|
||||
|
||||
// Done with tool calls
|
||||
progress.done().await;
|
||||
|
||||
// Extract final text from the last response
|
||||
if let Some(text) = current_response.assistant_text() {
|
||||
let text = strip_sol_prefix(&text);
|
||||
|
||||
Reference in New Issue
Block a user