/api| Method | Path | Description |
|---|---|---|
| GET | /api/pkg/{npcid} | Query character PKG |
| PUT | /api/pkg/{npcid} | Update character PKG fields |
| GET | /api/relationship/{npcid} | Query character relationships |
| GET | /api/diary/{npcid} | Query character diary |
| POST | /api/dream/{npcid} | Trigger character dreaming (memory consolidation) |
GET /api/pkg/{npcid}| Parameter | Type | Required | Description |
|---|---|---|---|
| npcid | string | Yes | Unique character identifier |
{
"npcid": "abc123",
"pkg": {
"Name": "Xiao Ming",
"Nickname": ["Mingming", "Little M"],
"Hobbies": ["Reading", "Running"],
"Important Friends": ["Xiao Hong"],
"voice_registered": true
}
}{
"status": "error",
"message": "Error details"
}PUT /api/pkg/{npcid}| Parameter | Type | Required | Description |
|---|---|---|---|
| npcid | string | Yes | Unique character identifier |
{
"updates": [
{"key": "Hobbies", "value": "Swimming,Painting"},
{"key": "Favorite Books", "value": ["Three-Body Problem", "One Hundred Years of Solitude"]}
]
}| Parameter | Type | Required | Description |
|---|---|---|---|
| updates | array | Yes | Array of update items, each containing key and value |
| updates[].key | string | Yes | PKG field name |
| updates[].value | string / array | Yes | Field value; multi-value fields can use comma-separated strings or arrays |
| Field Name | Item Limit |
|---|---|
| Nickname | 5 |
| Important Friends | 10 |
| Other Important People | 10 |
| Important Appointments | 10 |
| Favorite Books | 10 |
| Favorite Movies | 10 |
| Favorite Sports | 10 |
| Hobbies | 10 |
| Entertainment and Leisure | 10 |
key is emptykey is a protected field (voice_registered, face_registered)key is Name and the current name is non-empty{
"status": "ok",
"updated_fields": ["Hobbies", "Favorite Books"]
}{
"status": "error",
"message": "updates cannot be empty"
}{
"status": "error",
"message": "NPC abc123 does not exist or has no PKG"
}{
"status": "error",
"message": "Error details"
}GET /api/relationship/{npcid}| Parameter | Type | Required | Description |
|---|---|---|---|
| npcid | string | Yes | Unique character identifier |
{
"npcid": "abc123",
"relationship": {
"entity_001": {
"name": "Xiao Hong",
"alias": ["Honghong"],
"title": ["Classmate"],
"remark": "Often plays basketball together"
},
"entity_002": {
"name": "Teacher Zhang",
"alias": [],
"title": ["Class Teacher"],
"remark": "Math teacher"
}
},
"count": 2
}| Field | Type | Description |
|---|---|---|
| npcid | string | Character ID |
| relationship | object | Relationship data, keys are entity IDs |
| relationship.{id}.name | string | Person's name |
| relationship.{id}.alias | array | List of aliases |
| relationship.{id}.title | array | List of titles |
| relationship.{id}.remark | string | Remarks |
| count | number | Total number of relationship entries |
{
"status": "error",
"message": "Error details"
}GET /api/diary/{npcid}| Parameter | Type | Required | Description |
|---|---|---|---|
| npcid | string | Yes | Unique character identifier |
{
"npcid": "abc123",
"prior": "Xiao Ming is a sports enthusiast, often playing basketball with friends...",
"dailies": [
{
"date": "2026-04-08",
"summary": "Went to the library with Xiao Hong today, discussed the new project plan..."
},
{
"date": "2026-04-07",
"summary": "Attended the department weekly meeting, shared last week's work progress..."
}
],
"count": 2
}| Field | Type | Description |
|---|---|---|
| npcid | string | Character ID |
| prior | string | Historical summary (merged memories outside the rolling window) |
| dailies | array | Recent daily diaries, sorted by date |
| dailies[].date | string | Date in YYYY-MM-DD format |
| dailies[].summary | string | Daily diary summary |
| count | number | Total number of diary entries |
{
"status": "error",
"message": "Error details"
}POST /api/dream/{npcid}| Parameter | Type | Required | Description |
|---|---|---|---|
| npcid | string | Yes | Unique character identifier |
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
| dry_run | string | No | false | When set to true, only computes results without writing to the database |
{
"status": "ok",
"report": {
"skipped": false,
"diary": {
"date": "2026-04-09",
"diary_text": "Discussed travel plans with the user today...",
"prior_merged": false,
"overflow_count": 0
},
"extractions": {
"entity_ops_count": 2,
"pkg_updates_count": 3,
"entity_ops": [...],
"pkg_updates": [...],
"rel_written": true,
"pkg_written": true
},
"cleanup": {
"content_hybrid_deleted": 5,
"emotion_v2_deleted": 3
},
"error": null
}
}| Field | Type | Description |
|---|---|---|
| skipped | boolean | Whether skipped. When true, no new data was found and subsequent steps were not executed |
| diary | object / null | Diary generation result. Contains date, diary_text, prior_merged, overflow_count |
| extractions | object / null | Entity extraction result. Contains entity_ops_count, pkg_updates_count, rel_written, pkg_written |
| cleanup | object / null | Expired vector cleanup result. Contains content_hybrid_deleted, emotion_v2_deleted |
| error | string / null | Error message. Multiple errors are separated by semicolons |
skipped is true, diary, extractions, and cleanup are all null.dry_run=true, each step computes normally but does not write to the database. diary and cleanup may contain dry_run: true markers.{
"status": "error",
"message": "Error details"
}| HTTP Status Code | Description |
|---|---|
| 200 | Request successful |
| 400 | Invalid request parameters (e.g., updates is empty) |
| 404 | Resource not found (e.g., NPC does not exist or has no PKG) |
| 500 | Internal server error |
{
"status": "error",
"message": "Detailed error description"
}