数据库模式
Snoopy 使用本地 SQLite 数据库。
存储位置
路径模式:
<rootDir>/snoopy.db
在所有支持的操作系统上,默认根目录为 <home>/.snoopy:
- macOS 示例:
~/.snoopy/snoopy.db - Linux 示例:
~/.snoopy/snoopy.db - Windows 示例:
C:\Users\<you>\.snoopy\snoopy.db
默认路径(macOS/Linux):
~/.snoopy/snoopy.db
覆盖根目录:
- 设置
SNOOPY_ROOT_DIR
则数据库路径变为:
<SNOOPY_ROOT_DIR>/snoopy.db
模式来源
src/services/db/migrations/中的 TypeScript 迁移模块- 迁移执行器位于
src/services/db/migrations/runner.ts - 数据库启动代码位于
src/services/db/sqlite.ts(仅 WAL 模式 + 调用执行器)
表
settings
用途:
- 存储键值对形式的应用设置和凭证元数据
列:
key TEXT PRIMARY KEYvalue TEXT NOT NULLupdated_at TEXT NOT NULL DEFAULT datetime('now')
常用键:
modelmodel_settings_jsonreddit_app_namereddit_client_id
jobs
用途:
- 定义监控任务
列:
id TEXT PRIMARY KEYslug TEXT UNIQUEname TEXT NOT NULL UNIQUEdescription TEXT NOT NULLqualification_prompt TEXT NOT NULLsubreddits_json TEXT NOT NULLschedule_cron TEXT NOT NULL DEFAULT '*/30 * * * *'enabled INTEGER NOT NULL DEFAULT 1monitor_comments INTEGER NOT NULL DEFAULT 1created_at TEXT NOT NULL DEFAULT datetime('now')updated_at TEXT NOT NULL DEFAULT datetime('now')
索引:
idx_jobs_slug基于slug的唯一索引
说明:
- 命令接受任务 ID 或 slug。
- Slug 在仓库逻辑中生成并确保唯一。
job_runs
用途:
- 存储每次计划/手动执行尝试
活动运行时模式中的列:
id TEXT PRIMARY KEYjob_id TEXT NOT NULL(外键关联jobs.id)status TEXT NOT NULL(running、completed、failed、skipped)message TEXTstarted_at TEXTfinished_at TEXTitems_discovered INTEGER NOT NULL DEFAULT 0items_new INTEGER NOT NULL DEFAULT 0items_qualified INTEGER NOT NULL DEFAULT 0prompt_tokens INTEGER NOT NULL DEFAULT 0completion_tokens INTEGER NOT NULL DEFAULT 0estimated_cost_usd REALlog_file_path TEXTcreated_at TEXT NOT NULL DEFAULT datetime('now')
说明:
- 迁移 001 初始化一个最小版本。
- 运行时启动时会为较旧的本地数据库添加更新的分析列。
- 当详细日志可用时,
log_file_path指向~/.snoopy/logs/下每次运行的日志文件。 idx_job_runs_active_job确保每个job_id最多有一行处于running状态,以防止运行重叠。
scan_items
用途:
- 已扫描帖子/评论的去重存储及资格判定结果
- 支持下游自动化的轻量级结果生命周期追踪
列:
id TEXT PRIMARY KEYjob_id TEXT NOT NULL(外键关联jobs.id)run_id TEXT NOT NULL(外键关联job_runs.id)type TEXT NOT NULL CHECK(type IN ('post','comment'))reddit_post_id TEXT NOT NULLreddit_comment_id TEXTsubreddit TEXT NOT NULLauthor TEXT NOT NULLtitle TEXTbody TEXT NOT NULLurl TEXT NOT NULLreddit_posted_at TEXT NOT NULLqualified INTEGER NOT NULL DEFAULT 0viewed INTEGER NOT NULL DEFAULT 0validated INTEGER NOT NULL DEFAULT 0processed INTEGER NOT NULL DEFAULT 0consumed INTEGER NOT NULL DEFAULT 0qualification_reason TEXTcreated_at TEXT NOT NULL DEFAULT datetime('now')
索引:
idx_scan_items_dedup基于(job_id, reddit_post_id, COALESCE(reddit_comment_id,''))的唯一索引idx_scan_items_consumed基于(job_id, qualified, consumed, created_at DESC)的索引
行为:
- 防止每个任务重复处理相同的帖子/评论
- 存储最终资格判定原因以供审计
- 生命周期标志语义:
viewed = 1结果已被操作员或代理审阅validated = 1结果已通过质量检查/接受processed = 1结果已移交至下游工作流consumed = 1结果已被consume命令返回,将不再出现
说明:
- SQLite 将布尔值存储为整数(
0表示 false,1表示 true)。 - 较新的运行时版本在启动时会使用
ALTER TABLE为较旧的本地数据库回填缺失的生命周期列。
daemon_state
用途:
- 为守护进程生命周期保留的运行时状态表
列:
id INTEGER PRIMARY KEY CHECK (id = 1)is_running INTEGER NOT NULLupdated_at TEXT NOT NULL DEFAULT datetime('now')
migrations
用途:
- 跟踪迁移执行器已应用的模式迁移
列:
id INTEGER PRIMARY KEYname TEXT NOT NULLapplied_at TEXT NOT NULL DEFAULT datetime('now')
说明:
- 由迁移执行器在首次访问数据库时自动创建
- 每行代表一个已应用的迁移模块
snoopy doctor报告待处理与已应用的迁移对比
删除与数据生命周期
通过 CLI/仓库删除任务会移除:
- 该任务的
scan_items行 - 该任务的
job_runs行 job_runs.log_file_path引用的关联运行日志文件(如果存在)jobs行本身
此删除操作在仓库逻辑中以数据库事务方式执行。
查询示例
某个任务的最新运行记录:
SELECT *
FROM job_runs
WHERE job_id = ?
ORDER BY created_at DESC
LIMIT 20;
某次运行的最新合格项目:
SELECT reddit_post_id, reddit_comment_id, qualified, qualification_reason
FROM scan_items
WHERE run_id = ?
ORDER BY created_at DESC;
某个任务中未处理的合格项目:
SELECT
id,
url,
author,
title,
qualification_reason,
viewed,
validated,
processed,
reddit_posted_at
FROM scan_items
WHERE job_id = ?
AND qualified = 1
AND processed = 0
ORDER BY datetime(reddit_posted_at) DESC;
将一条结果标记为已查看 + 已验证:
UPDATE scan_items
SET viewed = 1,
validated = 1
WHERE id = ?;
批量将某次运行的合格结果标记为已处理:
UPDATE scan_items
SET processed = 1
WHERE run_id = ?
AND qualified = 1;
Agent 工作流参考
有关端到端的直接数据库工作流(列出任务、插入任务、验证守护进程/启动状态、运行任务、读取/更新结果),请参见 Agent 操作。