add context.md, strip LLM timestamps, clippy fixes, simplify deploy target
This commit is contained in:
@@ -16,6 +16,7 @@ pub struct Config {
|
||||
}
|
||||
|
||||
#[derive(Deserialize, Clone)]
|
||||
#[allow(dead_code)]
|
||||
pub struct GiteaConfig {
|
||||
pub url: String,
|
||||
/// Direct token or read from token_file at startup
|
||||
|
||||
@@ -6,6 +6,25 @@ use teloxide::types::ParseMode;
|
||||
|
||||
use crate::stream::{CURSOR, TG_MSG_LIMIT};
|
||||
|
||||
/// Strip leading timestamps that LLM copies from our injected message timestamps.
|
||||
/// Matches patterns like `[2026-04-10 21:13:15]` or `[2026-04-10 21:13]` at the start.
|
||||
pub fn strip_leading_timestamp(s: &str) -> &str {
|
||||
let trimmed = s.trim_start();
|
||||
if trimmed.starts_with('[') {
|
||||
if let Some(end) = trimmed.find(']') {
|
||||
let inside = &trimmed[1..end];
|
||||
// check if it looks like a timestamp: starts with 20xx-
|
||||
if inside.len() >= 16 && inside.starts_with("20") && inside.contains('-') {
|
||||
let after = trimmed[end + 1..].trim_start();
|
||||
if !after.is_empty() {
|
||||
return after;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
s
|
||||
}
|
||||
|
||||
pub fn truncate_for_display(s: &str) -> String {
|
||||
let budget = TG_MSG_LIMIT - CURSOR.len() - 1;
|
||||
if s.len() <= budget {
|
||||
|
||||
@@ -6,7 +6,7 @@ use axum::http::StatusCode;
|
||||
use axum::response::IntoResponse;
|
||||
use axum::routing::post;
|
||||
use axum::Json;
|
||||
use tracing::{error, info, warn};
|
||||
use tracing::{error, info};
|
||||
|
||||
use crate::config::GiteaConfig;
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ use crate::stream::{send_message_draft, DRAFT_INTERVAL_MS, EDIT_INTERVAL_MS, TG_
|
||||
pub struct TelegramOutput {
|
||||
pub bot: Bot,
|
||||
pub chat_id: ChatId,
|
||||
#[allow(dead_code)]
|
||||
pub is_private: bool,
|
||||
// internal state
|
||||
msg_id: Option<teloxide::types::MessageId>,
|
||||
@@ -140,6 +141,7 @@ impl Output for TelegramOutput {
|
||||
|
||||
use crate::gitea::GiteaClient;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct GiteaOutput {
|
||||
pub client: GiteaClient,
|
||||
pub owner: String,
|
||||
@@ -173,10 +175,12 @@ impl Output for GiteaOutput {
|
||||
|
||||
// ── Buffer (for Worker, tests) ─────────────────────────────────────
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct BufferOutput {
|
||||
pub text: String,
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
impl BufferOutput {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
|
||||
@@ -4,7 +4,7 @@ use anyhow::Result;
|
||||
use tracing::{error, info, warn};
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::display::truncate_at_char_boundary;
|
||||
use crate::display::{strip_leading_timestamp, truncate_at_char_boundary};
|
||||
use crate::output::Output;
|
||||
use crate::state::AppState;
|
||||
use crate::tools::{discover_tools, execute_tool, ToolCall};
|
||||
@@ -209,11 +209,14 @@ pub async fn run_openai_with_tools(
|
||||
continue;
|
||||
}
|
||||
|
||||
if !accumulated.is_empty() {
|
||||
let _ = output.finalize(&accumulated).await;
|
||||
// strip timestamps that LLM copies from our message format
|
||||
let cleaned = strip_leading_timestamp(&accumulated).to_string();
|
||||
|
||||
if !cleaned.is_empty() {
|
||||
let _ = output.finalize(&cleaned).await;
|
||||
}
|
||||
|
||||
return Ok(accumulated);
|
||||
return Ok(cleaned);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,6 +260,19 @@ pub fn build_system_prompt(summary: &str, persona: &str, memory_slots: &[(i32, S
|
||||
text.push_str(inner_state);
|
||||
}
|
||||
|
||||
// inject context file if present (e.g. /data/noc/context.md)
|
||||
let config_path = std::env::var("NOC_CONFIG").unwrap_or_else(|_| "config.yaml".into());
|
||||
let context_path = std::path::Path::new(&config_path)
|
||||
.parent()
|
||||
.unwrap_or(std::path::Path::new("."))
|
||||
.join("context.md");
|
||||
if let Ok(ctx) = std::fs::read_to_string(&context_path) {
|
||||
if !ctx.trim().is_empty() {
|
||||
text.push_str("\n\n## 运行环境\n");
|
||||
text.push_str(ctx.trim());
|
||||
}
|
||||
}
|
||||
|
||||
if !summary.is_empty() {
|
||||
text.push_str("\n\n## 之前的对话总结\n");
|
||||
text.push_str(summary);
|
||||
|
||||
@@ -7,7 +7,7 @@ use anyhow::Result;
|
||||
use tokio::io::AsyncBufReadExt;
|
||||
use tokio::process::Command;
|
||||
use tokio::sync::RwLock;
|
||||
use tracing::{error, info, warn};
|
||||
use tracing::{info, warn};
|
||||
|
||||
use crate::config::Config;
|
||||
use crate::display::truncate_at_char_boundary;
|
||||
|
||||
Reference in New Issue
Block a user