JianFeeeee 11c1bbcebb plugin: 子进程通道接通 registry(proc 通道端到端可运行)
Part 3 收尾。tryLoadProc 从桩位变成真实加载路径,plugin.bin 插件现在
经 registry 完整跑起来:spawn → 握手(共享段 fd 3)→ init/start →
反向注册 → 工具调用 → stage 共享内存读改写。

registry 侧:
- Registry 持有 procHost(惰性创建,**全部 .bin 插件共用一块段**)。
  每插件一段会让「内核 ctx → 段 → 插件改 → 回读 ctx」在多插件下退化成
  副本模型,lost update 原样复现(§8.4 实测 35.8~36.8%)。
- tryDynamic 分派到 Registry.loadProc;tryLoadProc 退为纯静态校验
  (构造需要 Host,只有 Registry 有)。
- StopAll 在锁外释放共享段:插件还持有映射时拆段,它们下一次访问就是
  SIGBUS;且持锁调用会与 onProcCrash 回调产生锁序风险。
- onProcCrash 把子进程退出转成 EventSystem 事件,不在回调里直接重载
  (重载需 registry 锁,而回调可能来自持锁路径的 goroutine)。

proc_core.go —— 权限梯度的类型系统落点(§3.8):
- procCore 用**命名字段**持有 *isdk.PluginSDK,不是嵌入。嵌入会提升全部
  方法,外部插件就能经类型断言拿到 Supervisor/Tracker/Adapter/Indexer/
  Status/Selftest。命名字段下只有显式写出的方法存在——权限梯度从
  「C ABI 表达能力的意外产物」变成显式声明并强制的策略。
- 能力访问器把内部超集接口收窄到公开面(isdk.KnowledgeAPI 内嵌
  pubsdk.KnowledgeAPI 再加 Stats/Remove,isdk.MemoryAPI 加 GraphData,
  isdk.LLMAPI 加 Chat/ReloadFromConfig);nil 保护避免类型化 nil 让
  corehandler 的判空失效。
- procPluginAdapter 转接 Start(*isdk.PluginSDK) → Start(proc.CoreSDK),
  Close 对 closeDynamic 可见故重载能真 kill 子进程(对比 dlclose 对
  Go c-shared 是 no-op,§1.1)。

共享段分配按平台拆分(原先 host.go 直接调 unix.MemfdCreate,darwin/windows
交叉编译失败):Linux memfd;macOS 立即 unlink 的临时文件(无 memfd_create,
但语义一致:无残留、fd 可经 ExtraFiles 传递、子进程 mmap 同一 inode);
其余平台明确报错而非静默降级成「无共享段」——那会让 stage 静默失去数据面。

测试 +13 项:
- e2e_template_test.go 用**真实 plugindev 模板**(而非 testdata 手写假插件)
  编译插件跑全链路,验证「模板 ↔ 内核」协议/布局真的对齐,不只是内核自己
  跟自己对齐。含 lifecycle.autoRestart 上报、工具调用、stage 读改写、
  FinalText 回传(C ABI 下 after_toolcall 看不到此字段,§8.3 10→16)、
  只读插件不覆盖改写插件。
- proc_load_test.go 验证 Host 唯一性/惰性、chmod +x 错误提示、
  Close 可见性,以及 procCore 不暴露内核内部机制的断言。

验证:go build ./... 通过;go test -race ./internal/plugin/... 全绿;
全仓 go test 无新增失败;git diff third_party/homeagent-sdk/sdk/ 为空。
既有告警 cabi/loader.go:156 unsafe.Pointer 非本次引入。

Ref: docs/zh/架构迁移评估.md §3.3/§3.4/§3.8、docs/zh/plugin-migration-plan.md Part 3
2026-09-02 13:03:57 +08:00
2026-07-29 15:45:24 +08:00

⚠️ AI-Assisted Programming Notice: Parts of this project's code, documentation, and commit history were generated or modified with AI assistance. Key changes have been human-reviewed, but please evaluate and verify before use.

HomeAgent

中文: README.md

An Agent framework designed around separation of core domain and application domain. The kernel enforces a zero-IO policy — all external interaction (WebUI, QQ, CLI, file operations, web search, memos, etc.) is handled by the plugin layer; the kernel performs no direct IO operations.

Combined with a three-layer memory architecture (Context → Document → Graph), it maintains contextual coherence across long-running single-conversation sessions through tiered storage and automated archival.

homed (kernel, zero IO)  PluginSDK  plugins (all IO capabilities)

Design Principles

Separation of Core Domain and Application Domain — The kernel's responsibilities are limited to LLM orchestration, memory management, and knowledge retrieval; all IO capabilities (message send/receive, file read/write, network requests, hardware interaction, etc.) are implemented by plugins. This separation defines domain boundaries at the Agent framework level, with distinct responsibility scopes for the kernel and plugins.

Three-Layer Memory Architecture — Manages information retention in long-running agents through a tiered storage strategy:

  • Context Layer: Pretrained word embedding / TF-IDF fallback relevance-scored event window, protects last 10 entries, maintains topK context entries
  • Document Layer: Temporary memory with automatic cold data sinking, also supports user-initiated submissions
  • Graph Layer: SQLite graph database, persists entity relationships and semantic memory, supports distillation pipelines to extract triples from conversations

Architecture Diagrams

1. Message Processing Sequence

sequenceDiagram
    participant U as User/Plugin
    participant IO as IOManager
    participant EV as eventLoop
    participant CTX as RelevanceContext
    participant LLM as LLM+Tool Loop
    participant ST as StageHost
    participant MEM as Three-Layer Memory

    U->>IO: InjectInput(type, payload)
    IO->>EV: inputCh
    rect lavender
        Note over EV: processTextInput
        EV->>ST: StageOnInput  Plugin can rewrite/short-circuit
        EV->>CTX: Prune(input,topK)  StaticEmbedder/TF-IDF cosine pruning
        CTX->>MEM: Low-score events archived to Document (original timestamp)
        EV->>CTX: Append(input)  CleanTemplateText→three-branch vector→5s write
    end
    rect lightgreen
        Note over EV,LLM: process()
        EV->>MEM: buildMemoryContext  Indexer recalls from Graph (vector+jieba→BFS depth=2)
        EV->>MEM: buildSystemPrompt  DocQuery summary+Graph memory index+Persona+Skills
        EV->>ST: StagePreAction  Plugin can pre-intercept
        loop Tool loop
            LLM->>LLM: drainInterrupts
            LLM->>LLM: LLM Chat
            LLM->>ST: StagePostAction  Plugin can modify/short-circuit
            alt No tool call
                LLM-->>EV: Returns response
            else
                loop Each tool
                    ST->>ST: StageBeforeToolcall  Plugin can reject
                    LLM->>LLM: executeToolCall
                    ST->>ST: StageAfterToolcall
                end
            end
        end
    end
    rect lightpink
        Note over EV: emitResponse
        CTX->>CTX: Append(response)
        ST->>ST: StageBeforeOutput  Plugin can rewrite
        EV-->>U: ResponseCh CLI sync
        EV-->>EV: Event bus WebUI SSE
        ST->>ST: StageAfterOutput  Read-only
        EV->>MEM: emitMemoryCandidate
    end

2. Stage Pipeline

flowchart LR
    S1[① on_input] --> S2[② pre_action]
    S2 --> S3[③ post_action]
    S3 --> Q{Has tool?}
    Q -->|Yes| S4[④ before_toolcall]
    S4 --> T[executeToolCall]
    T --> S5[⑤ after_toolcall]
    S5 --> S3
    Q -->|No| S6[⑥ before_output]
    S6 --> S7[⑦ after_output]
    style S1 fill:#e1f5fe
    style S3 fill:#fff3e0
    style S6 fill:#e8f5e9

3. Three-Layer Memory

flowchart TB
    subgraph C[① Context Working Window]
        RC[RelevanceContext]
        A[Append] -->|CleanTemplateText→three-branch vector| RC
        P[Prune StaticEmbedder/TF-IDF Cosine] -->|Low score original timestamp| D
        P -->|Keep| TL[timeline→chronological→system prompt]
    end
    subgraph D[② Document File Memory]
        DS[DocStore JSON+TF-IDF]
        Q1[Query summary auto-inject] -->|[Related Memory Docs]| SP
        Q2[doc_query LLM active recall] -->|Consume+delete source| DS
        Q2 -->|Original timestamp write to context| RC
        CD[FindColdDocs 72h] -->|docToTriples| G
    end
    subgraph G[③ Graph Database]
        DB[(SQLite)]
        IDX[Indexer vector+jieba→BFS depth=2] -->|[Memory Index]| SP
        MEM[memory_recall/commit/merge/purge/edit]
        SOC[person_query/set_trait]
    end
    subgraph H[④ Heartbeat Distillation]
        REORG -->|Step3 Cold docs| CD
        REORG -->|Step4 Bigram Jaccard| CONS[consolidation]
        PIPE[Pipeline regex] -->|Name/Address/Likes/Age/Job| DB
    end
    SP[System Prompt] -->|Sequential assembly| LLM
    LLM[LLM] -->|doc_query| Q2
    LLM -->|memory_recall| MEM

See assets/docs/en/ARCHITECTURE.md for details.

Web Mascot

HomeAgent Web Mascot Xiaozhai

Xiaozhai — HomeAgent Web Mascot

Quick Start

make build build-cli
./build/homed -data /tmp/ha
# Interactive mode
./build/waiter

# Or single message
echo "Hello, remember that I like coffee" | ./build/waiter

API keys are configured via WebUI http://localhost:8080 settings page, persisted in SQLite.

Code Structure

cmd/homed/          Daemon entry, assembles all subsystems
cmd/waiter/         CLI client (Unix socket)
internal/
├── agent/core/     Agent core: event loop, LLM tool loop, 7-stage pipeline
├── agent/api/      LLM Provider + 8 Lua adapters
├── memory/         Three-layer memory: Graph(SQLite) / Document(JSON+TF-IDF) / Text(JSONL) + StaticEmbedder(pretrained word embedding/TF-IDF fallback) + CleanTemplateText(de-template)
├── knowledge/      Knowledge base (filesystem + TF-IDF)
├── plugin/         Plugin registry + .so/.dll dynamic loader
├── plugins/        11 built-in plugins (webui/cli/timer/cmd/mcp/clawhubadapter/agentcli/healthcheck/pluginmgr/files/cfgmgr)
├── sdk/            PluginSDK (Tool/Stage/Event three channels)
├── config/         SQLite config center
├── events/         Event bus
└── internal/lua/adapters/   8 LLM protocol adapter scripts
External plugin development: see [homeagent-sdk](https://gitcode.com/JianFeeeee/homeagent-sdk) repo, use `plugindev` toolchain, refer to Go and Lua examples in `example/`

Project Status

v0.9.0 — C ABI v2: external plugin Stage callbacks can now write back (invoke_stage gained a result out-param; plugins may mutate RawMessage/LLMText/ToolResults etc. in OnInput/AfterToolcall/PostAction and have them synced to the core). ABI version now tracks core minor releases (v0.9.x → ABIVersion=2, version_min=1 keeps old plugins loadable). Also fixes the tool-loop zen-compat placeholder that wrongly fired on first-turn system context tail. The SDK ships an enhanced sanitizer example (bad-UTF-8 / U+FFFD / ANSI-escape scrub across the whole pipeline).

v0.8.0 — Core is functional, plugin system enhanced. 20+ built-in plugins. External plugin development via homeagent-sdk repo. Added input channel NoMemory/Cleaner, ChannelDef, plugin disable/enable system (CLI + WebUI), plugindev toolchain C ABI ChannelDef support.

Documentation

Build

make build build-cli    # Build daemon + CLI
make test               # go test ./...
make install            # Install to system

Dependencies: Go 1.25+, CGo (go-sqlite3), Linux/Windows.

Description
No description provided
Readme AGPL-3.0 83 MiB
Languages
Go 74.6%
JavaScript 12.8%
HTML 3.9%
CSS 3.1%
Python 2.4%
Other 3.1%