Back to skills
SkillHub ClubShip Full StackFull Stack

lifelog

生活记录自动化系统。自动识别消息中的日期(今天/昨天/前天/具体日期),使用 SubAgent 智能判断,记录到 Notion 对应日期,支持补录标记。 适用于:(1) 用户分享日常生活点滴时自动记录;(2) 定时自动汇总分析并填充情绪、事件、位置、人员字段

Packaged view

This page reorganizes the original catalog entry around fit, installability, and workflow context first. The original raw source lives below.

Stars
3,126
Hot score
99
Updated
March 20, 2026
Overall rating
C0.0
Composite score
0.0
Best-practice grade
C61.1

Install command

npx @skill-hub/cli install openclaw-skills-lifelog

Repository

openclaw/skills

Skill path: skills/421zuoduan/lifelog

生活记录自动化系统。自动识别消息中的日期(今天/昨天/前天/具体日期),使用 SubAgent 智能判断,记录到 Notion 对应日期,支持补录标记。 适用于:(1) 用户分享日常生活点滴时自动记录;(2) 定时自动汇总分析并填充情绪、事件、位置、人员字段

Open repository

Best for

Primary workflow: Ship Full Stack.

Technical facets: Full Stack.

Target audience: everyone.

License: Unknown.

Original source

Catalog source: SkillHub Club.

Repository owner: openclaw.

This is still a mirrored public skill entry. Review the repository before installing into production workflows.

What it helps with

  • Install lifelog into Claude Code, Codex CLI, Gemini CLI, or OpenCode workflows
  • Review https://github.com/openclaw/skills before adding lifelog to shared team environments
  • Use lifelog for development workflows

Works across

Claude CodeCodex CLIGemini CLIOpenCode

Favorites: 0.

Sub-skills: 0.

Aggregator: No.

Original source / Raw SKILL.md

---
name: lifelog
description: |
  生活记录自动化系统。自动识别消息中的日期(今天/昨天/前天/具体日期),使用 SubAgent 智能判断,记录到 Notion 对应日期,支持补录标记。
  适用于:(1) 用户分享日常生活点滴时自动记录;(2) 定时自动汇总分析并填充情绪、事件、位置、人员字段
version: 1.2.3
credentials:
  required:
    - NOTION_KEY
    - NOTION_DATABASE_ID
---

# LifeLog 生活记录系统

自动将用户的日常生活记录到 Notion,支持智能日期识别和自动汇总分析。

## ⚠️ 必需凭据

使用本技能前,必须设置以下环境变量:

```bash
export NOTION_KEY="your-notion-integration-token"
export NOTION_DATABASE_ID="your-notion-database-id"
```

获取方式:
1. 访问 https://www.notion.so/my-integrations 创建 Integration
2. 获取 Internal Integration Token
3. 创建 Database 并 Share 给 Integration
4. 从 URL 中提取 Database ID

# LifeLog 生活记录系统

自动将用户的日常生活记录到 Notion,支持智能日期识别和自动汇总分析。

## 核心功能

1. **实时记录** - 用户分享生活点滴时自动记录到 Notion
2. **智能日期识别(SubAgent)** - 使用 AI SubAgent 智能判断日期,优先分析文本中的日期关键词,其次分析上下文
3. **补录标记** - 非当天记录的内容会标记为"🔁补录"
4. **自动汇总** - 每天凌晨自动运行 LLM 分析,生成情绪状态、主要事件、位置、人员

## Notion 数据库要求

创建 Notion Database,需包含以下字段(全部为 rich_text 类型):

| 字段名 | 类型 | 说明 |
|--------|------|------|
| 日期 | title | 日期,如 2026-02-22 |
| 原文 | rich_text | 原始记录内容 |
| 情绪状态 | rich_text | LLM 分析后的情绪描述 |
| 主要事件 | rich_text | LLM 分析后的事件描述 |
| 位置 | rich_text | 地点列表 |
| 人员 | rich_text | 涉及的人员 |

## 脚本说明

### 1. lifelog-append.sh

实时记录脚本,接收用户消息内容。**日期由 Agent 调用 SubAgent 智能判断**:

```bash
# 基本用法(Agent 会自动判断日期)
bash lifelog-append.sh "今天早上吃了油条"

# Agent 判断后传入日期
bash lifelog-append.sh "前天去打球了" "2026-03-12"
```

**日期判断流程(Agent 侧)**:
1. 用户发送生活记录 → Agent 调用 SubAgent 判断日期
2. SubAgent 分析文本中的日期关键词(前天、昨天等)
3. 如果没有明确日期,SubAgent 根据上下文智能判断
4. Agent 将判断出的日期和内容一起传给脚本

### 2. lifelog-daily-summary-v5.sh

拉取指定日期的原文,用于 LLM 分析:

```bash
# 拉取昨天
bash lifelog-daily-summary-v5.sh

# 拉取指定日期
bash lifelog-daily-summary-v5.sh 2026-02-22
```

输出格式:
```
PAGE_ID=xxx
---原文开始---
原文内容
---原文结束---
```

### 3. lifelog-update.sh

将 LLM 分析结果写回 Notion:

```bash
bash lifelog-update.sh "<page_id>" "<情绪状态>" "<主要事件>" "<位置>" "<人员>"
```

## 配置步骤

1. 创建 Notion Integration 并获取 API Key
2. 创建 Database 并共享给 Integration
3. 获取 Database ID(URL 中提取)
4. 设置环境变量:

```bash
export NOTION_KEY="your-notion-integration-token"
export NOTION_DATABASE_ID="your-database-id"
```

## 定时任务(可选)

每天凌晨 5 点自动汇总昨天数据:

```bash
openclaw cron add \
  --name "LifeLog-每日汇总" \
  --cron "0 5 * * *" \
  --tz "Asia/Shanghai" \
  --session isolated \
  --message "运行 LifeLog 每日汇总" \
  --delivery-mode announce \
  --channel qqbot \
  --to "<用户ID>"
```

## 工作流

1. 用户发送生活记录 → 调用 `lifelog-append.sh` → 写入 Notion
2. 定时任务触发 → 调用 `lifelog-daily-summary-v5.sh` → 拉取原文
3. LLM 分析原文 → 调用 `lifelog-update.sh` → 填充分析字段


---

## Skill Companion Files

> Additional files collected from the skill directory layout.

### README.md

```markdown
# LifeLog 生活记录系统

[English](./README_EN.md) | 中文

> ⚠️ **声明**:本技能及其文档由 AI 生成,仅供参改。

自动将日常生活记录到 Notion,支持智能日期识别和自动汇总分析。

## 功能特点

- 🤖 **智能日期识别** - 自动识别"昨天"、"前天"等日期,记录到对应日期
- 🔁 **补录标记** - 非当天记录的内容会标记为"🔁补录"
- 📝 **实时记录** - 随时记录生活点滴,自动保存到 Notion
- 🌙 **自动汇总** - 每天凌晨自动运行 LLM 分析,生成情绪状态,主要事件、位置、人员
- 🔍 **智能过滤** - 自动过滤纯工作指令、测试消息等不需要记录的内容

## 效果预览

![LifeLog Preview](./assets/preview.png)

## 快速开始

### 1. 安装

通过 ClawHub 安装:
```bash
clawhub install lifelog
```

或手动下载:
```bash
git clone https://github.com/421zuoduan/lifelog.git
```

### 2. 配置 Notion

1. **创建 Integration**
   - 访问 https://www.notion.so/my-integrations
   - 点击 **New integration**
   - 填写名称(如 "LifeLog")
   - 复制生成的 **Internal Integration Token**

2. **创建 Database**
   - 在 Notion 中创建新 Database
   - 添加以下字段(全部为 rich_text 类型):
     | 字段名 | 类型 | 说明 |
     |--------|------|------|
     | 日期 | title | 日期,如 2026-02-22 |
     | 原文 | rich_text | 原始记录内容 |
     | 情绪状态 | rich_text | LLM 分析后的情绪描述 |
     | 主要事件 | rich_text | LLM 分析后的事件描述 |
     | 位置 | rich_text | 地点列表 |
     | 人员 | rich_text | 涉及的人员 |
   - 点击 Database 右上角的 **...** → **Connect to** → 选择你的 Integration

3. **获取 Database ID**
   - URL 中提取:`https://notion.so/{workspace}/{database_id}?v=...`
   - database_id 是 32 位字符串(带 `-`)

4. **修改脚本配置**
   - 编辑 `scripts/` 目录下的脚本,替换:
     ```bash
     # ===== 配置区域 =====
     NOTION_KEY="你的Notion_API_Key"
     DATABASE_ID="你的Database_ID"
     # ====================
     ```

### 3. 使用方式

```bash
# 记录今天的事情
bash scripts/lifelog-append.sh "今天早上吃了油条"

# 记录昨天的事情(自动识别日期)
bash scripts/lifelog-append.sh "昨天去超市买菜了"

# 记录前天的事情
bash scripts/lifelog-append.sh "前天和朋友吃饭了"

# 记录具体日期的事情
bash scripts/lifelog-append.sh "2月22日和家人去爬山了"
```

### 4. 设置定时汇总(可选)

```bash
openclaw cron add \
  --name "LifeLog-每日汇总" \
  --cron "0 5 * * *" \
  --tz "Asia/Shanghai" \
  --session isolated \
  --message "运行 LifeLog 每日汇总"
```

## 支持的日期表达

- 今天/今日/今儿 → 当天
- 昨天/昨日/昨儿 → 前一天
- 前天 → 前两天
- 明天/明儿 → 后一天
- 后天 → 后两天
- 具体日期:2026-02-22、2月22日

## 脚本说明

| 脚本 | 功能 | 使用示例 |
|------|------|----------|
| `lifelog-append.sh` | 实时记录用户消息 | `bash lifelog-append.sh "消息内容"` |
| `lifelog-daily-summary-v5.sh` | 拉取指定日期原文 | `bash lifelog-daily 2026-02-summary-v5.sh-22` |
| `lifelog-update.sh` | 写回分析结果 | `bash lifelog-update.sh "<page_id>" "<情绪>" "<事件>" "<位置>" "<人员>"` |

## 自动汇总工作流

1. 用户发送生活记录 → 调用 `lifelog-append.sh` → 写入 Notion 原文
2. 定时任务触发(每天5点)→ 调用 `lifelog-daily-summary-v5.sh` → 拉取昨日原文
3. LLM 分析原文内容 → 调用 `lifelog-update.sh` → 填充情绪状态、主要事件、位置、人员字段

## 过滤规则

系统会自动过滤以下内容,**不会**记录到 Notion:

| 类型 | 示例 |
|------|------|
| 纯工作指令 | "帮我写代码"、"部署服务"、"git push" |
| 测试消息 | "测试一下"、"试一下" |
| 系统消息 | "设置记录"、"配置Notion" |
| 太短的确认 | 单字或词(如"好"、"嗯") |

**注意**:包含情绪表达的即便是工作相关也会记录,如"写了代码累死了"会被记录。

## 故障排除

### API 请求失败
- 检查 Notion API Key 是否正确
- 确保 Integration 已连接到 Database

### 日期识别不准确
- 确保使用支持的日期表达格式
- 检查系统时区是否正确

### 定时任务不运行
- 检查 cron 任务状态:`openclaw cron list`
- 查看任务运行日志:`openclaw cron runs --id <job_id>`

## 常见问题

**Q: 如何查看今天的记录?**
A: 在 Notion 中搜索今天的日期即可。

**Q: 可以同时记录多条消息吗?**
A: 可以,多次调用会自动追加到同一天的记录中。

**Q: 补录的内容和当天记录有什么区别?**
A: 补录的内容会在时间戳后标记"🔁补录",方便区分。

## ClawHub

本技能已发布到 ClawHub:https://clawhub.com/s/lifelog

## License

MIT

```

### _meta.json

```json
{
  "owner": "421zuoduan",
  "slug": "lifelog",
  "displayName": "Lifelog",
  "latest": {
    "version": "1.2.3",
    "publishedAt": 1773555094435,
    "commit": "https://github.com/openclaw/skills/commit/f1ac03f3fdc1eab22c0083115540a8916871b528"
  },
  "history": [
    {
      "version": "1.1.0",
      "publishedAt": 1772563943416,
      "commit": "https://github.com/openclaw/skills/commit/d59d21758b39a26a1929fa3178cd4ab2c4453df3"
    },
    {
      "version": "1.0.1",
      "publishedAt": 1771866842589,
      "commit": "https://github.com/openclaw/skills/commit/afde9b68bdc4c71bd4aa4a9ddebcc6c0ec4d8ed2"
    },
    {
      "version": "1.0.0",
      "publishedAt": 1771865287231,
      "commit": "https://github.com/openclaw/skills/commit/b99bd7f2980c06dff8e35f035d49d440500f4440"
    }
  ]
}

```

### scripts/lifelog-append.sh

```bash
#!/bin/bash
# LifeLog Recorder - 实时记录单条消息到 Notion(只记录日常生活)
# 使用 OpenClaw SubAgent 智能判断日期

# Notion 凭据 - 从环境变量读取
NOTION_KEY="${NOTION_KEY:-}"
DATABASE_ID="${NOTION_DATABASE_ID:-}"

if [[ -z "$NOTION_KEY" ]]; then
    echo "Error: NOTION_KEY environment variable not set" >&2
    echo "Please set: export NOTION_KEY='your-notion-integration-token'" >&2
    echo "And optionally: export NOTION_DATABASE_ID='your-database-id'" >&2
    exit 1
fi

# 如果没有提供 DATABASE_ID,使用默认值(需要用户替换)
if [[ -z "$DATABASE_ID" ]]; then
    echo "Error: NOTION_DATABASE_ID environment variable not set" >&2
    echo "Please set: export NOTION_DATABASE_ID='your-database-id'" >&2
    exit 1
fi
API_VERSION="2022-06-28"
OPENCLAW_URL="http://localhost:421"

# 参数:消息内容 [可选:日期YYYY-MM-DD]
CONTENT="$1"
OPTIONAL_DATE="$2"

# 使用 SubAgent 判断日期
decide_date_with_subagent() {
    local content="$1"
    
    # 调用 OpenClaw subagent
    local result=$(curl -s -X POST "$OPENCLAW_URL/api/sessions" \
        -H "Content-Type: application/json" \
        -d '{
            "runtime": "subagent",
            "model": "minimax/MiniMax-M2.5",
            "task": "你是 LifeLog 系统的日期判断专家。当前是2026年3月14日(北京时间)。根据以下用户输入的文本,判断这条记录应该属于哪一天。\n\n用户输入:'"$content"'\n\n判断规则:\n1. 如果文本中明确提到「昨天」「前天」「今天」「明天」等,使用对应的日期(昨天=2026-03-13,前天=2026-03-12,大前天=2026-03-11)\n2. 如果没有明确日期,分析上下文(比如「早上」「下午」「晚上」等时间词,结合今天正在进行的活动)\n3. 如果仍然无法判断,输出今天的日期:2026-03-14\n\n只输出日期,格式:YYYY-MM-DD,不要输出其他任何内容。",
            "runTimeoutSeconds": 30
        }')
    
    # 解析返回的日期
    local decided_date=$(echo "$result" | grep -oE "[0-9]{4}-[0-9]{2}-[0-9]{2}" | head -1)
    
    if [ -z "$decided_date" ]; then
        echo ""
    else
        echo "$decided_date"
    fi
}

# 备用:简单日期解析(仅当 SubAgent 完全失败时)
parse_date_fallback() {
    local content="$1"
    local today="2026-03-14"
    
    # 昨天/昨儿
    if echo "$content" | grep -qE "昨天|昨日|昨儿"; then
        date -d "yesterday" +%Y-%m-%d
        return
    fi
    
    # 前天
    if echo "$content" | grep -qE "前天"; then
        date -d "2 days ago" +%Y-%m-%d
        return
    fi
    
    # 今天/今儿
    if echo "$content" | grep -qE "今天|今日|今儿"; then
        echo "$today"
        return
    fi
    
    # 无法判断,返回今天
    echo "$today"
}

# 主逻辑
TODAY=$(date +%Y-%m-%d)

# 如果传入了日期参数,直接使用
if [ -n "$OPTIONAL_DATE" ]; then
    TARGET_DATE="$OPTIONAL_DATE"
    echo "📅 使用传入的日期: $TARGET_DATE"
else
    # 没有传入日期,使用 SubAgent 判断(这里保留接口,未来可以在这里调用 subagent)
    # 目前先用备用方案
    echo "🔍 使用默认日期判断..."
    TARGET_DATE=$(parse_date_fallback "$CONTENT")
fi

# 判断是否为补录
IS_BACKDATE=false
if [ "$TARGET_DATE" != "$TODAY" ]; then
    IS_BACKDATE=true
fi

echo "📅 识别到日期: $TARGET_DATE (今天: $TODAY, 补录: $IS_BACKDATE)"

# 时间戳
if [ "$IS_BACKDATE" = true ]; then
    TIMESTAMP=$(date "+📅 %Y-%m-%d %H:%M 🔁补录")
else
    TIMESTAMP=$(date "+📅 %Y-%m-%d %H:%M")
fi

if [ -z "$CONTENT" ]; then
    echo "❌ 消息内容不能为空"
    exit 1
fi

# 检查是否为纯工作指令
is_work_content() {
    local content="$1"
    local emotion_keywords="觉得|感觉|累|烦|开心|有趣|抽象|无语|好玩|难受|爽|想|希望|花了|搞了|折腾"
    if echo "$content" | grep -qE "$emotion_keywords"; then
        return 1
    fi
    
    local work_keywords="帮我写代码|修改代码|部署服务|启动服务器|运行测试|git push|编译"
    if echo "$content" | grep -qE "$work_keywords"; then
        return 0
    fi
    return 1
}

# 检查是否为测试消息
is_test_or_ack() {
    local content="$1"
    if echo "$content" | grep -qE "^测试|^试一下|测试一下|测试测试"; then
        return 0
    fi
    if [ ${#content} -lt 4 ]; then
        return 0
    fi
    return 1
}

# 检查是否为系统消息
is_system_message() {
    local content="$1"
    local sys_keywords="设置记录|配置Notion|修改LifeLog|记录方式|修改偏好"
    if echo "$content" | grep -qE "$sys_keywords"; then
        return 0
    fi
    return 1
}

# 判断是否需要记录
if is_work_content "$CONTENT"; then
    echo "⏭️ 跳过工作内容: ${CONTENT:0:30}..."
    exit 0
fi

if is_system_message "$CONTENT"; then
    echo "⏭️ 跳过系统消息: ${CONTENT:0:30}..."
    exit 0
fi

if is_test_or_ack "$CONTENT"; then
    echo "⏭️ 跳过测试/确认消息: ${CONTENT:0:30}..."
    exit 0
fi

# 检查目标日期是否已有记录
echo "🔍 检查 $TARGET_DATE 是否有记录..."

RESPONSE=$(curl -s -X POST "https://api.notion.com/v1/databases/$DATABASE_ID/query" \
    -H "Authorization: Bearer $NOTION_KEY" \
    -H "Notion-Version: $API_VERSION" \
    -H "Content-Type: application/json" \
    -d "{\"filter\": { \"property\": \"日期\", \"title\": { \"equals\": \"$TARGET_DATE\" } }, \"page_size\": 1}")

COUNT=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d.get('results',[])))")

if [ "$COUNT" -gt 0 ]; then
    # 追加到现有记录
    PAGE_ID=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['results'][0]['id'])")
    EXISTING=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['results'][0]['properties'].get('原文',{}).get('rich_text',[{}])[0].get('plain_text',''))")
    
    NEW_CONTENT="${EXISTING}"$'\n'"${TIMESTAMP} ${CONTENT}"
    
    echo "📝 追加到现有记录 ${PAGE_ID:0:8}"
    echo "   原有: ${EXISTING:0:50}..."
    echo "   新增: ${CONTENT}"
    
    RESULT=$(curl -s -X PATCH "https://api.notion.com/v1/pages/$PAGE_ID" \
        -H "Authorization: Bearer $NOTION_KEY" \
        -H "Notion-Version: $API_VERSION" \
        -H "Content-Type: application/json" \
        -d "{
            \"properties\": {
                \"原文\": { \"rich_text\": [{ \"text\": { \"content\": \"$(echo "$NEW_CONTENT" | head -1000 | tr '\n' ' ' | sed 's/\"/\\\"/g')\" } }] }
            }
        }")
    
    if echo "$RESULT" | python3 -c "import sys,json; d=json.load(sys.stdin); print('OK' if d.get('object')=='page' else 'FAIL')" 2>/dev/null | grep -q "OK"; then
        echo "NOTION_OK"
    else
        echo "NOTION_FAIL: $RESULT"
    fi
else
    # 创建新记录
    FORMATTED="${TIMESTAMP} ${CONTENT}"
    
    echo "🆕 创建新记录"
    echo "   内容: ${FORMATTED}"
    
    RESULT=$(curl -s -X POST "https://api.notion.com/v1/pages" \
        -H "Authorization: Bearer $NOTION_KEY" \
        -H "Notion-Version: $API_VERSION" \
        -H "Content-Type: application/json" \
        -d "{
            \"parent\": { \"database_id\": \"$DATABASE_ID\" },
            \"properties\": {
                \"日期\": { \"title\": [{ \"text\": { \"content\": \"$TARGET_DATE\" } }] },
                \"原文\": { \"rich_text\": [{ \"text\": { \"content\": \"$FORMATTED\" } }] }
            }
        }")
    
    if echo "$RESULT" | python3 -c "import sys,json; d=json.load(sys.stdin); print('OK' if d.get('object')=='page' else 'FAIL')" 2>/dev/null | grep -q "OK"; then
        echo "NOTION_OK"
    else
        echo "NOTION_FAIL"
    fi
fi

```

### scripts/lifelog-daily-summary-v5.sh

```bash
#!/bin/bash
# LifeLog Daily Summary v5.0
# 第一步:从 Notion 拉取当天原文
# 第二步:输出原文供 LLM 分析(由 cron agentTurn 调用)
# 第三步:LLM 分析后调用 lifelog-update.sh 回写
# 使用前请配置下方的 NOTION_KEY 和 DATABASE_ID

# ===== 配置区域 =====
NOTION_KEY="YOUR_NOTION_API_KEY"
DATABASE_ID="YOUR_DATABASE_ID"
# ====================

# 支持指定日期,默认昨天(因为凌晨5点跑的是昨天的汇总)
if [ -n "$1" ]; then
    TARGET_DATE="$1"
else
    TARGET_DATE=$(date -d "yesterday" +%Y-%m-%d 2>/dev/null || date -v-1d +%Y-%m-%d 2>/dev/null || date +%Y-%m-%d)
fi

echo "📅 拉取 $TARGET_DATE 的 LifeLog 原文..."

RESPONSE=$(curl -s -X POST "https://api.notion.com/v1/databases/$DATABASE_ID/query" \
    -H "Authorization: Bearer $NOTION_KEY" \
    -H "Notion-Version: $API_VERSION" \
    -H "Content-Type: application/json" \
    -d "{\"filter\": { \"property\": \"日期\", \"title\": { \"equals\": \"$TARGET_DATE\" } }}")

TOTAL=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(len(d.get('results',[])))")

if [ "$TOTAL" -eq 0 ]; then
    echo "该日期无记录"
    exit 0
fi

# 提取 page_id 和原文
PAGE_ID=$(echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['results'][0]['id'])")
ORIGINAL=$(echo "$RESPONSE" | python3 -c "
import sys,json
d=json.load(sys.stdin)
props=d['results'][0]['properties']
txt=''
if '原文' in props and props['原文'].get('rich_text'):
    txt=props['原文']['rich_text'][0].get('plain_text','')
print(txt)
")

echo "PAGE_ID=$PAGE_ID"
echo "---原文开始---"
echo "$ORIGINAL"
echo "---原文结束---"

```

### scripts/lifelog-recorder.sh

```bash
#!/bin/bash
# LifeLog Enhanced Recorder v3.0
# 支持内容类型识别 + 生活/任务分离

# Notion 凭据 - 从环境变量读取
NOTION_KEY="${NOTION_KEY:-}"
DATABASE_ID="${NOTION_DATABASE_ID:-}"

if [[ -z "$NOTION_KEY" ]]; then
    echo "Error: NOTION_KEY environment variable not set" >&2
    echo "Please set: export NOTION_KEY='your-notion-integration-token'" >&2
    echo "And optionally: export NOTION_DATABASE_ID='your-database-id'" >&2
    exit 1
fi

# 如果没有提供 DATABASE_ID,使用默认值(需要用户替换)
if [[ -z "$DATABASE_ID" ]]; then
    echo "Error: NOTION_DATABASE_ID environment variable not set" >&2
    echo "Please set: export NOTION_DATABASE_ID='your-database-id'" >&2
    exit 1
fi
API_VERSION="2022-06-28"
SPEC_FILE="/root/.openclaw/workspace/docs/lifelog-spec.md"

# 读取规范文件
load_spec() {
    if [ -f "$SPEC_FILE" ]; then
        echo "✅ 已加载规范: $SPEC_FILE"
    else
        echo "⚠️ 规范文件不存在: $SPEC_FILE"
    fi
}

# 获取今天的日期(带时间戳)
get_timestamp() {
    date "+📅 %Y-%m-%d %H:%M"
}

# 内容类型识别
detect_content_type() {
    local content="$1"
    
    # 任务指令关键词
    local task_keywords="设置|提醒|安装|创建|删除|修改|更新|帮我|请|todo|待办|提醒我"
    
    # 个人生活关键词
    local life_keywords="今天|昨天|明天|起床|睡觉|吃饭|工作|学习|论文|运动|情绪|心情|感受|生活|做了|干了"
    
    # 检查是否包含任务指令
    if echo "$content" | grep -qE "$task_keywords"; then
        if echo "$content" | grep -qE "提醒我|设置.*提醒"; then
            echo "TASK"
        else
            echo "MIXED"
        fi
    elif echo "$content" | grep -qE "$life_keywords"; then
        echo "LIFE"
    else
        local has_time_info=$(echo "$content" | grep -cE "[0-9]+点|[0-9]+:[0-9]|上午|下午|晚上")
        local has_emotion=$(echo "$content" | grep -cE "开心|疲惫|焦虑|充实|愧疚|心情|感受")
        
        if [ "$has_time_info" -gt 0 ] || [ "$has_emotion" -gt 0 ]; then
            echo "LIFE"
        else
            echo "OTHER"
        fi
    fi
}

# 分析生活内容
analyze_life() {
    local content="$1"
    local emotions=""
    local event_type=""
    local location="未知"
    
    # 情绪分析
    if echo "$content" | grep -qE "开心|高兴|愉快|兴奋|满足|充实|不错|挺好|顺利"; then
        emotions="${emotions}开心,"
    fi
    if echo "$content" | grep -qE "疲惫|累|困|疲劳|无力|困倦"; then
        emotions="${emotions}疲惫,"
    fi
    if echo "$content" | grep -qE "焦虑|担心|紧张|压力|烦躁"; then
        emotions="${emotions}焦虑,"
    fi
    if echo "$content" | grep -qE "愧疚|后悔|遗憾|抱歉"; then
        emotions="${emotions}愧疚,"
    fi
    emotions="${emotions%,}"
    [ -z "$emotions" ] && emotions="一般"
    
    # 事件分类
    if echo "$content" | grep -qE "论文|学习|读书|上课|考试"; then
        event_type="学习"
    elif echo "$content" | grep -qE "工作|项目|代码|开发|会议|服务器|编程"; then
        event_type="工作"
    elif echo "$content" | grep -qE "运动|跑步|健身|游泳|骑车"; then
        event_type="运动"
    elif echo "$content" | grep -qE "睡觉|休息|睡眠|午睡"; then
        event_type="休息"
    elif echo "$content" | grep -qE "吃饭|餐饮|美食|外卖|做饭"; then
        event_type="餐饮"
    elif echo "$content" | grep -qE "娱乐|游戏|电影|电视剧|视频"; then
        event_type="娱乐"
    elif echo "$content" | grep -qE "购物|买|消费|花钱"; then
        event_type="消费"
    else
        event_type="日常"
    fi
    
    # 地点
    if echo "$content" | grep -qE "家里|在家|卧室|床|客厅"; then
        location="家里"
    elif echo "$content" | grep -qE "公司|办公室"; then
        location="公司"
    elif echo "$content" | grep -qE "学校|图书馆|实验室|教室"; then
        location="学校"
    elif echo "$content" | grep -qE "咖啡厅|星巴克|奶茶店"; then
        location="咖啡厅"
    fi
    
    echo "{\"emotions\":\"$emotions\",\"event_type\":\"$event_type\",\"location\":\"$location\"}"
}

# 创建日记条目
create_entry() {
    local content="$1"
    
    # 加载规范
    load_spec
    
    # 检测内容类型
    local content_type=$(detect_content_type "$content")
    
    case "$content_type" in
        "LIFE")
            echo "✅ 识别为:个人生活内容"
            ;;
        "TASK")
            echo "🎯 识别为:任务指令"
            echo "💡 提示:任务指令会直接执行,不会记录到日记"
            return
            ;;
        "MIXED")
            echo "⚠️ 识别为:混合内容"
            echo "📝 将提取生活部分记录到日记"
            ;;
        *)
            echo "❓ 内容类型不确定,先记录再说"
            ;;
    esac
    
    # 获取今天日期 (支持参数指定,或自动检测内容中的昨天/今天)
    local today
    if [ -n "$2" ]; then
        today="$2"
    else
        today=$(detect_date "$content")
    fi
    local timestamp=$(get_timestamp)
    
    # 格式化内容
    local formatted="$timestamp"$'\n'"$content"
    
    # 分析
    local analysis=$(analyze_life "$content")
    local emotions=$(echo "$analysis" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['emotions'])")
    local event_type=$(echo "$analysis" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['event_type'])")
    local location=$(echo "$analysis" | python3 -c "import sys,json; d=json.load(sys.stdin); print(d['location'])")
    
    # 转换情绪
    local emotion_json=""
    IFS=',' read -ra EMOTIONS <<< "$emotions"
    for emo in "${EMOTIONS[@]}"; do
        [ -n "$emo" ] && emotion_json="${emotion_json}{\"name\": \"$emo\"},"
    done
    emotion_json="${emotion_json%,}"
    
    echo ""
    echo "📊 分析结果:"
    echo "   情绪: $emotions"
    echo "   事件: $event_type"
    echo "   地点: $location"
    echo ""
    
    # 保存到Notion - 使用 rich_text 类型
    local response=$(curl -s -X POST "https://api.notion.com/v1/pages" \
        -H "Authorization: Bearer $NOTION_KEY" \
        -H "Notion-Version: $API_VERSION" \
        -H "Content-Type: application/json" \
        -d "{
            \"parent\": {\"database_id\": \"$DATABASE_ID\"},
            \"properties\": {
                \"日期\": {\"title\": [{\"text\": {\"content\": \"$today\"}}]},
                \"原文\": {\"rich_text\": [{\"text\": {\"content\": \"$(echo "$formatted" | head -1000 | tr '\n' ' ' | sed 's/\"/\\\"/g')\"}}]},
                \"情绪状态\": {\"rich_text\": [{\"text\": {\"content\": \"$emotions\"}}]},
                \"主要事件\": {\"rich_text\": [{\"text\": {\"content\": \"$event_type\"}}]},
                \"位置\": {\"rich_text\": [{\"text\": {\"content\": \"$location\"}}]}
            }
        }")
    
    if echo "$response" | grep -q "object.*page"; then
        local url=$(echo "$response" | python3 -c "import sys,json; print(json.load(sys.stdin).get('url', 'Unknown'))")
        echo "✅ 已保存到 LifeLog"
        echo "🔗 $url"
    else
        echo "❌ 保存失败: $response"
    fi
}

export -f create_entry load_spec detect_content_type analyze_life

# 自动检测内容中的日期 (增强版,支持多种格式)
detect_date() {
    local content="$1"
    local today=$(date "+%Y-%m-%d")
    local yesterday=$(date -d "yesterday" "+%Y-%m-%d")
    local day_before=$(date -d "yesterday -1 day" "+%Y-%m-%d")
    
    # 检测具体日期格式:3月3日、03月03日、3.3、03.3
    if echo "$content" | grep -qE "[0-9]{1,2}月[0-9]{1,2}日"; then
        local month=$(echo "$content" | grep -oE "[0-9]{1,2}月[0-9]{1,2}日" | head -1 | sed 's/月.*//')
        local day=$(echo "$content" | grep -oE "[0-9]{1,2}月[0-9]{1,2}日" | head -1 | sed 's/.*月//' | sed 's/日//')
        printf "2026-%02d-%02d" "$month" "$day"
    # 检测大前天/前天
    elif echo "$content" | grep -qE "大前天"; then
        date -d "yesterday -2 day" "+%Y-%m-%d"
    elif echo "$content" | grep -qE "前天|前一天"; then
        echo "$day_before"
    # 检测昨天
    elif echo "$content" | grep -qE "昨天|昨日"; then
        echo "$yesterday"
    # 检测大后天/后天
    elif echo "$content" | grep -qE "大后天"; then
        date -d "tomorrow +2 day" "+%Y-%m-%d"
    elif echo "$content" | grep -qE "后天"; then
        date -d "tomorrow +1 day" "+%Y-%m-%d"
    # 检测明天
    elif echo "$content" | grep -qE "明天|明日"; then
        date -d "tomorrow" "+%Y-%m-%d"
    # 检测今天
    elif echo "$content" | grep -qE "今天|今日|刚才|刚刚|现在"; then
        echo "$today"
    else
        # 默认返回昨天(用户回忆往事时通常是说昨天)
        echo "$yesterday"
    fi
}

# 从文件读取内容 (支持长内容)
read_content_from_file() {
    local file="$1"
    if [ -f "$file" ]; then
        cat "$file"
    else
        echo ""
    fi
}

# 执行记录
# 支持三种方式:
# 1. lifelog-recorder.sh "内容" - 直接传内容
# 2. lifelog-recorder.sh -f file.txt - 从文件读取
# 3. lifelog-recorder.sh - - 从stdin读取
if [ "$1" = "-f" ] && [ -n "$2" ]; then
    content=$(cat "$2")
    create_entry "$content" ""
elif [ "$1" = "-" ]; then
    content=$(cat)
    create_entry "$content" ""
else
    create_entry "$1" ""
fi

```

### scripts/lifelog-update.sh

```bash
#!/bin/bash
# LifeLog Update - 将分析结果写回 Notion
# 用法: lifelog-update.sh <page_id> <情绪状态> <主要事件> <位置> <人员>
# 使用前请配置下方的 NOTION_KEY

# ===== 配置区域 =====
NOTION_KEY="YOUR_NOTION_API_KEY"
# ====================

API_VERSION="2022-06-28"

PAGE_ID="$1"
EMOTION="$2"
EVENTS="$3"
LOCATION="$4"
PEOPLE="$5"

if [ -z "$PAGE_ID" ] || [ -z "$EMOTION" ]; then
    echo "用法: lifelog-update.sh <page_id> <情绪状态> <主要事件> <位置> <人员>"
    exit 1
fi

# 转义 JSON 特殊字符
escape_json() {
    echo "$1" | python3 -c "import sys,json; print(json.dumps(sys.stdin.read().strip()))" | sed 's/^"//;s/"$//'
}

E_EMOTION=$(escape_json "$EMOTION")
E_EVENTS=$(escape_json "$EVENTS")
E_LOCATION=$(escape_json "$LOCATION")
E_PEOPLE=$(escape_json "$PEOPLE")

RESULT=$(curl -s -X PATCH "https://api.notion.com/v1/pages/$PAGE_ID" \
    -H "Authorization: Bearer $NOTION_KEY" \
    -H "Notion-Version: $API_VERSION" \
    -H "Content-Type: application/json" \
    -d "{
        \"properties\": {
            \"情绪状态\": { \"rich_text\": [{ \"text\": { \"content\": \"$E_EMOTION\" } }] },
            \"主要事件\": { \"rich_text\": [{ \"text\": { \"content\": \"$E_EVENTS\" } }] },
            \"位置\": { \"rich_text\": [{ \"text\": { \"content\": \"$E_LOCATION\" } }] },
            \"人员\": { \"rich_text\": [{ \"text\": { \"content\": \"$E_PEOPLE\" } }] }
        }
    }")

if echo "$RESULT" | grep -q '"object": "page"'; then
    echo "✅ 已更新 Notion 页面 $PAGE_ID"
else
    echo "❌ 更新失败: $RESULT"
    exit 1
fi

```

lifelog | SkillHub