mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-21 17:38:10 +00:00
feat: add package/build.sh cross-platform build script
- build.sh supports linux/amd64, linux/arm64, darwin/amd64, darwin/arm64, windows/amd64, and 'all' for matrix build - Components: homed (CGO, Linux/macOS-only), waiter (all platforms), gui - Platform matrix documented in script header - waiter: extract setRawMode into rawmode_linux.go + rawmode_other.go for cross-platform support - Add cmd/gui/node_modules/ and dist/ to .gitignore - Fix .gitignore waiter pattern to not ignore cmd/waiter/ directory
This commit is contained in:
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,5 +1,5 @@
|
|||||||
homed
|
homed
|
||||||
waiter
|
/waiter
|
||||||
*.exe
|
*.exe
|
||||||
*.log
|
*.log
|
||||||
*.test
|
*.test
|
||||||
@ -14,3 +14,8 @@ internal/meta/
|
|||||||
|
|
||||||
*.hmap
|
*.hmap
|
||||||
dev/
|
dev/
|
||||||
|
|
||||||
|
# GUI
|
||||||
|
cmd/gui/node_modules/
|
||||||
|
cmd/gui/dist/
|
||||||
|
|
||||||
|
|||||||
@ -11,7 +11,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -238,34 +237,5 @@ func printServerOutput(content string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func setRawMode(fd int) (func(), error) {
|
|
||||||
type termios struct {
|
|
||||||
Iflag uint32
|
|
||||||
Oflag uint32
|
|
||||||
Cflag uint32
|
|
||||||
Lflag uint32
|
|
||||||
Cc [20]byte
|
|
||||||
Ispeed uint32
|
|
||||||
Ospeed uint32
|
|
||||||
}
|
|
||||||
const (
|
|
||||||
TCGETS = 0x5401
|
|
||||||
TCSETS = 0x5402
|
|
||||||
ICANON = 0x2
|
|
||||||
ECHO = 0x8
|
|
||||||
)
|
|
||||||
var old termios
|
|
||||||
if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), TCGETS, uintptr(unsafe.Pointer(&old))); err != 0 {
|
|
||||||
return func() {}, fmt.Errorf("ioctl TCGETS: %v", err)
|
|
||||||
}
|
|
||||||
new := old
|
|
||||||
new.Lflag &^= ICANON | ECHO
|
|
||||||
if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), TCSETS, uintptr(unsafe.Pointer(&new))); err != 0 {
|
|
||||||
return func() {}, fmt.Errorf("ioctl TCSETS: %v", err)
|
|
||||||
}
|
|
||||||
return func() {
|
|
||||||
syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), TCSETS, uintptr(unsafe.Pointer(&old)))
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
18
cmd/waiter/rawmode_defs.go
Normal file
18
cmd/waiter/rawmode_defs.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
type termios struct {
|
||||||
|
Iflag uint32
|
||||||
|
Oflag uint32
|
||||||
|
Cflag uint32
|
||||||
|
Lflag uint32
|
||||||
|
Cc [20]byte
|
||||||
|
Ispeed uint32
|
||||||
|
Ospeed uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
TCGETS = 0x5401
|
||||||
|
TCSETS = 0x5402
|
||||||
|
ICANON = 0x2
|
||||||
|
ECHO = 0x8
|
||||||
|
)
|
||||||
23
cmd/waiter/rawmode_linux.go
Normal file
23
cmd/waiter/rawmode_linux.go
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
//go:build linux
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"syscall"
|
||||||
|
"unsafe"
|
||||||
|
)
|
||||||
|
|
||||||
|
func setRawMode(fd int) (func(), error) {
|
||||||
|
var old termios
|
||||||
|
if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), TCGETS, uintptr(unsafe.Pointer(&old))); err != 0 {
|
||||||
|
return func() {}, err
|
||||||
|
}
|
||||||
|
new := old
|
||||||
|
new.Lflag &^= ICANON | ECHO
|
||||||
|
if _, _, err := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), TCSETS, uintptr(unsafe.Pointer(&new))); err != 0 {
|
||||||
|
return func() {}, err
|
||||||
|
}
|
||||||
|
return func() {
|
||||||
|
syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), TCSETS, uintptr(unsafe.Pointer(&old)))
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
9
cmd/waiter/rawmode_other.go
Normal file
9
cmd/waiter/rawmode_other.go
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
//go:build !linux
|
||||||
|
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
func setRawMode(fd int) (func(), error) {
|
||||||
|
return func() {}, fmt.Errorf("raw terminal mode not supported on this platform")
|
||||||
|
}
|
||||||
119
package/build.sh
Executable file
119
package/build.sh
Executable file
@ -0,0 +1,119 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
|
BUILD_DIR="${PROJECT_ROOT}/build"
|
||||||
|
VERSION="${VERSION:-$(git -C "$PROJECT_ROOT" describe --tags --dirty 2>/dev/null || echo "0.7.1")}"
|
||||||
|
COMMIT="${COMMIT:-$(git -C "$PROJECT_ROOT" rev-parse --short HEAD 2>/dev/null || echo "unknown")}"
|
||||||
|
BUILD_TIME="${BUILD_TIME:-$(date -u '+%Y-%m-%dT%H:%M:%SZ')}"
|
||||||
|
GO="${GO:-$(command -v go 2>/dev/null || echo "/home/jianf/go1.26.5/go/bin/go")}"
|
||||||
|
LDFLAGS="-X gitcode.com/JianFeeeee/HomeAgent/internal/meta.Version=${VERSION} -X gitcode.com/JianFeeeee/HomeAgent/internal/meta.Commit=${COMMIT} -X gitcode.com/JianFeeeee/HomeAgent/internal/meta.BuildTime=${BUILD_TIME}"
|
||||||
|
|
||||||
|
TARGET="${1:-native}"
|
||||||
|
COMPONENT="${2:-all}"
|
||||||
|
|
||||||
|
# ---- platform matrix ----
|
||||||
|
# homed: linux/amd64 + linux/arm64 (CGO), macOS native-only (no osxcross)
|
||||||
|
# windows: blocked — gojieba CXX flags + dlfcn.h not available in MinGW
|
||||||
|
# waiter: all platforms (CGO-free, raw terminal mode is a no-op on non-Linux)
|
||||||
|
# gui: electron-builder handles cross-platform natively
|
||||||
|
|
||||||
|
case "$TARGET" in
|
||||||
|
native) GOOS="" GOARCH="" ;;
|
||||||
|
linux/amd64) GOOS=linux GOARCH=amd64 CC="${CC:-}" ;;
|
||||||
|
linux/arm64) GOOS=linux GOARCH=arm64 CC="${CC:-aarch64-linux-gnu-gcc}" ;;
|
||||||
|
darwin/amd64) GOOS=darwin GOARCH=amd64 CC="${CC:-}" ;;
|
||||||
|
darwin/arm64) GOOS=darwin GOARCH=arm64 CC="${CC:-}" ;;
|
||||||
|
windows/amd64) GOOS=windows GOARCH=amd64 CC="${CC:-x86_64-w64-mingw32-gcc}" ;;
|
||||||
|
all)
|
||||||
|
"$0" linux/amd64 "$COMPONENT"
|
||||||
|
"$0" linux/arm64 "$COMPONENT"
|
||||||
|
"$0" darwin/amd64 "$COMPONENT"
|
||||||
|
"$0" darwin/arm64 "$COMPONENT"
|
||||||
|
"$0" windows/amd64 "$COMPONENT"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unknown target: $TARGET"
|
||||||
|
echo "Usage: $0 [native|linux/amd64|linux/arm64|darwin/amd64|darwin/arm64|windows/amd64|all]"
|
||||||
|
echo " [all|homed|waiter|gui]"
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -n "${GOOS:-}" ]; then
|
||||||
|
SUFFIX="${GOOS}_${GOARCH}"
|
||||||
|
export GOOS GOARCH
|
||||||
|
fi
|
||||||
|
if [ -n "${CC:-}" ]; then
|
||||||
|
export CC
|
||||||
|
fi
|
||||||
|
export CGO_ENABLED="${CGO_ENABLED:-1}"
|
||||||
|
|
||||||
|
mkdir -p "$BUILD_DIR"
|
||||||
|
|
||||||
|
# ---- homed (CGO, sqlite3) ----
|
||||||
|
build_homed() {
|
||||||
|
local out="$BUILD_DIR/homed${SUFFIX:+_$SUFFIX}"
|
||||||
|
local plat="${GOOS:-linux}/${GOARCH:-amd64}"
|
||||||
|
|
||||||
|
if [ "$GOOS" = "darwin" ] && [ "${CC:-}" = "" ] && [ "$(uname)" != "Darwin" ]; then
|
||||||
|
echo "[SKIP] homed ${plat} — requires native macOS build (CGO + sqlite3, no osxcross)"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
if [ "$GOOS" = "windows" ]; then
|
||||||
|
echo "[SKIP] homed ${plat} — gojieba CXX flags + dlfcn.h unavailable in MinGW cross-compiler"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$GOOS" = "windows" ]; then out="${out}.exe"; fi
|
||||||
|
echo "[BUILD] homed ${plat} → $out"
|
||||||
|
CGO_ENABLED=1 "$GO" build -trimpath -installsuffix dynlink \
|
||||||
|
-ldflags "$LDFLAGS" -o "$out" ./cmd/homed/
|
||||||
|
echo " OK ($(file "$out" | sed 's/.*: //') | $(du -h "$out" | cut -f1))"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---- waiter (cross-platform, CGO-free) ----
|
||||||
|
build_waiter() {
|
||||||
|
local plat="${GOOS:-linux}/${GOARCH:-amd64}"
|
||||||
|
local out="$BUILD_DIR/waiter${SUFFIX:+_$SUFFIX}"
|
||||||
|
if [ "$GOOS" = "windows" ]; then out="${out}.exe"; fi
|
||||||
|
|
||||||
|
echo "[BUILD] waiter ${plat} → $out"
|
||||||
|
CGO_ENABLED=0 "$GO" build -trimpath -installsuffix dynlink \
|
||||||
|
-ldflags "$LDFLAGS" -o "$out" ./cmd/waiter/
|
||||||
|
echo " OK ($(du -h "$out" | cut -f1))"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---- gui (Electron) ----
|
||||||
|
build_gui() {
|
||||||
|
if [ -n "${GOOS:-}" ] && [ "$GOOS" != "$("$GO" env GOOS)" ]; then
|
||||||
|
echo "[SKIP] gui ${GOOS}/${GOARCH} — electron-builder handles cross-platform natively; run 'all' on CI host"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local gui_dir="$PROJECT_ROOT/cmd/gui"
|
||||||
|
echo "[BUILD] gui → $BUILD_DIR/"
|
||||||
|
|
||||||
|
if [ ! -d "$gui_dir/node_modules" ]; then
|
||||||
|
echo " npm install..."
|
||||||
|
(cd "$gui_dir" && npm install --production)
|
||||||
|
fi
|
||||||
|
|
||||||
|
(cd "$gui_dir" && npx electron-builder --config "$gui_dir/package.json" \
|
||||||
|
--linux --win --mac \
|
||||||
|
--x64 --arm64 \
|
||||||
|
-p never \
|
||||||
|
-o "$BUILD_DIR")
|
||||||
|
echo " OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
# ---- dispatch ----
|
||||||
|
case "$COMPONENT" in
|
||||||
|
all) build_homed; build_waiter; build_gui ;;
|
||||||
|
homed) build_homed ;;
|
||||||
|
waiter) build_waiter ;;
|
||||||
|
gui) build_gui ;;
|
||||||
|
*)
|
||||||
|
echo "Unknown component: $COMPONENT"
|
||||||
|
exit 1
|
||||||
|
esac
|
||||||
135
审查.md
Normal file
135
审查.md
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
# HomeAgent 代码审查报告(第三轮逐行全面复审)
|
||||||
|
|
||||||
|
审查日期: 2026-07-18
|
||||||
|
|
||||||
|
## 审查范围
|
||||||
|
|
||||||
|
- `cmd/homed/main.go` (453 行)
|
||||||
|
- `internal/agent/core/agent.go` (3156 行), `stages.go` (155 行), `context.go` (252 行), `plugin_health.go` (128 行)
|
||||||
|
- `internal/agent/core/stages_test.go` (199 行)
|
||||||
|
- `internal/agent/api/provider.go` (783 行)
|
||||||
|
- `internal/agent/io/channel.go` (636 行)
|
||||||
|
- `internal/sdk/` 全部 9 个文件 (510 行)
|
||||||
|
- `internal/plugin/` registry.go (426 行), plugin.go (295 行), dynamic.go (142 行)
|
||||||
|
- `internal/plugin/cabi/loader.go` (651 行)
|
||||||
|
- `internal/lua/vm.go` (403 行)
|
||||||
|
- `internal/events/bus.go` (83 行)
|
||||||
|
- `internal/config/registry.go` (700 行)
|
||||||
|
- `internal/memory/graph.go` (766 行), indexer.go (312 行), static_embedder.go (369 行), clean_text.go (57 行)
|
||||||
|
- `internal/memory/document/document.go` (471 行)
|
||||||
|
- SDK 仓库 `sdk/` 全部 6 个 API 文件 + `plugin_test.go` (~700 行)
|
||||||
|
- SDK 仓库 `tools/plugindev/templates.go`
|
||||||
|
- 架构文档 4 份 (`docs/zh/`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bug 级别
|
||||||
|
|
||||||
|
### A-1 `processTextInput` 缺失 `runStage(StageOnInput)` 调用
|
||||||
|
|
||||||
|
- **位置**: `internal/agent/core/agent.go:494-562`
|
||||||
|
- **严重程度**: 高
|
||||||
|
- **描述**: `processTextInput` 创建了 `stageCtx` (行515) 但从未调用 `a.runStage(sdk.StageOnInput, stageCtx)`。注册了 `on_input` 阶段的插件对文本输入完全不可见。
|
||||||
|
- **对照**: `processMediaInput` (行410) 正确调用了 `runStage(StageOnInput)`。
|
||||||
|
- **影响**: 所有文本输入的 `on_input` 阶段钩子静默失效。黑名单、限流、短路回复等功能对文本输入无效。
|
||||||
|
- **文档对照**: ARCHITECTURE.md 完整链路图中 `processTextInput()` 下方第一支路即为 `on_input stage`。
|
||||||
|
|
||||||
|
### A-2 `processTextInput` 缺失 `publishEvent(EventRawInput)`
|
||||||
|
|
||||||
|
- **位置**: `internal/agent/core/agent.go:494-562`
|
||||||
|
- **严重程度**: 中
|
||||||
|
- **描述**: `processTextInput` 没有发布 `EventRawInput` 事件。
|
||||||
|
- **对照**: `processMediaInput` (行405) 正确调用了 `a.publishEvent(events.EventRawInput, ...)`。
|
||||||
|
- **影响**: 订阅 `raw_input` 事件的插件/WebUI 收不到文本输入的原始事件。
|
||||||
|
|
||||||
|
### A-4 `processMediaInput` 缺失 `emitMemoryCandidate` 调用
|
||||||
|
|
||||||
|
- **位置**: `internal/agent/core/agent.go:371-436`
|
||||||
|
- **严重程度**: 中
|
||||||
|
- **描述**: 媒体输入处理完成后,没有调用 `emitMemoryCandidate`(文本处理在行560对应调用)。图片/音频对话不会被捕获到文本记忆层。
|
||||||
|
- **影响**: `text memory` 中缺失多模态交互记录。
|
||||||
|
|
||||||
|
### A-5 `StageOnInput` 在 `context.Append` 之后执行
|
||||||
|
|
||||||
|
- **位置**: `internal/agent/core/agent.go:389-410`
|
||||||
|
- **严重程度**: 低
|
||||||
|
- **描述**: `processMediaInput` 中行389 `a.context.Append()` 先执行,行410 `runStage(StageOnInput)` 后执行。插件在 `on_input` 阶段无法阻止上下文被追加。
|
||||||
|
- **文档对照**: ARCHITECTURE.md 描述 `on_input` 为"消息到 Agent,零处理",应在任何处理之前执行。
|
||||||
|
|
||||||
|
### A-6 `lua/vm.go` 中 `http_get`/`http_post` 返回 mock 数据
|
||||||
|
|
||||||
|
- **位置**: `internal/lua/vm.go:69-80`
|
||||||
|
- **严重程度**: 高
|
||||||
|
- **描述**: `http_get` 返回 `{"url":...,"body":"mock","status":200}`,`http_post` 返回 `{"url":...,"body":...,"status":200}`。没有实际 HTTP 网络调用。
|
||||||
|
- **文档对照**: ADAPTER.md 第93-95行明确说明 `http_get(url)` 和 `http_post(url, body)` 应发起真实 HTTP 请求。
|
||||||
|
- **影响**: Lua 适配器脚本中尝试使用 `http_get`/`http_post` 获取外部数据的功能均静默失败。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 功能限制
|
||||||
|
|
||||||
|
### A-7 C ABI 注册阶段时未传递 `StageScope`
|
||||||
|
|
||||||
|
- **位置**: `internal/plugin/cabi/loader.go:285-304`
|
||||||
|
- **描述**: C ABI 的 `CORE_REGISTER_STAGE` (methodID=2) 调用 `s.RegisterStage(sdk.Stage(st), handler)`,没有 scope 参数,总是使用 `StageScopeGlobal`。外部 `.so` 插件无法使用 `StageScopeOwnTools`。
|
||||||
|
- **对照**: 公共 SDK `sdk/plugin.go:237` 的 `RegisterStage` 支持 `...scope` 变参。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 顺序/次要问题
|
||||||
|
|
||||||
|
### A-8 `processConsolidation` 未注入 source context
|
||||||
|
|
||||||
|
- **位置**: `internal/agent/core/agent.go:2567`
|
||||||
|
- **描述**: `processConsolidation` 直接传 `&sdk.StageContext{RawMessage: input}`,没有调用 `injectSourceContext`。整理任务在 `process()` 内部的阶段钩子中无法获取来源/通道信息。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 已确认无问题的功能
|
||||||
|
|
||||||
|
1. **SDK 接口映射**: `internal/sdk/` 的 5 组 type alias (`MemoryAPI`, `KnowledgeAPI`, `SettingsAPI`, `LLMAPI`, `DocMemoryAPI`) 全部正确对齐 `pubsdk`,impl 包装器逐一桥接。
|
||||||
|
|
||||||
|
2. **C ABI 45 个 dispatch 方法**: 全部覆盖 SDK API,JSON 序列化/反序列化正确,无遗漏。方法列表:
|
||||||
|
- 1: CORE_REGISTER_TOOL
|
||||||
|
- 2: CORE_REGISTER_STAGE
|
||||||
|
- 3: CORE_REGISTER_OUTPUT_CH
|
||||||
|
- 4: CORE_REGISTER_PLUGIN_API
|
||||||
|
- 5-7: CORE_INJECT_TEXT / INJECT_INTERRUPT_TEXT / INJECT_TEXT_NO_MEMORY
|
||||||
|
- 8: CORE_SET_AUTO_RESTART
|
||||||
|
- 9-13: CORE_MEMORY_RECALL / COMMIT / INTROSPECT / MERGE / PURGE
|
||||||
|
- 14: CORE_DOC_QUERY
|
||||||
|
- 15: CORE_KNOWLEDGE_SEARCH
|
||||||
|
- 16-18: CORE_SETTINGS_GET / SET / REGISTER_DEF
|
||||||
|
- 19-20: CORE_LLM_LIST_SOURCES / SET_SOURCE
|
||||||
|
- 21-22: CORE_SOCIAL_GET_PERSON / GET_NETWORK
|
||||||
|
- 23-24: CORE_SUBSCRIBE / UNSUBSCRIBE
|
||||||
|
- 25: CORE_FREE_STRING
|
||||||
|
- 26-31: CORE_SETTINGS_GET_CORE / SET_CORE / LIST_CORE / GET_PLUGIN / SET_PLUGIN / LIST_PLUGIN
|
||||||
|
- 32-34: CORE_DOC_INSERT / REMOVE / STATS
|
||||||
|
- 35-36: CORE_KNOWLEDGE_ADD / LIST
|
||||||
|
- 37: CORE_LLM_CURRENT_SOURCE
|
||||||
|
- 38-40: CORE_SOCIAL_GET_TRAIT / GET_RELATIONS / LIST_PERSONS
|
||||||
|
- 41: CORE_TEXT_MEMORY_APPEND
|
||||||
|
- 42-45: CORE_SETTINGS_LIST / DEFS / DUMP / PLUGINS
|
||||||
|
|
||||||
|
3. **`pipeline.go` 非死代码**: `internal/memory/pipeline/pipeline.go` 在 `cmd/homed/main.go:122-130` 中被引用和启动。
|
||||||
|
|
||||||
|
4. **`emitMemoryCandidate` 被消费**: `cmd/homed/main.go:213-247` 的 goroutine 消费 `iom.OutputChan()` 中的 `memory_candidate` 事件,写入 `textMem` 和 `distiller`。
|
||||||
|
|
||||||
|
5. **向量表示跨会话兼容**: `StaticEmbedder` / `TFIDFVectorizer` 的 `Vectorize()` 是纯函数(基于词袋权重),不依赖会话状态。
|
||||||
|
|
||||||
|
6. **`processConsolidation` 不发射记忆候选**: 行2579注释说明这是有意为之,防止任务文本被蒸馏进图库造成污染。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 汇总
|
||||||
|
|
||||||
|
| 编号 | 级别 | 文件 | 行 | 描述 |
|
||||||
|
|------|------|------|----|------|
|
||||||
|
| A-1 | **Bug** | `agent.go` | 494-562 | `processTextInput` 未调用 `StageOnInput` |
|
||||||
|
| A-2 | **Bug** | `agent.go` | 494-562 | `processTextInput` 未发布 `EventRawInput` |
|
||||||
|
| A-4 | **Bug** | `agent.go` | 371-436 | `processMediaInput` 未调用 `emitMemoryCandidate` |
|
||||||
|
| A-5 | **Bug** | `agent.go` | 389-410 | `StageOnInput` 在 `context.Append` 之后执行 |
|
||||||
|
| A-6 | **Bug** | `lua/vm.go` | 69-80 | `http_get`/`http_post` 返回 mock |
|
||||||
|
| A-7 | 限制 | `cabi/loader.go` | 285-304 | C ABI 缺 `StageScopeOwnTools` 支持 |
|
||||||
|
| A-8 | 顺序 | `agent.go` | 2567 | `processConsolidation` 未注入 source context |
|
||||||
Reference in New Issue
Block a user