Memories / 文件

本頁目錄

人格卡片

人格卡片是跨產品的身分卡片,可在 Grok Bot、Muse 等用戶端之間同步個性與行為。保管庫中的副本具有權威性。

分層

  1. 核心(慢速) — 說話與行動的方式。儲存為人格卡片本文,並透過 persona_card / memories persona put 管理修訂(與其他記憶及卡片使用相同的簽章修訂 DAG)。
  2. 封存/情節記憶(中速) — 日誌、外觀、契約、觀點、台詞、操作等。儲存為獨立的一般知識卡片,從人格設定檔(archives[])連結,並映射為圖譜中的 persona_archive:<kind> 卡片連結。不要將封存內容併回核心。
  3. 行為事件(快速) — 透過 persona_append_event / memories persona append-event,在連結的 events 封存中維護僅可附加的事件串流。

設定檔欄位

欄位 意義
persona_id 穩定 ID(例如技能前置資料的 name)
display_name 供人閱讀的標題(例如 小雅 / 李雅)
aliases 別名
timezone IANA 名稱(例如 Asia/Singapore)。未設定或舊卡片預設為 Asia/Singapore
day_boundary 選填的本機 HH:MM,表示日曆日期切換(隔日)時間。未設定 = 本機午夜
world 即時世界快照:place/pose/look/body、通用 things(id→{name,description,images,attrs JSON})、帳本(counters + counters_today、as_of_local_date)、天氣、工具
本文 / core Markdown/文字行為指示
traits 選填的字串對應表(版本、語言等)
bindings { product, agent } 產品綁定
memory_policy / sync_hints 選填的同步指引
archives { kind, card, vault?, title? } 連結的資產

summary.type 為 persona,包含 persona_id、display_name、timezone、day_boundary、place、pose、look、things_count、has_weather、alias_count、archive_count 及 binding_count。

時區、隔日、早課/晚課

人格以當地時鐘推理,而非僅使用 UTC 紀元時間。

  1. 時區 — 每個人格都有 IANA timezone。匯入時從 SKILL.md 讀取 timezone / metadata.timezone;CLI 可透過 --timezone Asia/Singapore 覆寫。示範中未設定時預設為 Asia/Singapore。
  2. 日曆日期(隔日) — 除非設定 day_boundary(例如以 05:00 延後深夜換日),當地民用日期以該時區的午夜為界。帳本/日誌的「新的一天」檢查應比較時間戳記輔助函式的 local_date,而非 UTC 日期。
  3. 時段(當地時間,半開區間):
時段 當地時間
early_morning [00:00, 05:00)
morning [05:00, 12:00)
afternoon [12:00, 18:00)
evening [18:00, 22:00)
night [22:00, 24:00)

晚課/「仍是同一個晚上」的跨夜連續性使用 [22:00, 05:00)(night ∪ early_morning)範圍。早課對應 morning(也可包含較晚的 early_morning);晚課對應 evening / night。 4. 事件時間戳記 — persona_append_event 在事件封存標題及 JSON 回應中,同時寫入 UTC 與當地 ISO-8601(含時差),以及 timezone、period 與 local_date(utc、local、timezone、period、local_date、timestamp 為 Unix UTC)。

核心輔助函式(Rust):memories_core::persona 中的 persona_local_now、classify_period、stamp_persona_now、format_event_heading。

世界領域分類(世界狀態域)

world 是領域/標籤,不是將資料傾倒至核心的地方。核心(SKILL.md 本文)僅保留語氣/規則。

層級 意義 儲存位置
world 場景 + 帳本 + 工具 + 天氣的領域 profile.world + 標記為 world 的封存
things 具有自由 JSON 屬性的通用物品(任意名稱:桌子/杯子/燈等) world.things + 封存 things/wardrobe
scene 地點(居所)、姿態、外觀(今日裝扮摘要)、身體 world.place/pose/look/body;詳細外觀位於封存 look
ledger 計數器、餐點、命令、常設事項 world.counters/counters_today/meals/orders_*/standing + 封存 ledger
tools 骰子、轉盤、日程 world.dice/spinners/schedule + 封存 dice/spinner/schedule
weather 環境狀況/溫度/濕度/風(+ 選填預報) world.weather / world.forecast + 封存 weather
automation 掛鉤(schedule/random/webhook/attr_change/chat_message)+ 動作 world.automation

時區(profile.timezone)位於 world 之外,但隔日、早課/晚課及日程的當地時間都需要它。

從 xiaoya 測試資料研究 → 已實作

需求(來自外觀/日誌/操作) 欄位/封存
當地日期/隔日/早課晚課 timezone、day_boundary、時段輔助函式
固定 + 今日穿著 封存 look;摘要 world.look
物品清單(任意命名物品 + 自由 JSON 屬性/圖片) world.things ↔ 封存 things/wardrobe;CLI persona thing
居所/姿態 world.place、world.pose
動作計數器(累計與今日) world.counters(累計)、world.counters_today(每日)
今日吃了 world.meals
奉令未辦/已辦 world.orders_pending、world.orders_done
常設 world.standing
身體註記 world.body
遊戲工具 world.dice、world.spinners、world.schedule
天氣/短期預報 world.weather、world.forecast ↔ 封存 weather

自動化(world.automation)

具名掛鉤含有觸發條件 + 動作,儲存於人格世界快照(cron/本機日程使用人格時區)。

觸發條件 type 意義
cron 人格當地時間的 M H 或 M H * * DOW
local_time HH:MM + 選填 days(與日程相同)
random_interval 在 [min_secs, max_secs] 的隨機延遲後觸發
random_and_timed 當地時間 + 選填 jitter_secs
webhook 傳入 HTTP / CLI --source webhook
attr_change 在 thing attr set/delete 後,當 thing_id 相符,且路徑篩選器完全相符或為前綴時觸發
chat_message 在 persona chat send 時,每位參與者各觸發一次(相同事件;選填 peer 為另一張人格卡片 ID,可為完整 ID 或清單中的短 ID)
manual CLI/MCP automation trigger --source manual
動作 type 意義
set_attr 設定物品屬性路徑(設定時建立)
random_attr dice / range / choice
call_function 內建函式:inc、dec、clamp、roll、set_weather_stub
append_event 附加至事件封存
webhook_out 對 URL 傳送 HTTP POST JSON

常駐程式 HTTP(啟用 --listen 時):

POST /v1/persona/{vault}/{persona}/automation/trigger
Authorization: Bearer <world.automation.webhook_token>
Content-Type: application/json

{"hook":"HOOK_ID"}

掛鉤僅透過明確的自動化執行/觸發路徑觸發(包含現有屬性變更觸發條件,以及人格聊天傳送時的 chat_message)。呼叫 persona automation run 會補執行八天內最近一次錯過的 cron/當地時間時段,最多一次,而非重播所有錯過的時段。星期篩選仍套用於該次發生時間;定時隨機掛鉤保留其抖動門檻。RandomInterval 不變。常駐程式沒有自動化計時器:Service::tick 僅處理工作階段、授權及遠端狀態的到期。

傳出的 webhook_out 動作要求 world.automation.webhook_allowlist 中存在完全相符的 URL;預設空清單會阻擋每個 POST。請使用 persona automation webhook-allow VAULT PERSONA --add https://example.com/hook(可重複 --add / --remove)或 MCP persona_automation_webhook_allow 明確管理項目。項目必須是無使用者資訊或空白的 HTTP(S) URL,最多 2048 位元組。此清單是公開設定,但傳入的 webhook_token 仍屬機密,絕不會在用戶端檢視中回傳。允許清單不會引入背景 POST。

暫緩項目(原因)

構想 暫緩原因
即時天氣 API 用戶端 代理設定/查詢保管庫狀態;在外部擷取後執行 world-set
電話/通知 依產品而異;不是保管庫的真實狀態
錢包/金錢遊戲 需求較小;需要時可使用 things + 計數器
同伴 NPC 需要自己的圖譜/卡片
居所內的房間圖譜 目前編碼於 place 字串
將衛生/睡眠作為一級功能 使用 standing / schedule / body
world-set 時自動編輯 look.md「今日」 保留詳細測試資料;代理以 card put 更新外觀封存

代理同步流程

  1. world-get / persona_world_get → 讀取快照、local_date、period、revision 及 stale_day。缺少 as_of_local_date 即視為過期;否則 stale_day 會將帳本日期與套用 day_boundary 後的人格當地日期比較。weather_age_secs 是有效 RFC3339 觀測資料的帶正負號經過時間;缺少/無效時為 null。
  2. 隔日時,明確呼叫 persona world-rollover VAULT PERSONA / persona_world_rollover。此換日路徑會清除 meals、orders_done、簡短 look 摘要及 counters_today,並將 as_of_local_date 設為今天的當地帳本日期。累計 counters、standing、things、待辦命令、場景/身體、工具、天氣/預報及自動化均保留。不會編輯外觀封存或 look.md「今日」。
  3. world-set 僅更新已提供的場景/物品/帳本/工具/天氣欄位。即使已過期,也絕不在隔日時默默換日或清除每日欄位。它會建立缺少的 as_of_local_date 而不清除現有欄位,並一律標記世界層級的 updated_at(UTC、Z)及 updated_local(含時差的人格當地 ISO)。persona_card 原樣儲存提供的世界資料,包括過去的帳本日期。
  4. 使用 world-get 取得的 --expected-revision HASH / MCP expected_revision 防止更新遺失:目前頂端雜湊不符時,會在修改前回傳衝突。省略時仍採最後寫入者優先。每日計數器使用 --counter-today NAME=VALUE;--clear-counter NAME 與 --clear-counter-today NAME 刪除累計/每日鍵(皆可重複)。
  5. 封存同步只處理該次呼叫提供的領域。既有卡片只有在本文仍是變更前產生的範本時才會取代;手寫文字會保留,並回報為 synced_archives[kind] = "preserved"。這也適用於物品新增/刪除/屬性同步,以及換日的帳本同步。變更物品會同時同步 things 與 wardrobe。既有外觀封存一律保留。
  6. 物品數量對應表的鍵/--item ID=COUNT 使用穩定的 ID,絕不依顯示名稱查找。既有 ID 只更新數量而不重新命名;零只移除該 ID。屬於另一個 ID 的顯示名稱會遭拒絕。未知鍵仍沿用舊行為,以該 ID 及名稱建立物品。
  7. dice-roll / spinner-spin / schedule-list 提供具時區感知的工具。詳細外觀/日誌編輯使用一般 card put;選填的 append-event(例如 kind=weather)可記錄行為而不重寫封存文字。

CLI

# Import a skill directory (SKILL.md + references/*.md)
memories persona import VAULT_ID /path/to/xiaoya-persona --timezone Asia/Shanghai
# equivalent:
memories card persona-import VAULT_ID /path/to/xiaoya-persona

# Create / update core
memories persona put VAULT_ID --title "小雅 / 李雅" \
  --persona-id xiaoya-persona --display-name "小雅 / 李雅" \
  --timezone Asia/Shanghai \
  --core-file ./SKILL.body.md --alias-name 小雅 --alias-name 李雅 \
  --binding grok_bot:default --archive contract=CARD_ID

memories card persona VAULT_ID --title "…" --persona-id … --display-name … \
  --timezone Asia/Singapore --core-file …

# Append a behavior event (stamped UTC + local)
memories persona append-event VAULT_ID PERSONA_ID --text "…" --kind note

# World things / weather
memories persona world-get VAULT_ID PERSONA_ID
memories persona world-set VAULT_ID PERSONA_ID \
  --place "客厅书桌旁" --pose "坐着,整理笔记" \
  --look "白衬衫、浅色长裙、白色帆布鞋" \
  --item 白色衬衫=1 --item 马克杯=1 --item 白色帆布鞋=1
memories persona world-set VAULT_ID PERSONA_ID \
  --weather-condition "多云" --weather-temp-c 28 --weather-humidity 72 \
  --weather-wind "微风" --weather-location "上海" \
  --forecast 2026-10-02:晴:30:22 --forecast 2026-10-03:小雨:26:20

# Generic things (任意物品; attrs = unrestricted JSON)
memories persona thing put VAULT_ID PERSONA_ID --id mug --name 马克杯 \
  --description "白色陶瓷马克杯" --tag kitchen --count 1 \
  --attrs '{"wear":80,"material":"ceramic","sizes":["S","M"]}'
memories persona thing list VAULT_ID PERSONA_ID
memories persona thing get VAULT_ID PERSONA_ID --id mug
memories persona thing image VAULT_ID PERSONA_ID --id mug --file ./mug.jpg
memories persona thing delete VAULT_ID PERSONA_ID --id mug

# Single-field attrs (dotted path or JSON Pointer; create-on-set)
memories persona thing attr get VAULT_ID PERSONA_ID --id mug --path nested.wear
memories persona thing attr set VAULT_ID PERSONA_ID --id mug --path nested.wear --value 70
memories persona thing attr set VAULT_ID PERSONA_ID --id mug --path /nested/deep/x --value 1
memories persona thing attr delete VAULT_ID PERSONA_ID --id mug --path nested.deep.x

# Automation hooks (stored on world.automation; timezone = persona timezone)
memories persona automation put VAULT_ID PERSONA_ID \
  --hook '{"id":"morning","trigger":{"type":"local_time","time":"07:00"},"actions":[{"type":"call_function","name":"set_weather_stub","args":{"condition":"晴","temp_c":26}}]}' \
  --webhook-token secret-token
memories persona automation list VAULT_ID PERSONA_ID
memories persona automation run VAULT_ID PERSONA_ID
memories persona automation trigger VAULT_ID PERSONA_ID --id morning --source manual
memories persona automation delete VAULT_ID PERSONA_ID --id morning

# Read / history / diff (same as other cards; summary shows timezone)
memories card read VAULT_ID PERSONA_ID
memories card history VAULT_ID PERSONA_ID
memories card diff VAULT_ID PERSONA_ID REVISION_ID
memories card list --type persona

Webhook 權杖保留於加密的人格狀態,供傳入驗證、同步及備份使用,但用戶端回應不會回傳權杖。世界 get/set、自動化 put/list、一般卡片讀取(包含歷史及無人值守讀取)及封存讀取,在自動化檢視中僅公開 webhook_token_set。請妥善保存已配置的權杖;設定替代值即可輪替。

同一保管庫中兩張人格卡片的聊天使用一般對話卡片,以及各人格的讀取游標;讀取歷史不會將訊息標為已讀。傳送訊息會觸發每位參與者的 chat_message 掛鉤;承載資料包含 vault、from、to 及 message_id,不包含訊息文字。

memories persona chat send VAULT_ID PERSONA_A PERSONA_B --text "Hello"
memories persona chat list VAULT_ID PERSONA_B
memories persona chat history VAULT_ID PERSONA_A --with PERSONA_B --limit 20
memories persona chat mark-read VAULT_ID PERSONA_B --with PERSONA_A

MCP

具備寫入授權時:persona_write(選填 timezone / day_boundary)、persona_append_event、persona_world_get、persona_world_set、persona_world_rollover、persona_thing_put/get/list/delete、persona_thing_attr_get/set/delete、persona_automation_list/put/delete/run/trigger、persona_automation_webhook_allow、persona_dice_roll、persona_spinner_spin、persona_schedule_list、persona_chat_send、persona_chat_list、persona_chat_history、persona_chat_mark_read。歷史與差異比較使用現有的 memory_history / memory_diff / memory_read 工具(人格卡片修訂包含 world.*;衣櫥/地點/姿態封存各自擁有歷史)。

為代理產生 AGENTS.md/技能

memories default set persona VAULT/PERSONA
memories skill generate --out AGENTS.md --persona VAULT/PERSONA
memories agents generate --out ./skills/memories-persona --layout skill

產生的檔案摘要說明保管庫/卡片/人格/世界操作;選取人格時,會嵌入該人格的核心概覽,以及世界、物品與事件的 CLI/MCP 操作範例。請參閱 README 的技能產生。

同步註記(Grok Bot / Muse)

將保管庫人格卡片及其連結封存視為唯一真實來源。本機技能目錄只是匯入/匯出的便利工具;匯入後,代理應讀取保管庫(card read / MCP memory_read),而非過期的檔案系統副本。核心變更透過 persona put;封存編輯透過對封存資產執行一般 card put;短期行為則使用 append-event 附加。判斷隔日、早課或晚課時,請使用人格的 timezone(及選填 day_boundary)— 不要僅依代理主機時鐘推斷日期邊界。

技能目錄結構

xiaoya-persona/
  SKILL.md              # frontmatter name/type/version/timezone + core markdown
  references/
    contract.md
    journal.md
    look.md
    lines.md
    ops.md
    views-index.md
    view-*.md

匯入會將 SKILL.md 映射為人格核心,並將每個 references/*.md 映射為連結的封存卡片(kind = 不含副檔名的檔名)。封存內容會以使用者內容原樣儲存。

前置資料鍵:timezone 或 metadata.timezone(IANA);選填 day_boundary / metadata.day_boundary(HH:MM)。

本機示範保管庫

在開發機器上,可以使用版本庫中的 xiaoya 測試資料初始化可拋棄的保管庫:

cargo run -p memories-core --example seed_xiaoya_persona

這會寫入 /workspace/persona-demo-vault(密碼 persona-demo-password),以及包含保管庫與資產 ID(包括 timezone)的 SEED.json / README.md。若要對執行中的常駐程式重現 CLI 匯入,請執行:

memories persona import VAULT_ID testdata/xiaoya-persona