Files
HomeAgent/internal/sdk/llm.go
JianFeeeee 3f834794c5 refactor: SDK module 路径统一改为 hologramagentsdk(59 文件 + go.mod)
## 为什么必须做

SDK 仓(独立仓库)已把 module 从 `github.com/JianFeeeee/homeagentsdk`
改名为 `hologramagentsdk`。主仓通过 `replace` 直接引用它的**物理目录**:

    replace github.com/JianFeeeee/homeagentsdk => ./third_party/homeagent-sdk

一旦 SDK 侧改成新 module 名,主仓立刻炸:

    go: ./third_party/homeagent-sdk@ used for two different module paths
        (github.com/JianFeeeee/hologramagentsdk and github.com/JianFeeeee/homeagentsdk)

Go **不允许**同一目录被两个 module 路径 replace。所以不能"新旧并存",
只能把主仓 59 个文件的 import 全部改到新名,并删掉旧 replace。

## 一个被证伪的前提

我最初按"third_party/homeagent-sdk 是独立仓库,不能在此仓修改其源码"
来处理,并因此判断两个仓的改动可以隔离。实际上主仓是靠 `replace` 指向
该目录的物理副本 —— **两个仓的改动不可能真正隔离**:SDK 侧改 module 名,
主仓必然跟着改 import。

这个前提应该在做任何改动之前用 `go list -m` 验证,而不是假设。

## 连带修掉两处

| 缺陷 | 性质 |
|---|---|
| `TestLuaSDKMockSingleSource` 失败 | SDK 的 `sdk/lua/sdk.lua` 变了,主仓内嵌副本未同步(跑 `scripts/sync-lua-sdk.sh` 修复) |
| `sdkModuleNames` 分散两处 | 已在 SDK 仓合并为单一数据源(见 SDK 仓 725732b) |

第一条是**副本一致性判据抓到的**,不是我自己发现的 —— 这类判据的价值在此:
两个仓必然有副本,靠人记住"改了 A 要同步 B"是做不到的。

## 验证

- `go build ./...` / `go vet ./...` 干净
- `go test ./... -count=1`:**58 包 0 失败**
- `internal/plugin`(Lua SDK 副本一致性)+ `internal/sdk` 全绿
- 主仓 `third_party/homeagent-sdk/` 与 SDK 仓 `main` 无差异
2026-10-23 15:51:02 +08:00

73 lines
2.8 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package sdk
import (
"context"
pubsdk "github.com/JianFeeeee/hologramagentsdk/sdk"
)
// LLMAPI 是内置插件使用的全量 LLM Provider 接口。
// 内置 SDK 为全量接口,外部 SDK 仅暴露其中的安全子集(pubsdk.LLMAPI)。
type LLMAPI interface {
pubsdk.LLMAPI
// ReloadFromConfig 从内核配置重建所有 LLM Provider。
ReloadFromConfig() error
// Chat 向默认 Provider 发起一次补全调用(非记忆管线)。
Chat(ctx context.Context, req *LLMCompletionRequest) (*LLMCompletionResponse, error)
}
// LLMMessage 是面向 LLM Provider 的中立对话消息。
type LLMMessage struct {
Role string `json:"role"`
Content string `json:"content,omitempty"`
ReasoningContent string `json:"reasoning_content,omitempty"`
ToolCallID string `json:"tool_call_id,omitempty"`
ToolCalls []LLMToolCall `json:"tool_calls,omitempty"`
// Blocks 多模态内容块(与 Content 二选一;非空时优先)。
// 支持 text 与 image_url 两类,用于视觉模型看图(如 screensee 截屏描述)。
Blocks []LLMContentBlock `json:"blocks,omitempty"`
}
// LLMContentBlock 是多模态消息中的单个内容块。
type LLMContentBlock struct {
Type string `json:"type"` // "text" | "image_url"
Text string `json:"text,omitempty"`
ImageURL string `json:"image_url,omitempty"` // data URL 或 http(s) URL
}
// LLMToolCall 是中立的工具调用请求。
type LLMToolCall struct {
ID string `json:"id"`
Name string `json:"name"`
Arguments map[string]interface{} `json:"arguments"`
}
// LLMTokenUsage 报告一次补全的 token 消耗。
type LLMTokenUsage struct {
Prompt int `json:"prompt"`
Completion int `json:"completion"`
Total int `json:"total"`
}
// LLMCompletionRequest 是中立的补全请求。
// Tools/ToolChoice 使用 OpenAI 风格载荷,便于 Provider 直接转发。
type LLMCompletionRequest struct {
Model string `json:"model,omitempty"`
Messages []LLMMessage `json:"messages"`
Temperature float64 `json:"temperature,omitempty"`
MaxTokens int `json:"max_tokens,omitempty"`
Stream bool `json:"stream,omitempty"`
Tools []interface{} `json:"tools,omitempty"`
ToolChoice interface{} `json:"tool_choice,omitempty"`
DisableThinking bool `json:"disable_thinking,omitempty"`
}
// LLMCompletionResponse 是中立的补全响应。
type LLMCompletionResponse struct {
Content string `json:"content"`
ReasoningContent string `json:"reasoning_content,omitempty"`
FinishReason string `json:"finish_reason,omitempty"`
TokenUsage LLMTokenUsage `json:"token_usage,omitempty"`
ToolCalls []LLMToolCall `json:"tool_calls,omitempty"`
}