Files
hunjing/docs/contracts/internal-api.md
T
chenxin 42513d13c6 📝 docs: 建立魂镜完整 1.0 设计文档体系
- 产品层:产品宪章与永久禁域、产品定义、完整 1.0 范围与发布门、道家文化语言体系、指标与反指标
- 研究层:参考项目研究(deepseek-harness、pi、MemOS、模型网关)、灵台原生引擎研究(业界原生引擎架构理念与道家文化出处)
- 架构层:系统、Agent 运行时(周天体系)、插件系统、灵台引擎(C++ 双形态)、媒体与设备、社区协作市场、前端富内容渲染、数据、记忆与知识
- 契约层:协议与稳定标识、API 总体约定、Native API、兼容网关、实时与 Webhook、内部端口、统一 ContentBlock 与流式(含分支对话交互态)、灵台 C ABI 与 gRPC Service、API 表面、HTTP 与事件、运行观测
- 决策:ADR-001 至 ADR-023(模块化单体、每 attempt 持久化、候选记忆、OAuth 2.1、灵台引擎、双形态部署、大周天演化、宪章、三界作用域、私箧与保全态、叩心、周天统一等)
- 交付:WP-01 至 WP-15 实施 TODO 与设计阶段交接文档
- 工程:AGENTS.md 工程规则(含 C++/灵台规范)、CLAUDE.md 引用、.gitignore
2026-09-09 21:07:14 +08:00

6.8 KiB
Raw Blame History

内部端口、事件与插件协议

1. 原则

模块化单体内部不为每个模块创建 HTTP。领域模块通过类型化 Port、Command、Query 和 Domain Event 交互;只有独立扩缩容或安全边界才使用私有网络协议。

flowchart LR
  API[Native API] --> CMD[Application Commands]
  CMD --> DOMAIN[Domain Modules]
  DOMAIN --> OUTBOX[(Transactional Outbox)]
  OUTBOX --> WORKER[Workers]
  DOMAIN --> PORTS[Provider and Tool Ports]
  PORTS --> MODEL[Model Adapters]
  PORTS --> PLUGIN[Plugin RPC]
  PORTS --> SANDBOX[Sandbox RPC]

2. 应用 Command

核心 Command 示例:

CreateCharacter
CreateConversation
AppendConversationMessageAndStartRun
StartTaskRun
SteerRun
CancelRun
ResumeRun
DecideApproval
CreateMemoryCandidate
DecideMemoryCandidate
PublishRelease
InstallPlugin
GrantDeviceCapability
CreateOrder
ApplyPaymentEvent
CreateRefund
CreateSettlement
DecideModerationCase

每个 Command 包含 command_id、actor、scope、trace context、idempotency key、occurred_at 和类型化 payload。Handler 在一个事务中写权威状态、AuditEvent 和 OutboxEvent。

3. Query Port

Query 返回授权后的 DTO,不返回 ORM Entity 或裸数据库连接。调用方必须提供 actor/scope;Repository 自身再次施加数据域条件,避免只在 API 层授权。

高成本检索使用显式 Query:SearchMemories、SearchCommunity、BuildContextSnapshot、CalculateOrderQuote。交易报价必须返回 price version 和 expires_at。

4. Domain Event 与 Outbox

Domain Event/Outbox 记录已提交领域事实,使用 payload 和聚合版本;公共 SSE 使用 HTTP 与事件契约 的 data、Run sequence 和公开事件名;Normalized Model Event 只存在于 Model Adapter→Runtime 流中。Runtime 必须显式完成三层映射,不把 Provider/Normalized 事件原样作为公共事件或领域事实持久化。

Event envelope:

{
  "id": "event_01...",
  "type": "run.queued",
  "aggregate_type": "run",
  "aggregate_id": "run_01...",
  "aggregate_version": 1,
  "personal_domain_id": "domain_01...",
  "trace_id": "trace_01...",
  "occurred_at": "2026-09-03T08:00:00Z",
  "payload": {}
}

消费者按 event ID 幂等。事件只陈述已提交事实,不使用 *.requested 假装命令。命令需要结果时调用 Application Port;异步请求创建 Job/Run 资源。

5. Normalized Model Port

ModelGateway.invoke(NormalizedRequest) -> AsyncIterator<NormalizedEvent>
ModelGateway.count_tokens(NormalizedRequest) -> TokenCount
ModelGateway.list_models(scope) -> ModelCapabilities[]

NormalizedRequest 包含逻辑模型、标准 content blocks、tools、tool choice、output contract、thinking/effort hint、cache plan、预算、地区、隐私级别和 trace。它不包含 Provider SDK 类型。

NormalizedEvent:

response.started
content.block.started
text.delta
thinking.summary.delta
tool.call.delta
tool.call.completed
usage.updated
response.completed
response.failed

Adapter 负责协议转换、Provider Header allowlist、错误分类、上游 request ID、usage 标准化和能力校验;Gateway Kernel 负责路由、重试边界、预算、ModelCall 持久化和首个可见事件提交。Runtime 将 text.delta、tool.call.* 等 Normalized Event 映射为统一 ContentBlock 与 content.block.* 公共 SSE;response.* 只控制内部调用生命周期,不直接进入公共事件表。

6. Tool Runtime Port

ToolRegistry.snapshot(scope) -> ToolSnapshot
Policy.evaluate(ToolInvocation, ActorContext) -> PolicyDecision
ToolExecutor.execute(ExecutionTicket) -> ToolResult

ExecutionTicket 是短期、单 ToolCall、不可扩大权限的凭证,包含 tool/plugin version、参数 hash、文件/网络/设备范围、超时、资源限制、approval 和 idempotency key。Executor 不接受模型直接构造的票据。

ToolResult 包含 status、typed content、is_error、result size、evidence refs 和 redaction metadata。大结果落 File/Object,模型只收到摘要和引用。

7. Worker 与 Lease

异步 Job 具有 queued/running/succeeded/failed/cancelled 状态。Worker 通过私有 Queue Port:

claim(queue, worker_id, lease_ms) -> JobLease | null
heartbeat(job_id, lease_token)
complete(job_id, lease_token, result_ref)
fail(job_id, lease_token, retry_class, error)

Lease token 只在 Header/消息元数据传递,不能成为业务 API 凭据。过期 Lease 可重新领取;副作用步骤仍依赖业务幂等键,不能仅靠 Lease 防重复。

8. Hunjing Plugin Protocol

通用插件协议采用 JSON-RPC 2.0:

  • 本地隔离插件:stdio;
  • 远程插件:HTTPS;
  • Tool-only 插件优先使用 MCP;
  • UI 扩展使用声明式 manifest + 隔离消息协议。

握手方法:

plugin.initialize
plugin.get_manifest
plugin.list_contributions
plugin.activate
plugin.deactivate
plugin.health

调用方法:

tool.invoke
hook.observe
hook.transform
context.provide
memory.extract_candidates
media.process
importer.inspect
importer.apply

每次请求带 plugin_run_id、PluginVersion、deadline、trace context 和短期 capability token。Host 验证响应 Schema、大小、时限和调用顺序。插件不能返回新权限,也不能调用未在 Manifest 声明的 Host service。

8.1 Host 回调

插件需要访问 Host 时,只能调用受限反向 RPC:

host.files.read
host.objects.create
host.http.fetch
host.secrets.use_reference
host.events.publish_observation

Host 根据 capability token 决定范围。secrets.use_reference 只让代理侧在允许 host/位置注入秘密,不向插件返回明文。

9. Sandbox RPC

Sandbox Worker 处于独立安全边界,私有协议至少支持:

sandbox.start
sandbox.execute
sandbox.read_output
sandbox.cancel
sandbox.stop

请求包含镜像摘要、只读/可写挂载、网络 allowlist、环境变量引用、CPU/内存/进程/时间限制和 ExecutionTicket。没有满足策略的后端时返回 sandbox_unavailable,禁止未隔离执行。

10. 支付内部端口

PaymentProvider.create_session(OrderSnapshot)
PaymentProvider.verify_webhook(raw_body, headers)
PaymentProvider.refund(PaymentReference, Amount)
PayoutProvider.create_payout(SettlementSnapshot)
ReconciliationProvider.list_transactions(period)

Provider Adapter 不写 Ledger。交易 Application Service 在验签和幂等后写 PaymentAttempt、LedgerEntry、Entitlement、Refund 或 PayoutAttempt。所有金额与货币由权威 Order/Settlement Snapshot 提供。

11. 内部认证

独立服务使用 workload identity/mTLS 或短期服务令牌;不复用用户 Cookie、Service Account API key 或 DiagnosticToken。每个服务身份只获所需方法与数据域。内部 Header 同样传播 traceparent 和 Hunjing-Request-ID,但不把 baggage 当授权。