Commit Graph

26 Commits

Author SHA1 Message Date
cff8e10ad5 fix(lua): 补齐 6 个适配器的流式 tool_calls 支持
体检判据(TestAllBundledAdaptersStreamToolCallStatus)报出的三类问题,
本提交解决其中两类;第三类(gemini)未动,原因见下。

## ① OpenAI 兼容族:github / groq / mistral(3 个)

它们的 transform_stream_chunk 与修复前的 deepseek **逐字相同** ——
只透 content/done,tool_calls 处理只存在于 transform_response(非流式)。

后果与 deepseek 相同:流式模式下工具调用全部丢失,模型调不动任何工具,
且**没有任何报错**。生产当前未启用这三个源,但按预设配置的用户会踩到。

照 deepseek 的修法补上(含 reasoning_content 透传)。

## ② 嵌套形态 + 键名错:server / kimicode / anthropic / ollama(4 个)

这四个**有** tool_calls 处理,但发的是:

    { index = N, id = ..., ["function"] = { name = ..., arguments = ... } }

而 homed 的 `agentAPI.ToolCall` 是**扁平**结构,json tag 为:

    id / type / name / arguments / raw_arguments / stream_index

两处都是**静默**失效(Go 侧按 json tag 反序列化,取不到就是零值,无报错):
- **嵌套** `["function"]` ⇒ `name` / `raw_arguments` 取零值
  ⇒ flush 时判「无 name」丢弃,或参数为空
- **键名 `index`** ⇒ `StreamIndex` 取零值
  ⇒ 多个分片并到同一个桶,argsRaw 混拼 ⇒ 每个工具报「参数不是合法 JSON」
  而**一个都没真跑**

已逐项对齐为扁平 + `stream_index`。协议差异都保留:
- anthropic:`content_block_start` / `input_json_delta`,续传片 name 留空
  (内核按 stream_index 累积,补齐 name 后才 flush)
- ollama:tool_calls **整条一次发完**(不分片),故 stream_index 取数组下标

## ③ gemini 未动

它的流式函数处理 `candidates[].content.parts`,**全文件没有任何
tool_calls / functionCall 处理** —— 连非流式路径也没有。补它不是"对齐"
而是新实现,且 gemini 的 functionCall 形态(`functionCall: {name, args}`,
args 是对象而非 JSON 字符串)与 OpenAI 族不同,需要单独判据。

生产三个源(llmsproxy / visionllm / justworker)全部用 `openai.lua`,
不阻塞。留作独立项。

## 判据

- TestOpenAICompatibleFamilyHandlesStreamToolCalls  5 个 OpenAI 族适配器,
  逐个验证 tool_calls 未丢 + stream_index 正确
- TestAnthropicAdapterEmitsFlatToolCallsWithStreamIndex  用 **Anthropic 协议**
  的 fixture(不用 OpenAI 的,否则会因"不适用该 chunk"跳过 —— 看着绿,
  实则没测)
- TestOllamaAdapterEmitsFlatToolCallsWithStreamIndex  用 Ollama 协议形态
- TestDeepSeekAdapterHandlesStreamToolCalls  单列,因它有源预设指向

★ 三个判据按**协议**分文件而非逐适配器:这几个文件的流式函数逐字相同,
共用一个 fixture 会因协议不适用而静默跳过 —— 那等于没测。

## 体检分类

    修前: ✓ [openai]        ⚠ [kimicode server]  ✗ [anthropic deepseek gemini github groq mistral ollama]
    修后: ✓ [openai deepseek github groq mistral]  ⚠ []  ✗ [gemini]
2026-09-27 18:34:33 +08:00
0fdb13749a fix(lua): deepseek 适配器的流式路径处理 tool_calls(此前全部丢失)
## 缺陷

deepseek.lua 的 tool_calls 处理只存在于 `transform_response`(**非流式**路径),
而 `transform_stream_chunk` 只透 content/done:

    return json.encode({ content = delta.content or "", done = (fr ~= nil) })

于是 deepseek 源在**流式**模式下工具调用全部丢失 —— 模型调不动任何工具,
且**没有任何报错**,只是"工具好像不听话"。

## 为什么难发现

- 非流式路径是好的 ⇒ 端到端手工测试也过
- 内核的 tool call 循环默认走**流式**(provider.go 的 stream 分支)⇒ 实际不可用
- 功能判据(core 包的批内测试)直接构造 `agentAPI.StreamChunk{}`,
  **绕过适配器** ⇒ 测不到这一层

配置里 `deepseek` 源预设指向 `adapters/deepseek.lua`,所以任何按预设配置
的用户都会踩到(生产当前未启用该源,配置里 deepseek 相关键为 0)。

## 修法

照 openai.lua 的做法在流式路径补上:OpenAI 兼容格式
`{function:{name,arguments}, id, type, index}` → homed 扁平结构
`{id, type, name, raw_arguments, stream_index}`,含 reasoning_content 透传。

两个容易踩的点也写进注释:
- **不能按 name 过滤**:流式续传片 name 为空但携带 arguments,
  内核按 stream_index 分桶累积
- **必须透传 stream_index**:否则多个分片并到槽 0、argsRaw 混拼

## 判据

新增 TestDeepSeekAdapterHandlesStreamToolCalls:喂两个含 tool_call 的分片,
断言 tool_calls 未被丢弃且 stream_index 正确。修前两条分片全被丢弃。

## 体检分类随之变化

    修前: ✓ [openai]                                       ✗ [deepseek ...]
    修后: ✓ [deepseek openai]                              ✗ [anthropic gemini github groq mistral ollama]
2026-09-27 18:31:42 +08:00
61a2d56bbb test(lua): 记录仓库/生产适配器漂移的具体内容与时间线
生产 adapters/openai.lua(4853 字节)含 stream_index,仓库 ddef195 时的版本
(4709 字节)不含。生产文件时间 2026-08-26 15:46,比 ddef195 提交(16:10)
早 32 分钟 —— 该提交说明里写着「openai.lua 输出 stream_index 字段」,
但 --stat 显示它没改这个文件:修复先在生产生效,入库时漏了。

于是「生产能跑多工具、仓库跑不了」持续一个月而两端都没人发现:生产不报
问题(它有),仓库的判据也测不到(直接构造 Go 结构体,绕过适配器)。

判据本身不变(仍是诊断式 t.Log),只把这条漂移的具体内容写进注释 ——
它是理解本次全部误判的关键背景。
2026-09-27 18:29:32 +08:00
969206eb85 test(lua): 加适配器漂移报告 + 键名契约判据
上一提交(66200ff)纠正了一处误判:仓库的 openai.lua 缺 stream_index 透传,
而生产实例早就有 —— 仓库版本落后于生产。这个漂移当时没有任何判据能发现。

## 两条判据,定位不同

### TestBundledAdaptersMatchDeployedOnes —— 诊断式,刻意**不**作为失败判据

实测结果:生产部署的 7/10 个适配器比仓库旧(anthropic 2537 vs 5144 字节),
而 openai 那份反而领先。这**是正常的** —— 生产是长期运行的部署,适配器在它首次
创建时就解包落地,之后仓库一直在演进。

若把"必须一致"写成失败判据,它会在任何老部署上恒红,而恒红的判据会被无视 ——
那等于没有判据,甚至更糟(它会掩盖真正的漂移)。所以这里只把差异摆出来。

但它顺带把**部署陷阱**摆到了明面上:

    vm.go writeBundledAdapters: if 文件已存在 { continue }

升级二进制**不会更新已部署的适配器文件**。于是"仓库改了适配器但老实例上不生效"
与"仓库根本没改"在现象上完全一样 —— 这大概就是仓库长期缺 stream_index 却
没人发现的原因之一。

### TestAdapterEmitsOnlyKnownFields —— 这条才是能自动抓 bug 的

契约 = agentAPI.ToolCall / StreamChunk 的 json tag:
`id, type, name, arguments, raw_arguments, stream_index`(+ 上游原样透传的
`index` / `function`)。

★ 为什么必须有:Go 侧按 json tag 反序列化,**键名拼错会静默取零值**。
`streamindex`(少个下划线)与"没写这行"的表现完全一样 —— 无报错、字段为零、
分桶全部并到槽 0。这正是本次 stream_index 缺失的形态。

判据只看"适配器吐出来的键名对不对",与环境无关,所以能在 CI 里恒定生效。

## 顺带确认的一件事(事后查明:是我的操作失误)

压测实例解包出的 openai.lua 是 4709 字节(无 stream_index),而二进制 embed
里是 5672 字节(有)。`rm -rf` 后重新解包**仍是旧的**。

我逐行读过 `writeBundledAdapters`,只找到 embed 一条来源,一度判为"未解释的
矛盾"。**真因是操作失误**:`rm -rf` 之后启动的那一轮,用的还是修复前编译的
/tmp/homed-stress —— 删除与重编之间隔了几轮,中间又用旧二进制起了好几次
实例,每次解包出来的自然都是旧版。

用当前 main 重新构建 + 全新数据目录验证:全新解包 5672 字节、含
stream_index×3、md5 与源文件一致;删掉再解一次仍一致;启动日志有
`[lua] installed bundled adapter: openai.lua`。⇒ **writeBundledAdapters 无缺陷**。

★ 教训:验证"二进制内嵌内容是否更新"时,必须确认跑的就是**刚编译出来的那个
二进制**。否则会得出"代码有 bug"的错误结论 —— 我确实这么怀疑了好几天。

(下面那条"部署陷阱"观察本身仍然成立:升级二进制确实不会更新已部署的适配器
文件。但它与这次的现象无关。)
2026-09-27 18:29:15 +08:00
66200ff226 test(lua): 补适配器 stream_index 透传判据 + 全适配器体检
## 先纠正一件事:这个修复在生产上早就存在

最初我判断"`openai.lua` 缺 stream_index 透传、批内并发在生产走不通",并据此
写了实现。**核对生产实例后,这个判断是错的**:

    生产 /home/newqqagent/adapters/openai.lua   130 行  含 stream_index
    仓库 950b21b^                                128 行  无 stream_index

生产那份的注释是「透传上游分片 index:并行多工具调用时内核按它区分归属桶」——
简洁,与本提交新增的长注释不同。**也就是说仓库版本落后于生产,生产一直没这个
问题。** 我修的是"仓库与生产的差距",不是"生产正在发生的故障"。

## 真正缺的是判据

`internal/agent/core/stream_index_test.go` 的
TestAccumulateStreamParallelToolCallsByIndex 直接构造 Go 结构体
`agentAPI.StreamChunk{...}`,**不经过 Lua 适配器** —— 所以"适配器有没有把
index 透传出来"它永远测不到。生产有、仓库没有,判据也发现不了。

而提交 ddef195(2026-08-26,"流式并行 tool_call 按 JSON index 分桶")的说明里
写着「openai.lua 输出 stream_index 字段」,Go 侧也加了
`StreamIndex int json:"stream_index,omitempty"` 并注明"lua 适配器以
stream_index 键透传" —— 但那次提交**根本没改 openai.lua**(6 个文件里没有它)。
说明与实现不符,而没有任何判据能发现。

## 本提交做的事

① 让 openai.lua 与生产一致(补 stream_index 透传),并说明为何缺它会静默失效:
   多个分片全部并到槽 0 → argsRaw 混拼 → 每个工具报"参数不是合法 JSON",
   而**工具一次都没真跑过**。单工具时上游 index 恒为 0,缺省也是 0,
   所以问题只在"一轮多个 tool_call"时显形。

② 新增 internal/lua/adapter_streamindex_test.go,**真正加载并执行内嵌的
   openai.lua**(复用 VM 的真实路径),三条判据:
   - TestOpenAIAdapterPassesThroughStreamIndex  3 个 tool_call 的
     stream_index 必须是 0/1/2
   - TestOpenAIAdapterKeepsContinuationFragment 续传分片(只有 arguments、
     没有 name)的 stream_index 必须正确 —— 它是分桶的**唯一**依据
   - TestAllBundledAdaptersStreamToolCallStatus  全 10 个适配器体检

★ 第三条刻意**不**用 t.Skip 掩盖不支持的适配器 —— 早期版本一律 Skip,结果
"完全不支持流式工具调用"也会让整体显示为绿,而绿会被误读成"都支持"。
现在分类记录:openai ✓ / kimicode+server 透传嵌套形态需另修 /
其余 7 个未产出 tool_calls。

③ 体检顺带暴露的、与本提交无关但已记录的问题:
   - **仓库 vs 生产漂移无判据**:仓库适配器落后于生产时,只有靠人工对比才发现
   - **部署陷阱**:vm.go writeBundledAdapters 是
     `if 文件已存在 { continue }`,升级二进制**不会更新已有适配器文件**。
     这可能正是"仓库缺透传却没人发现"的原因之一
2026-09-27 17:48:16 +08:00
6878f0126d fix(lua): 同步注入在 Lua 中明确报不可用(避免自锁)+ 文档/mock 同步
sdk.inject_input_sync / *_opts / inject_input_media_sync* 在 Lua 里必然自锁:
Lua 代码只在 Start/工具/阶段/输出/事件回调中执行,这些路径都持有 plg.mu,
而同步注入要等本轮回复(回复路径上的回调又需要同一把锁)。原实现会挂死
直到超时;现改为立即返回明确错误,并在中英文 PLUGIN_DEV 里标注不可用 +
指向 Go 插件/异步注入。mock sdk.lua(SDK 仓为事实源)同步为同样的错误语义。
新增 TestLuaSyncInjectUnavailable 钉住不挂死。
2026-09-13 21:59:23 +08:00
162f33f81e feat(lua): Lua 插件桥全量对齐 SDK 1.3.0(媒体/注入标志位/优先级/事件/通道注销)
内核 Lua 桥(internal/plugin/lua_plugin.go)此前停在 v0.8.0 时代能力面,
1.1/1.2/1.3 新增能力只在 Go 侧存在,而 PLUGIN_DEV.md 宣称『能力完全对齐』。
本补丁把 Lua 侧补齐到与公开 SDK 1.3.0 对齐:

- 1.1 媒体:memory.commit 支持 sentence_text/media_digests;
  doc.insert_with_media + attachments;text_memory.append attachments;
  set_tool_blocks / inject_input_media(_sync) / inject_interrupt_media。
- 1.2 注入语义:inject_input_sync(_opts)、六个 *_opts 变体
  (no_memory/context_policy/cleaner_name/priority);
  ToolDef/ChannelDef 解析 context_policy。
- 1.3 优先级与动态通道:priority 常量透传;unregister_output_channel。
- StageContext 暴露 reasoning_content/context_msgs/token_usage/memory/extra/errors。
- 新增 sdk.events.subscribe 与 sdk.plugin_mgr.*。
- sdk.lua mock 同步(单一事实源在 SDK 仓 sdk/lua/sdk.lua,内核副本由
  third_party/homeagent-sdk/scripts/sync-lua-sdk.sh 同步)。

契约测试(lua_surface_test.go):
- 守住内核内嵌 mock 与 SDK 仓事实源一致;
- 守住 mock 承诺的每个函数都有运行时 RawSetString 绑定;
- 覆盖 opts/media/attachments 解析与 context_policy 透传。

文档:中英 PLUGIN_DEV.md 的 Lua API 表补齐并改为『对齐至 SDK 1.3.0』。
2026-09-13 19:56:32 +08:00
51eb98e0ae fix(mcp+adapter): 流式 tool_calls 解析修复 + MCP transport 超时保护
openai adapter transform_stream_chunk:
- OpenAI 流式分片是嵌套格式 function.{name,arguments},原样透传后
  json.Unmarshal 到扁平 ToolCall{name,arguments} 时 name 恒为空,
  accumulateStream flushToolCall 因 acc.name=="" 静默丢弃整个工具调用
  (流式路径自上线起 tool_calls 全部丢失的根因)
- 现在正确解包 function.name → name,function.arguments → raw_arguments
  (保留原始 JSON 字符串分片,由 accumulateStream 按 index 拼接)
- 不按 name 过滤分片:OpenAI 流式续传块 name 为空但携带 arguments 分片

mcp stdio/sse transport:
- stdio Send() 无超时:server 进程卡死时插件加载永久阻塞
- sse http.Client 无超时:远程 server 网络抖动/无响应时永久阻塞,
  导致 webui 等后续插件全部无法启动(生产实例偶发启动卡死根因)
- stdio 加 60s 请求超时;sse client 加 30s 整体 + 10s 拨号超时
2026-08-25 18:59:00 +08:00
7d6c0bb90b feat(provider): complete ChatStream with llmsproxy-grade streaming
Rewrite LuaAdaptedProvider.ChatStream to match the maturity of
llmsproxy's streaming implementation:

HTTP layer:
  - Dedicated stream HTTP client with no overall timeout (SSE must not
    be cut by the 180s Chat timeout); only a 30s dial timeout
  - Uses applyAdapterHeaders (supports build_headers dynamic signing
    hook), matching the non-streaming Chat path

Non-200 response handling:
  - New TransformError Lua hook (adapter.transform_error) for per-source
    protocol knowledge in error messages
  - Safe fallback truncation of raw error bodies (prevents HTML dump
    leakage to clients)

SSE parsing enhancements:
  - parseOpenAICompatibleStreamChunkFull: handles token usage in the
    final chunk (prompt_tokens/prompt, total_tokens/total dual keys),
    prompt cache detail fields, and empty-string finish_reason filtering
    (sensenova sends "" on every chunk)
  - Replaced old SSEScanner with bufio.Scanner (larger buffer, fewer
    allocations)

Stream integrity:
  - errorOnlyChunk detection: holds back the first chunk to reject
    degenerate streams (e.g. zen free pool's finish_reason:"network_error"
    with empty content) before any byte reaches the caller
  - [DONE] dedup: adapters that already emit a terminating done chunk
    with the real finish_reason don't get a second reason-less done
  - Clean EOF sends a final Done:true if no done was seen

Struct changes:
  - StreamChunk: added FinishReason and Usage fields for callers
  - LuaAdaptedProvider: added streamClient (lazy) + streamMu

Tested: curl against llmsproxy SSE confirms reasoning_content parsing
is correct (delta.reasoning_content), usage chunk handling works, and
[DONE] termination is properly emitted.
2026-08-25 08:30:53 +08:00
147d0baaf9 fix: LLM 工具循环 400、中断消息注入、ConPTY 终端支持
- agent: 工具轮请求尾部补 user 占位(zen 网关强制),tool 消息正确配对
- agent: 工具提醒/中断以 system 角色注入并带 [中断消息] 前缀,不进用户履历;系统提示词说明中断消息格式
- agentcli: 基于 ConPTY 的交互式终端(ptywin fork),terminal_create/read/write/resize/close/watch
- webui: server 输出通道适配器(保留 reasoning_content/disable_thinking)
- GUI: 沉浸式标题栏、icon 圆角重制、mascot 等打磨
2026-08-14 00:48:40 +08:00
27183312ad adapters: 支持多模态(对照 llmsproxy)
- ollama: content 数组拆分文本/images(base64),映射到 Ollama messages.images;
  流式透传 reasoning_content 与增量 tool_calls
- anthropic: OpenAI content(字符串/数组) 转 Anthropic blocks(文本 + image{source})
  + thinking/空 arguments tool_use/input_json_delta 流
- openai 透传 adapter 已保留多模态 content 数组(验收确认)
- 新增多模态单测:ollama images / anthropic image.source / openai passthrough

验证: go test ./... 27 包 0 失败;Windows 交叉编译通过;部署后服务健康
2026-08-10 12:17:15 +08:00
f0dacef281 lua: 吸收 llmsproxy 适配器高级特性(worker 池/静态预提取/动态签名钩子)
- 适配器 worker 池化:单 LState+全局锁(串行瓶颈)→ 每 adapter 一个 gopher-lua
  LState 池,按使用该 adapter 的源并发上限求和配置池大小,并发 transform 互不阻塞
- staticInfo 预提取:name/version/endpoint/headers 加载期编译缓存,Endpoint/Headers
  读缓存不占 worker;加载即预编译首个 worker
- build_headers 动态钩子 + hmac/sha256/base64/tohex 全局:签名型上游(kimicode 等)可接入
- provider applyAdapterHeaders 接入动态头(url/method/body/api_key/timestamp/source 元数据),
  未定义时回落静态 headers,缺省补 Authorization
- LLMSource.MaxConcurrent + core.llm.sources.<name>.max_concurrent,注册时汇总
  VM.ConfigureConcurrency
- 新增 Lua VM 测试(load/transform/build_headers/并发)

验证: go test ./... 27 包 0 失败;Windows 交叉编译通过;部署后 9 adapter 全部预加载
2026-08-10 11:29:57 +08:00
171e6f233b llm: 统一源接入层修复(对照 llmsproxy)
- provider: 新增 OpenAI-compatible 响应/流兜底解析,Lua adapter 异常时也能解析
  choices/message/tool_calls/usage(含 function.arguments 缺失、对象/字符串参数)
- 过滤无效 LLM 源(<nil>/空/缺 http(s) scheme),main 与 ReloadFromConfig 均跳过,
  避免 mocktest 等坏源污染 fallback 与 healthcheck
- adapter(openai/deepseek/groq/mistral/github/kimicode): 修 tool_calls 对
  nil function 的崩溃,兼容扁平/嵌套结构;openai 流透传 reasoning/tool_calls
- config: ToConfig 探活端点过滤无效 base_url,修复 supervisor 误报 LLM unreachable
2026-08-09 20:39:54 +08:00
0f68608403 feat(lua plugin): align Lua plugin bridge with C ABI surface, accept table args in sdk.memory.recall
- Lua 桥接层补齐 register_def/no_memory/cleaner/own_tools/output+input channels/register_api/set_auto_restart 等 v0.8.0 能力,与 C ABI 插件面一致
- sdk.memory.recall 兼容表参数(多 key 批量 recall),修复 Lua 插件传表报 bad argument
- 新增 TestLuaAlignedAPIs 覆盖对齐后的 API 面(含 recall 数组回归断言)
- sdk.lua 同步子表 mock(memory/doc/knowledge/text_memory/llm/social/settings)
- 更新 PLUGIN_DEV.md 中英文示例插件参考表
2026-07-31 11:42:23 +08:00
64615a9b19 fix(all lua adapters): type-safe field access in transform_response
All 5 adapters (deepseek, github, groq, mistral, openai) now:
- Guard against json.decode returning nil (null body)
- Use type() == "table" instead of truthy checks for table access
- Prevents 'attempt to index a non-table object(nil)' crashes
2026-07-30 18:32:17 +08:00
548b750b1a fix(openai adapter): handle null response body and use type-safe field access
- Fix transform_response crash when json.decode returns nil (null body)
- Replace truthy checks with type() == "table" for safer field access
- Prevents 'attempt to index a non-table object(nil)' errors
2026-07-30 17:09:51 +08:00
51f190e0b6 core: pass ReasoningContent to assistant messages in process.go
- process.go: attach resp.ReasoningContent when building assistant messages
- deepseek.lua v2.1.0: remove last_reasoning closure hack; rely on
  core-provided reasoning_content in messages
- openai.lua: strip reasoning_content from messages in transform_request
  (not supported by OpenAI API)
2026-07-28 17:07:17 +08:00
f91b20ee16 v0.7.3: 重构 Provider 层 + 计算层隔离 + Cleaner/NoMemory 架构
- 删除 OpenAIProvider/OllamaProvider 死代码,LuaAdaptedProvider 独存
- DisableThinking 从 ExtraBody 移到 CompletionRequest 顶层字段
- ContextWindow 从 Provider 签名移到 BaseConfig/ModelContextWindow() 统管
- 确认 CleanText 仅做基本空白 trim,QQ 模板剥离归插件 Cleaner
- Cleaner/NoMemory 仅作用于向量计算和 jieba 分词层,原文不变
- context.ContextEvent/Doc.Content 始终保存原文
- 删除 nlp/download.go 死代码
- media.go: context.Background() -> a.ctx 级联
- clawhubadapter: HTTP 超时
- cut.go: 跨平台 mod cache 路径 (GOMODCACHE->GOPATH->HomeDir)
- bridge_e2e_test: 移除未用 runtime import
- lua 适配器: disable_thinking 传参
2026-07-28 11:42:29 +08:00
c9e67d3d55 docs: 修正全部文档使其与源码实现一致
主仓库:
- 修复 4 份英文文档语言切换链接指向错误 (../zh/ → ../en/)
- ARCHITECTURE.md 标题 "三种加载方式" → "四种加载方式" (实际表格4行)
- PLUGIN_DEV.md 示例表: 添加 webfetch, 移除不存在的 luaplugintest/testlua
- PLUGIN_DEV.md 代码示例: InjectInput/InjectInterrupt → InjectText/InjectInterruptText
- PLUGIN_DEV.md 代码示例: Memory/Knowledge/LLM/Events 接口签名修正
- PLUGIN_DEV.md .hmap 内容统一, plugindev 编译去除 .exe 后缀

SDK 仓库:
- Plugin.Start(sdk *PluginSDK) 接口签名改为指针
- 方法表重写: 移除 CallLLM/QueryKnowledge/SetMemory 等不存在方法
- IOInjector 参数顺序修正为 (source, channel, text)
- 删除虚构 SDKConfig, 替换为实际 New() 构造函数签名
- .hmap 内容描述一致化

修正前一次会话中的 QQ/Bili 插件问题:
- qq napcat() 超时, fetchBotInfo 竞态, handleWebhook 同步阻塞
- bili CDN 直连失败, 添加 HTTP_PROXY 代理
2026-07-18 20:46:58 +08:00
c7e22fbe30 refactor: move webui.listen_addr from core.daemon to webui category 2026-07-14 11:22:46 +08:00
950090959f feat: restructure plugin system, add Lua plugin support, update docs 2026-07-13 21:48:13 +08:00
1f1233b823 refactor: P0-P3 fixes, C1 cleanup, architecture diagrams, go.work upgrade
- P0-1: ProviderError type + ReportStatus for precise 401/403 detection
- P0-2: Remove -config flag from deploy/homeagent.service
- P2-1: 5s debounce on context.go Save()
- P2-2→C1: Delete output_set_channel entirely
- P2-3: Extract mediaDataURL/mediaChat helpers
- P2-4: Dedup defaultSources var
- P3: Delete dead packages (embed/tokenizer/container/snapshot)
- P3: Delete dead functions (messagesToMap, RunStageAll)
- CL: Update .gitignore, docs, Makefile, gojieba removal
- Config: Delete config/config.yaml, update docs
- Arch: Remove EmitOutputTo from emitResponse
- CL-1: go.work 1.19→1.21
- Docs: Add Mermaid architecture diagrams to README
- Docs: Add kernel-rebuild requires plugin-rebuild note to PLUGIN_DEV.md
2026-07-12 11:42:56 +08:00
239a22899b fix: 模型思考模式配置 + Unicode 截断 + 审计修复 (13 files)
模型模式:
- 新增 LLMConfig/Source.ThinkingEnabled 配置,通过 ExtraBody
  控制 DeepSeek thinking mode,默认关闭
- SeedDefaults/ToConfig 读写 core.llm.thinking_enabled
- deepseek.lua 移除硬编码 temperature=0

Unicode 截断:
- truncateStr 改按 rune 计数,修复中文截断乱码

审计修复 (Critical):
- graph.go: defer rows.Close 在 for 循环 → 显式 Close (连接池泄漏)
- cli/openclaw/plugin.go: bare type assertion → comma-ok (panic)
- channel.go: payload["type"].(string) → comma-ok (panic)
- webui/handler.go: .(string) → fmt.Sprint (panic)
- agent.go: 添加 nil provider 错误返回

审计修复 (High):
- events/bus.go: copy handler slice under RLock (data race)
- webui/handler.go: SSE 通过 channel 串行化写入 (data race)
- timer/plugin.go: time.Sleep → select with stopCh (Stop 阻塞)
- provider.go: stream ch <- 添加 select ctx.Done (goroutine 泄漏)
- main.go: outputCh goroutine 添加 ctx.Done 退出路径
2026-07-03 20:46:04 +08:00
4442c9cea4 适配多个 LLM 源 (anthropic/gemini/mistral/groq/github) + SQLite 配置收敛 + 测试插件 2026-07-03 14:03:51 +08:00
ee811fb308 fix: Lua adapter fixes + add ReasoningContent to CompletionResponse
- Fix syntax error: tc.function -> tc["function"] (function is Lua keyword)
- Fix empty tool_calls: Lua returns nil instead of empty table ({} vs [] in JSON)
- Fix token_usage key name in unified response (usage -> token_usage)
- Add ReasoningContent to CompletionResponse struct
- Nits: jsonTable init, import ordering
2026-07-03 08:29:08 +08:00
bc26850b50 feat: complete HomeAgent architecture v2
- IO abstraction layer with OutputChannel routing and capability validation
- Three-layer memory (Context-Document-Graph) with TF-IDF relevance pruning
- OneBot V11 QQ protocol plugin with Reverse WebSocket client
- Plugin system with hot-reload (SKILL.md + native factories)
- Knowledge system with TF-IDF vector indexing
- Personality system (personal.md)
- Text memory (JSONL with rotation)
- Change tracker (overlayfs) with rollback
- Lua adapter VM
- Design document (DESIGN.md)

Module: gitcode.com/JianFeeeee/HomeAgent
2026-07-02 12:04:36 +08:00