惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Y
Y Combinator Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园_首页
量子位
V
Visual Studio Blog
博客园 - Franky
宝玉的分享
宝玉的分享
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 【当耐特】
罗磊的独立博客
小众软件
小众软件
V
V2EX
GbyAI
GbyAI
B
Blog RSS Feed
博客园 - 三生石上(FineUI控件)
大猫的无限游戏
大猫的无限游戏
有赞技术团队
有赞技术团队
月光博客
月光博客
Recent Announcements
Recent Announcements
雷峰网
雷峰网
F
Fortinet All Blogs
M
MIT News - Artificial intelligence

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
"You Got This Error Last Week" — Building an AI That Reme...
hiyoyo · 2026-05-07 · via DEV Community
Cover image for "You Got This Error Last Week" — Building an AI That Remembers Your Past Errors

hiyoyo

If this is useful, a ❤️ helps others find it.

All tests run on an 8-year-old MacBook Air.

The same error appears twice. Most AI tools diagnose it twice — two API calls, same answer.

HiyokoHelper remembers. When the same error appears again, it responds instantly from cache: "💡 先日も同じケースが発生し、〇〇で解決しました"

Here's how the history cache works.


The data structure

#[derive(Serialize, Deserialize, Clone)]
pub struct HistoryEntry {
    pub error_hash: String,
    pub error_preview: String,
    pub diagnosis: String,
    pub resolved: bool,
    pub created_at: u64,
    pub hit_count: u32,
}

Enter fullscreen mode Exit fullscreen mode

Stored in history.json via tauri-plugin-store. Local only, never leaves the machine.


Normalizing before hashing

Same error, different timestamps → same hash:

pub fn normalize_error(text: &str) -> String {
    let mut result = text.to_string();

    let timestamp_re = Regex::new(r"\d{4}-\d{2}-\d{2}[T ]\d{2}:\d{2}:\d{2}").unwrap();
    result = timestamp_re.replace_all(&result, "[TIMESTAMP]").to_string();

    let line_re = Regex::new(r"line \d+").unwrap();
    result = line_re.replace_all(&result, "line [N]").to_string();

    let pid_re = Regex::new(r"\bpid[: ]\d+").unwrap();
    result = pid_re.replace_all(&result, "pid [PID]").to_string();

    result.split_whitespace().collect::>().join(" ")
}

Enter fullscreen mode Exit fullscreen mode


The lookup flow

pub async fn diagnose_with_history(
    input: &str,
    api_key: &str,
    history: &mut HistoryCache,
) -> DiagnosisResult {
    let hash = error_hash(input);

    if let Some(entry) = history.get(&hash) {
        entry.hit_count += 1;
        let msg = if entry.resolved {
            format!("💡 先日も同じエラーが発生し、解決済みです。\n\n{}", entry.diagnosis)
        } else {
            format!("⚠️ このエラーは以前も発生しています({}回目)。\n\n{}", entry.hit_count, entry.diagnosis)
        };
        return DiagnosisResult::FromHistory { diagnosis: entry.diagnosis.clone(), message: msg };
    }

    let diagnosis = call_gemini(input, api_key).await?;
    history.insert(hash, HistoryEntry {
        error_hash: hash.clone(),
        error_preview: input.chars().take(100).collect(),
        diagnosis: diagnosis.clone(),
        resolved: false,
        created_at: unix_now(),
        hit_count: 1,
    });

    DiagnosisResult::Fresh { diagnosis }
}

Enter fullscreen mode Exit fullscreen mode


The "resolved" button

pub fn mark_resolved(history: &mut HistoryCache, hash: &str) {
    if let Some(entry) = history.get_mut(hash) {
        entry.resolved = true;
    }
    history.save();
}

Enter fullscreen mode Exit fullscreen mode

Next time: "You had this issue and resolved it. Here's what worked."


Cache eviction

Unresolved entries older than 30 days evicted. Resolved entries kept forever.

pub fn evict_old_entries(history: &mut HistoryCache) {
    let cutoff = unix_now() - (30 * 24 * 60 * 60);
    history.entries.retain(|_, entry| {
        entry.created_at > cutoff || entry.resolved
    });
}

Enter fullscreen mode Exit fullscreen mode


HiyokoHelper (OSS) → github.com/hiyoyok/HiyokoHelper
X → @hiyoyok