用途
archive-crawler(The Universal Archivist)是 gbrain 体系下的通用档案归档技能,用于探索和整理个人内容文件树。它支持本地挂载、Dropbox API、Backblaze B2、Gmail takeout(.mbox)等来源。目标是从大量噪音文件(系统文件、配置、二进制块)中筛选出高价值内容——即用户自己的写作、想法、关系材料等。
安全闸门(强制)
该技能只有在 gbrain.yml 中显式配置 archive-crawler.scan_paths: 允许列表时才会运行。这是防止代理过度扩大扫描范围、误摄取敏感内容(税务 PDF、医疗记录、凭据)的安全围栏。
gbrain.yml 配置示例:
archive-crawler:
scan_paths:
- ~/Documents/writing/
- ~/Dropbox/Archive/
- /mnt/backup/old-letters/
# Optional deny-list inside the allow-list:
# deny_paths:
# - ~/Documents/finances/
# - ~/Documents/medical/
若 scan_paths 为空或缺失,技能会退出并提示:
archive-crawler: refusing to run. No `archive-crawler.scan_paths:` allow-list
in gbrain.yml. Add explicit paths the agent is permitted to scan, then re-run.
This is a safety fence — the agent will not infer what's safe to read.
该约定由 src/core/storage-config.ts 强制执行。
主要概念
- Source(来源):待探索的文件树,具有 type(local | dropbox | backblaze | gmail-takeout | mbox | pst)、root(路径/前缀)、manifest(进度 brain 页面
projects/<archive-slug>/STATUS.md)。 - Manifest(清单):跟踪树清单、triage 状态(⬜ unseen / 👀 reviewed / ✅ ingested / ⏭️ skip / 🔥 high-signal)、用户反应(按 quality.md 保留逐字引用)、优先级队列、会话日志。
- Gold filter(黄金过滤器):展示前先过滤。保留项包括个人写作、对话、想法、关系材料、创作、起源故事、情感内容;跳过项包括系统文件、二进制块、票据发票税务、垃圾邮件、损坏文件。
使用方式(三阶段协议)
阶段 1:清单
- 确认 scan_paths 已设置,否则退出。
- 映射文件树——列出文件夹、文件、大小、日期范围。
- 按可能的内容类型归类文件夹。
- 创建 manifest,写入
projects/<archive-slug>/STATUS.md。 - 按可能的黄金密度排出优先级队列。
- 展示地图与顺序,允许用户覆盖。
阶段 2:爬取:按优先级逐个读取、过滤、逐条展示 gold 项,用用户原话记录反应,更新 manifest,且不重复展示已标记项。
阶段 3:归档:按 _brain-filing-rules.md 以主题归档:
- 用户自己的写作/想法/起源 →
originals/<slug>.md - 反思/个人生活 →
personal/<slug>.md - 产品/商业想法 →
ideas/<slug>.md - 关于某人的信件/线程 →
people/<person>/timeline回链,正文归入 personal 或 originals。
该技能为 schema-generic,不在代码中固化任何特定年代目录,而是运行时读取 _brain-filing-rules.json。
Brain 页面格式:
---
title: "[Title or first line]"
type: original
source_type: "[local|dropbox|backblaze|gmail-takeout|mbox|pst]"
source_path: "[path within the allow-listed scan_paths]"
date: "YYYY-MM-DD" # date from the file metadata or content
people: ["person-1", "person-2"]
tags: ["tag-1", "tag-2"]
---
# [Title]
[Summary: what it is, when it's from, why it matters]
**User's reaction:** [exact quote, no paraphrasing]
## Context
[Cross-links to people, concepts, projects.]
---
[Raw source material below the line — full text]
支持的文件类型处理
- 纯文本 / HTML / Markdown:直接读取,展示时剥离 HTML 标签。
- .mbox(邮件归档):
import mailbox
mbox = mailbox.mbox('/path/to/file.mbox')
for msg in mbox:
body = ''
if msg.is_multipart():
for part in msg.walk():
if part.get_content_type() == 'text/plain':
body = part.get_payload(decode=True).decode('utf-8', errors='replace')
break
else:
body = msg.get_payload(decode=True).decode('utf-8', errors='replace')
# Apply gold filter
- .doc / .docx:
# .docx (modern)
python3 -c "
import zipfile, xml.etree.ElementTree as ET
with zipfile.ZipFile('/path/to/file.docx') as z:
tree = ET.parse(z.open('word/document.xml'))
print(''.join(t.text or '' for t in tree.iter('{http://schemas.openxmlformats.org/wordprocessingml/2006/main}t')))
"
# .doc (legacy, requires antiword or catdoc)
antiword /path/to/file.doc 2>/dev/null || catdoc /path/to/file.doc 2>/dev/null
- .pst(Outlook 归档):
# Validate first; many PSTs are null bytes
python3 -c "
with open('/path/to/file.pst', 'rb') as f:
print('Valid PST' if f.read(4) == b'!BDN' else 'CORRUPT/NULL')
"
# If valid:
readpst -o /tmp/pst-output /path/to/file.pst
- .zip / .tar / .tar.gz:解压到临时目录后递归处理。
- 图片:仅记录文件名、大小、日期等元数据,除非用户要求否则不展示。
错误处理
- 缺少 allow-list:这是技能自身的硬性拒绝,需询问用户可扫描哪些目录,绝不自行扩大列表。
- 归档挂载/ takeout / bucket 不可读(权限、令牌过期):报告具体失败路径并停止该来源,不回退扫描父目录。
- 归档返回 write_pending(退出码 10)或 revision_conflict:前者轮询
gbrain write-request <request_id>,后者重读页面并合并,不用新 slug 重新归档。
反模式
- 未设置 scan_paths 就运行(硬拒绝,不得绕过)。
- 硬编码年代特定归档路径。
- 重复展示 manifest 中已标记项。
- 转述用户反应(只用原话)。
- 用经验教训或总结包裹发现内容。
- 内容涉及有 brain 页面的人或公司时漏掉回链。
适用场景与限制
适用于在明确授权的路径内对个人档案(本地、Dropbox、B2、Gmail takeout 等)做系统性探索、筛选与归档,并将有价值内容沉淀为 brain 页面。限制包括:必须显式配置允许列表,否则拒绝运行;图片不主动展示;具体安装方式、收费、价格资料中暂未提供。