Skip to content

Latest commit

 

History

History
843 lines (672 loc) · 22.5 KB

File metadata and controls

843 lines (672 loc) · 22.5 KB

PIXIU API 规格文档

本文档定义前端(Module A)与后端(Module C API 网关)之间的全部通信契约。 所有端点、请求结构、响应结构、事件类型的变更须经 Module A + Module C 双方确认。


1. 通信协议

协议 用途 默认端口 说明
HTTP REST 一问一答的操作(写/查/管理) 8765 http://127.0.0.1:8765
WebSocket 服务端推送事件 8765 ws://127.0.0.1:8765/events
D-Bus 桌面生态整合(可选回退至 HTTP) com.kylin.pixiu.Memory

2. 端点一览

方法 路径 说明 实现状态
POST /memory/write 写入一条记忆 ✅ 已实现
POST /memory/query 混合检索(BM25+ANN+Graph) ✅ 已实现(2026-08-10)
GET /evidence/{id} 证据详情(查看原文) ✅ 已实现(2026-08-24)
POST /memory/ocr 图片文字识别(麒麟 kysdk-ocr) ✅ 已实现(2026-08-24,无 SDK 环境返回 503 OCR_UNAVAILABLE)
POST /preference/extract 触发偏好提取 ✅ 已实现
GET /preferences 偏好列表(支持 scope 过滤) ✅ 已实现(2026-08-24)
GET /preference/{id}/history 偏好版本回溯 ✅ 已实现
POST /forget 自然语言遗忘 ✅ 已实现
GET /conflicts 冲突审计列表 ✅ 已实现
POST /memory/flow/promote 短/中期→长期流转 ✅ 已实现(2026-08-10)
POST /sync/token 生成配对令牌(QR/PIN) ✅ 已实现(2026-08-24)
POST /sync/pair 设备配对(QR/PIN + 签名令牌) ✅ 已实现(2026-08-10)
GET /sync/peers 节点列表 ✅ 已实现(2026-08-10)
GET /sync/discover 发现局域网设备(含未配对) ✅ 已实现(2026-08-29)
POST /sync/pair/request 发起确认式配对请求(含 6 位 PIN) ✅ 已实现(2026-08-29)
POST /sync/pair/confirm 确认/拒绝配对请求 ✅ 已实现(2026-08-29)
GET /sync/status 同步状态(含运行时开关 enabled/paused) ✅ 已实现(2026-08-10)
PUT /sync/settings 更新同步开关(enabled/paused,热生效) ✅ 已实现(2026-08-29)
POST /sync/peers/{id}/revoke 解绑设备 ✅ 已实现(2026-08-10)
GET /monitor/config 读取监控配置 ✅ 已实现(2026-08-26)
PUT /monitor/config 写入监控配置(全量提交,热生效) ✅ 已实现(2026-08-26)
GET /monitor/log 监控活动日志(分页,最新在前) ✅ 已实现(2026-08-26)
GET /delivery/insights 洞察流(欢迎页动态建议,最近高质量记忆) ✅ 已实现(2026-08-29)
GET /delivery/digest 定时简报(按日聚合当日记忆沉淀) ✅ 已实现(2026-08-29)
WS /events 事件推送 ✅ 契约已实现(连接/心跳/广播,含全部五类事件)

状态说明(2026-08-29):24 个 REST 端点已全部按本文档契约真实实现; 六类 WebSocket 事件(memory_ready / conflict_detected / forget_confirmation / sync_event / capture_event / pair_request)均已广播。 监控三端点 + capture_event 事件自 frontend/docs/MONITOR_API_REQUIREMENTS.md 转正(Module A + Module C 双方于 2026-08-26 确认)。 pair_request/pair/confirm 通道按计划(2026-08-29)实现;confirm 后仍由前端 走既有 /sync/pair 完成签名入网。


3. 端点详情

3.1 POST /memory/write

写入一条记忆。同步落 evidence 后立即 ACK,结构化处理异步执行。

请求体:

{
  "source_type": "OCR|TOOL_RESULT|USER_BEHAVIOR|MANUAL_CONFIG",
  "raw": {
    "title": "2026年4月家庭支出清单",
    "body": {
      "items": [
        {"category": "水电燃气", "vendor": "国家电网", "amount": 210.00, "date": "2026-04-10", "tags": ["电费"]}
      ]
    },
    "entities": ["国家电网", "市自来水公司"],
    "relations": [
      {"from": "国家电网", "to": "水电燃气", "type": "BELONG_TO"}
    ]
  },
  "scope": "user:alice|shared:home",
  "context": {
    "source_device": "书房工作站",
    "trigger_event": "OCR_RESULT"
  }
}

响应体(200):

{
  "evidence_id": "evd_01H...",
  "status": "accepted",
  "quality_score": 0.94,
  "sensitivity": 0,
  "latency_ms": 42
}

3.2 POST /memory/query

混合检索。

请求体:

{
  "text": "我们好像在水电燃气方面花了一些钱,花了多少钱来着?",
  "context_hint": {
    "time_range": "last_month",
    "scope": "shared:home",
    "top_k": 5
  }
}

响应体(200):

{
  "answer": "2026年4月,你们在水电燃气方面共支出 434.50 元,其中电费 210 元、水费 68.50 元、燃气费 156 元。",
  "source_evidence": ["evd_01H..."],
  "source_knowledge": "knw_02K...",
  "confidence": 0.93,
  "latency_ms": 210
}

3.3 GET /evidence/{id}

按 evidence_id 获取原始证据详情,供前端 EvidenceCard「查看原文」。

响应体(200):

{
  "id": "evd_01H...",
  "source_type": "OCR",
  "raw": { "...": "写入时的原始结构化内容" },
  "quality_score": 0.94,
  "sensitivity": 0,
  "scope": "shared:home",
  "created_at": 1714435200
}

3.4 POST /memory/ocr

图片文字识别。请求体二选一:image_base64(前端上传,≤20MB base64) 或 image_path(本机绝对路径)。无麒麟 kysdk-ocr 环境返回 503 {"error": "OCR_UNAVAILABLE"}

响应体(200):

{
  "text_lines": ["2026年4月家庭支出清单", "电费 210 元"],
  "text": "2026年4月家庭支出清单\n电费 210 元",
  "engine": "KylinOcr",
  "latency_ms": 850
}

3.5 POST /preference/extract

触发偏好提取。

请求体:

{
  "evidence_ids": ["evd_01H..."]
}

响应体:

{
  "extracted_preferences": [
    {
      "id": "pref_...",
      "category": "OP_HABIT|OUTPUT_STYLE|SECURITY_POLICY",
      "key": "output_style.compact",
      "value": {"enabled": true},
      "confidence": 0.85
    }
  ],
  "latency_ms": 1500
}

3.6 GET /preferences

偏好列表,支持 scope 查询参数过滤,供前端 MemoryPanel 偏好选择器使用。

查询参数: scope(可选,e.g. shared:home

响应体(200):

{
  "preferences": [
    {
      "id": "pref_...",
      "category": "OP_HABIT|OUTPUT_STYLE|SECURITY_POLICY",
      "key": "output_style.compact",
      "value": {"enabled": true},
      "confidence": 0.85,
      "version": 3,
      "scope": "shared:home",
      "created_at": 1714435200,
      "updated_at": 1714608000
    }
  ]
}

3.7 GET /preference/{id}/history

偏好版本回溯。

响应体:

{
  "id": "pref_...",
  "key": "output_style.compact",
  "current_version": 3,
  "history": [
    {"version": 1, "value": {"enabled": false}, "updated_at": 1714435200},
    {"version": 2, "value": {"enabled": true}, "updated_at": 1714521600},
    {"version": 3, "value": {"enabled": true, "detail_level": "high"}, "updated_at": 1714608000}
  ]
}

3.8 POST /forget

自然语言遗忘指令。

请求体:

{
  "command": "忘记那张4月支出清单",
  "confirm": false
}

响应体(confirm=false,待确认):

{
  "targets": [
    {"type": "knowledge", "id": "knw_02K...", "title": "2026年4月家庭支出清单"}
  ],
  "cascade": {
    "evidence_count": 1,
    "relation_count": 3
  },
  "irreversible": true
}

响应体(confirm=true,已执行):

{
  "status": "forgotten",
  "forgotten_ids": ["knw_02K...", "evd_01H..."],
  "latency_ms": 85
}

3.9 GET /conflicts

冲突审计列表。

响应体:

{
  "conflicts": [
    {
      "id": "cfl_...",
      "target_knowledge": "knw_02K...",
      "field": "body.items[2].amount",
      "old_value": 156,
      "new_value": 186,
      "resolution": "NEW_WINS",
      "created_at": 1714608000,
      "knowledge_title": "2026年4月家庭支出清单",
      "severity": "medium"
    }
  ]
}

severity(B3-3 起):low | medium | high,按 resolution 派生的打扰级别 (MERGE→low 自动合并静默 / NEW_WINS→medium 自动裁决但用户应知晓 / MANUAL→high 需人工确认)。读取路径始终按 resolution 派生,保证改判后 自洽;SQL 层列值随 save / resolve 同步维护,供过滤与直查。

3.10 POST /memory/flow/promote

短/中期记忆沉淀到长期记忆。

请求体:

{
  "source": "SHORT_TERM|MID_TERM",
  "context_ids": ["ctx_..."],
  "scope": "user:alice"
}

响应体:

{
  "promoted_count": 2,
  "knowledge_ids": ["knw_03K..."],
  "latency_ms": 3200
}

3.11 POST /sync/token

生成设备配对令牌(QR/PIN),供前端 PairDialog 展示二维码或 PIN 码。 注意:method=PIN 时必须提供 6 位数字 pinmethod=QR 时无需 pin。

请求体:

{
  "method": "QR|PIN",
  "pin": "123456",
  "ttl_seconds": 300
}

响应体(200):

{
  "token": "base64_encoded_pairing_token",
  "method": "QR",
  "ttl_seconds": 300
}

3.12 POST /sync/pair

设备配对,加入共享域。

请求体:

{
  "method": "QR|PIN",
  "token": "base64_encoded_pairing_token",
  "pin": "123456"
}

响应体:

{
  "peer_id": "dev_...",
  "device_name": "麒麟笔记本",
  "domain": "shared:home",
  "status": "paired"
}

3.13 GET /sync/peers

节点列表。

响应体:

{
  "peers": [
    {
      "id": "dev_abc",
      "name": "书房工作站",
      "is_self": true,
      "status": "ONLINE",
      "last_sync_ts": 1714608000,
      "pending_ops": 0
    },
    {
      "id": "dev_def",
      "name": "客厅一体机",
      "is_self": false,
      "status": "ONLINE",
      "last_sync_ts": 1714607900,
      "pending_ops": 3
    }
  ]
}

3.14 GET /sync/status

同步状态(SN-4 起含运行时开关)。

响应体:

{
  "domain": "shared:home",
  "peers_online": 2,
  "peers_total": 3,
  "pending_outgoing_ops": 0,
  "last_anti_entropy_ts": 1714608000,
  "total_ops_synced": 1285,
  "enabled": true,
  "paused": false
}

字段说明:enabled 为同步总开关(KV sync_runtime:enabled 覆盖 env 默认 PIXIU_SYNC_NETWORK_ENABLED,未写时回 env 默认——代码默认 true); paused 为数据流暂停(KV sync_runtime:paused,默认 false)。

3.15 POST /sync/peers/{id}/revoke

解绑设备。

响应体:

{
  "status": "revoked",
  "peer_id": "dev_def",
  "domain": "shared:home"
}

3.16 GET /sync/discover

发现局域网内已广播的 PIXIU 设备(含未配对)。paired 标注本地信任关系, 本机自身被过滤。

响应体(200):

{
  "devices": [
    {
      "device_id": "dev_...",
      "device_name": "Alpha",
      "addresses": ["192.168.1.10"],
      "port": 8766,
      "pairable": true,
      "paired": true
    }
  ]
}

字段说明:pairable 来自设备 mDNS 通告(未配对设备广播的可配对标志; 旧版通告缺省 false);paired 表示该设备是否已在本地信任列表 (sync.peers());sync runtime 未启动时返回 {"devices": []}

3.17 GET /monitor/config

读取当前监控配置(daemon 视角的全量状态)。

响应体(200):

{
  "enabled": false,
  "sources": {
    "directory": false,
    "clipboard": false,
    "behavior": false,
    "screenshot": false
  },
  "directories": ["/home/u/Downloads"]
}

字段说明:enabled 全局总闸(关闭时各数据源开关状态保留);sources 四类数据源开关,键名固定 directory | clipboard | behavior | screenshotdirectories 监视目录绝对路径清单(去重、非空)。

3.18 PUT /monitor/config

写入监控配置,请求体结构与 GET 响应一致(全量提交,不做局部 patch)。 服务端持久化配置并对运行中的 daemon 热生效(开启/关闭采集器、增删 inotify 监视点),无需重启。每次成功写入追加一条 state_changed 活动日志 并广播 capture_event

请求体 / 响应体(200,返回归一化后的完整配置):

{
  "enabled": true,
  "sources": {
    "directory": true,
    "clipboard": false,
    "behavior": false,
    "screenshot": false
  },
  "directories": ["/home/u/Downloads"]
}

错误响应(400): 未知 source 名、字段类型错误、目录为相对路径等 → {"error": "INVALID_REQUEST", "message": "...", "request_id": "req_..."}

3.19 GET /monitor/log

分页查询监控活动记录(按时间倒序,最新在前)。limit 缺省 100、上限 500; offset 缺省 0。空日志返回 {"events": []} 而非 404。

查询参数: limit(1–500,默认 100)、offset(≥0,默认 0)

响应体(200):

{
  "events": [
    {
      "ts": 1756080000,
      "source": "directory|clipboard|behavior|screenshot|system",
      "status": "ingested|sensitive_quarantined|ignored|state_changed",
      "summary": "记住文件 支出清单.xlsx",
      "evidence_id": "evd_...",
      "knowledge_id": "knw_..."
    }
  ]
}

字段说明:ts Unix 秒时间戳;sourcesystem(监控自身状态变更, 如总闸开闭);status 四态(ingested / sensitive_quarantined / ignored / state_changed);evidence_id/knowledge_id 事件未产生入库时允许缺失或为 null。summary 由服务端生成用户可读文案,不含敏感原文全文(隔离类条目 只给脱敏摘要)。

3.20 POST /sync/pair/request

发起确认式配对请求(「一键发现+确认配对」GUI 主路径):本机生成 6 位 PIN 并落库(pair_request:{request_id},TTL 60s),随后向所有 WebSocket 客户端 广播 pair_requesttype: "INCOMING")供目标机弹窗确认。确认后仍复用既有 POST /sync/pair 完成签名入网(QR/PIN 令牌流程保留为备选)。

请求体:

{
  "target_device_id": "dev_..."
}

响应体(200):

{
  "request_id": "req_...",
  "pin": "483920",
  "target_device_id": "dev_...",
  "expires_at": 1756080060
}

错误响应(400): 目标 ID 格式非法或自配对 → {"error": "INVALID_REQUEST", "message": "...", "request_id": "req_..."}

3.21 POST /sync/pair/confirm

确认或拒绝一条配对请求(按 request_id 直查本机存储)。accept=true 返回 accepted,实际签名入网由前端在确认成功后自动执行既有 POST /sync/pair (Task SN-6 接线),后端 confirm 仅返回状态。

请求体:

{
  "request_id": "req_...",
  "accept": true
}

响应体(200): {"status": "accepted" | "rejected" | "expired"}

错误响应(404): request_id 不存在 → {"error": "REQUEST_NOT_FOUND", "message": "...", "request_id": "req_..."}

3.22 PUT /sync/settings

更新同步运行时开关(SN-4)。两字段均可缺省,只更新显式传入的键; KV 持久化(sync_runtime:enabled / sync_runtime:paused)+ 热生效: enabled=false 停止 runtime(mDNS 注册与监听停);enabled=true 启动 (若未启动);paused=true 暂停 gossip 数据流(保留发现与配对)。

请求体:

{
  "enabled": false,
  "paused": true
}

响应体(200): 合并后的当前运行时设置(enabled 缺省回 env 默认)

{
  "enabled": false,
  "paused": true
}

3.23 GET /delivery/insights

洞察流(批次④ B4-1):返回最近 24h 入库的高质量记忆候选(按关联证据 quality_score 降序、过滤 sensitivity>0),供聊天窗欢迎页渲染动态建议卡。

查询参数:

参数 类型 缺省 说明
limit int 3 返回条数;上限 10,>10<1 → 400 INVALID_REQUEST

生成规则(服务端,无 LLM):

  • 候选 = 最近 24h 入库(created_at >= now-24h)的 ACTIVE knowledge,scope 为本机 user:local
  • 质量分/敏感度取自关联 Evidence(knowledge_evidence 链接);
  • sensitivity > 0 的候选不出现;summary 为服务端生成文案(标题 + 正文前 60 字), 不含敏感原文;
  • 任一 MANUAL 冲突待处理 → 整体抑制(返回空列表,避免干扰人工裁决);
  • 空库/无候选 → {"insights": []}

响应体(200):

{
  "insights": [
    {
      "title": "2026年4月家庭支出清单",
      "summary": "2026年4月家庭支出清单:本月水电燃气共支出 434.50 元,其中电费 210 元、水费…",
      "knowledge_id": "knw_02K...",
      "score": 0.94,
      "kind": "recent"
    }
  ]
}

错误(400): limit > 10limit < 1INVALID_REQUEST(错误体见 §5)。


3.24 GET /delivery/digest

定时简报(批次④ B4-2):按日聚合当日 monitor_log 捕获事件,服务端规则化 生成中文简报(无 LLM、离线可运行),供前端「今日简报」入口消费。

查询参数:

参数 类型 缺省 说明
date str 今天(本地时区) YYYY-MM-DD;非法格式/无效日历日 → 400 INVALID_REQUEST

生成规则(服务端,无 LLM):

  • 按本地时区日边界取当日 monitor_log 事件(跨日不串);
  • status == "ingested" 计为「新增记忆」,按 source 分组计数 (directory|clipboard|behavior|screenshot|system,无独立「文本」枚举—— 文本文件经目录捕获走 directory,见批次②);
  • sensitive_quarantined 不计入新增,> 0 时单列「另有 N 条敏感内容已隔离」; ignored / state_changed 不计入;
  • summary 为模板计数文案,不含任何事件原始 summary 文本(敏感隔离原则);
  • 空日 → summary 为「当日无新记忆」。

响应体(200):

{
  "date": "2026-08-29",
  "summary": "当日新增 12 条记忆(目录 8、剪贴板 3、行为 1),另有 1 条敏感内容已隔离"
}

错误(400): date 非严格 YYYY-MM-DD(如 2026-13-01 / 2026-02-30 / 2026-1-1 / 非日期)→ INVALID_REQUEST(错误体见 §5)。


4. WebSocket 事件

连接 ws://127.0.0.1:8765/events。JSON 行协议。

4.1 memory_ready ✅ 已实现(写入链路已广播)

{
  "event": "memory_ready",
  "data": {
    "evidence_id": "evd_01H...",
    "knowledge_id": "knw_02K...",
    "title": "2026年4月家庭支出清单",
    "scope": "shared:home"
  }
}

4.2 conflict_detected ✅ 已实现(写入链路冲突仲裁命中时广播)

{
  "event": "conflict_detected",
  "data": {
    "conflict_id": "cfl_...",
    "knowledge_title": "2026年4月家庭支出清单",
    "field": "body.items[2].amount",
    "old_value": 156,
    "new_value": 186,
    "severity": "medium"
  }
}

severity(B3-3 起):low | medium | high,按裁决方式派生 (MERGE→low / NEW_WINS→medium / MANUAL→high,见 §3.9)。前端按此分流 打扰级别:low 静默仅计数 / medium 温和通知+角标 / high 全动作。 旧后端广播无此字段时,前端缺省按 high 处理(宁可打扰不漏报)。

4.3 forget_confirmation ✅ 已实现(遗忘执行后广播,含 targets/forgotten_ids/expires_at)

{
  "event": "forget_confirmation",
  "data": {
    "command": "忘记那张4月支出清单",
    "targets": [
      {"type": "knowledge", "id": "knw_02K..."},
      {"type": "evidence", "id": "evd_01H..."},
      {"type": "relation", "count": 3}
    ],
    "expires_at": 1714608100
  }
}

4.4 sync_event ✅ 已实现(配对/解绑时已广播)

{
  "event": "sync_event",
  "data": {
    "type": "PEER_ONLINE|PEER_OFFLINE|SYNC_COMPLETE|ANTI_ENTROPY_DONE",
    "peer_id": "dev_def",
    "peer_name": "客厅一体机",
    "timestamp": 1714608000
  }
}

4.5 capture_event ✅ 已实现(2026-08-26,监视捕获/状态变更时已广播)

每次目录捕获(ingested / sensitive_quarantined / ignored)与监控配置变更 (state_changed)推送;data 与 §3.19 日志条目同构,knowledge_id 可缺 (事件未产生入库时为 null)。

{
  "event": "capture_event",
  "data": {
    "source": "directory",
    "status": "ingested",
    "summary": "记住文件 支出清单.xlsx",
    "ts": 1756080000,
    "evidence_id": "evd_...",
    "knowledge_id": "knw_..."
  }
}

前端行为:普通事件 → 角标 +1(可选)+ 监控中心「活动记录」实时追加; sensitive_quarantined 额外弹系统通知(隔离区查看/恢复交互属批次③范围)。

4.6 pair_request ✅ 已实现(2026-08-29,发起配对请求时已广播)

本机发起 POST /sync/pair/request 后全局广播(前端按目标设备过滤展示, 确认对话框接线见 Task SN-6)。MVP 语义:from_device_id 为请求目标设备 (request_id 由本机生成,confirm 也按 request_id 查本机存储);from_name 留空,由前端在确认成功后展示目标设备名。

{
  "event": "pair_request",
  "data": {
    "type": "INCOMING",
    "request_id": "req_...",
    "from_device_id": "dev_...",
    "from_name": "",
    "pin": "483920",
    "expires_at": 1756080060
  }
}

5. 错误码

错误码 HTTP 状态码 说明
INVALID_REQUEST 400 请求体不符合 Schema
NOT_FOUND 404 资源不存在
CONFLICT_TIMEOUT 408 遗忘确认超时
PAIRING_FAILED 422 设备配对失败
PEER_NOT_FOUND 404 解绑的设备 ID 不存在
REQUEST_NOT_FOUND 404 配对请求 ID 不存在
INTERNAL_ERROR 500 后端内部错误

错误响应体格式:

{
  "error": "INVALID_REQUEST",
  "message": "field 'source_type' must be one of: OCR, TOOL_RESULT, USER_BEHAVIOR, MANUAL_CONFIG",
  "request_id": "req_..."
}

错误响应实现(2026-08-11):后端经 request_id 中间件将错误响应统一对齐 上述 §5 契约({error, message, request_id}):

  • HTTPException → 原状态码 + {error:<错误码>, message:<错误码>, request_id}
  • 参数校验失败 → 400 + INVALID_REQUEST
  • 未捕获异常 → 500 + INTERNAL_ERROR
  • 所有响应携带 X-Request-Id 响应头。 前端 parseBackendError 同时兼容 error 与早期 detail 两种形状,错误码不丢失。