Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,14 @@ Halo 官方 AI 能力平台,统一接入主流大模型,为插件生态提
- **统一参数映射**:按 Provider 或模型配置采样、重试、推理、Embedding、Rerank 和图像参数到供应方字段的映射
- **文本与多模态生成**:支持非流式与流式文本、图片 / 文件输入、推理内容、来源、结构化输出和多步骤结果
- **工具调用**:支持服务端与外部工具、流式工具输入、审批、输入修复、并行工具调用和步骤控制
- **共享工具**:插件工具发现、网页读取、网络与全站搜索,以及 FormKit 工具选择器
- **Embedding、Rerank 与 RAG**:提供文本向量、批处理、相似度、重排和可组合的检索 / 重排 / 上下文注入 middleware
- **图像生成**:支持文生图、图生图、蒙版编辑、多图聚合和图像 middleware
- **UI Message Stream**:提供可持久化的消息协议、SSE 响应、消息校验 / 转换、取消和前端工具续跑
- **默认模型设置**:分别配置语言、Embedding、Rerank 和图像生成默认模型
- **模型测试工作台**:在控制台验证对话、Embedding、Rerank、图像生成和单轮 RAG,并查看流事件、用量、warning 与诊断信息
- **用量统计**:查看调用次数、Token 用量、趋势和调用明细,按插件、供应商和模型等维度筛选,并支持自动刷新
- **消费方 SDK**:提供 Provider-neutral Java API、浏览器 / Vue npm 包和 FormKit `aiModelSelector`
- **消费方 SDK**:提供 Provider-neutral Java API、浏览器 / Vue npm 包,以及 FormKit `aiModelSelector` 和 `aiToolSelector`

## 已接入插件

Expand Down Expand Up @@ -117,6 +118,7 @@ cd ui && pnpm install && pnpm dev
- [SDK Core](./dev/zh-CN/sdk-core/README.md):Java 后端的文本、工具、结构化输出、Embedding、Rerank、RAG、图像生成、middleware 与错误处理。
- [SDK UI](./dev/zh-CN/sdk-ui/README.md):Vue Chat、消息持久化、工具交互、Completion、Object stream、Transport 与 UI Message 协议。
- [插件集成示例](./dev/zh-CN/plugin-integration-examples.md):Halo 插件依赖、后端模型调用、UI Message Endpoint、Vue Chat 与模型设置。
- [共享工具](./dev/zh-CN/tool-catalog.md):内置工具配置、工具选择器、后端调用和插件工具注册。

[SDK Core 单页参考](./dev/zh-CN/dev.md) 与
[UI Message Stream 单页参考](./dev/zh-CN/ui-message-stream.md) 适合全文搜索。
Expand All @@ -139,4 +141,4 @@ npx skills add halo-dev/plugin-ai-foundation --skill use-ai-foundation-sdk --glo

## 许可证

[GPL-3.0](./LICENSE) © Halo
[GPL-3.0](./LICENSE) © Halo
277 changes: 277 additions & 0 deletions api-docs/openapi/v3_0/aiFoundationApis.json
Original file line number Diff line number Diff line change
Expand Up @@ -1359,6 +1359,148 @@
"tags" : [ "console.api.aifoundation.halo.run/v1alpha1/Provider" ]
}
},
"/apis/console.api.aifoundation.halo.run/v1alpha1/tools" : {
"get" : {
"description" : "List tools contributed by enabled plugins without executors.",
"operationId" : "ListTools",
"responses" : {
"default" : {
"content" : {
"*/*" : {
"schema" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/ToolDescriptor"
}
}
}
},
"description" : "default response"
}
},
"tags" : [ "console.api.aifoundation.halo.run/v1alpha1/Tool" ]
}
},
"/apis/console.api.aifoundation.halo.run/v1alpha1/tools/{pluginName}/{localName}/configuration" : {
"get" : {
"description" : "Get provider-owned configuration values without credentials.",
"operationId" : "GetToolConfiguration",
"parameters" : [ {
"in" : "path",
"name" : "pluginName",
"required" : true,
"schema" : {
"type" : "string"
}
}, {
"in" : "path",
"name" : "localName",
"required" : true,
"schema" : {
"type" : "string"
}
} ],
"responses" : {
"default" : {
"content" : {
"*/*" : {
"schema" : {
"$ref" : "#/components/schemas/ToolConfig"
}
}
},
"description" : "default response"
}
},
"tags" : [ "console.api.aifoundation.halo.run/v1alpha1/Tool" ]
},
"put" : {
"description" : "Validate and save provider-owned tool configuration.",
"operationId" : "UpdateToolConfiguration",
"parameters" : [ {
"in" : "path",
"name" : "pluginName",
"required" : true,
"schema" : {
"type" : "string"
}
}, {
"in" : "path",
"name" : "localName",
"required" : true,
"schema" : {
"type" : "string"
}
} ],
"requestBody" : {
"content" : {
"*/*" : {
"schema" : {
"$ref" : "#/components/schemas/ToolConfig"
}
}
},
"required" : true
},
"responses" : {
"default" : {
"content" : {
"*/*" : {
"schema" : {
"$ref" : "#/components/schemas/ToolConfig"
}
}
},
"description" : "default response"
}
},
"tags" : [ "console.api.aifoundation.halo.run/v1alpha1/Tool" ]
}
},
"/apis/console.api.aifoundation.halo.run/v1alpha1/tools/{pluginName}/{localName}/state" : {
"put" : {
"description" : "Enable or disable a shared tool for all consumers.",
"operationId" : "UpdateToolState",
"parameters" : [ {
"in" : "path",
"name" : "pluginName",
"required" : true,
"schema" : {
"type" : "string"
}
}, {
"in" : "path",
"name" : "localName",
"required" : true,
"schema" : {
"type" : "string"
}
} ],
"requestBody" : {
"content" : {
"*/*" : {
"schema" : {
"$ref" : "#/components/schemas/ToolEnabledRequest"
}
}
},
"required" : true
},
"responses" : {
"default" : {
"content" : {
"*/*" : {
"schema" : {
"$ref" : "#/components/schemas/ToolDescriptor"
}
}
},
"description" : "default response"
}
},
"tags" : [ "console.api.aifoundation.halo.run/v1alpha1/Tool" ]
}
},
"/apis/console.api.aifoundation.halo.run/v1alpha1/usage-statistics/breakdown" : {
"get" : {
"description" : "Get usage totals grouped by a dimension.",
Expand Down Expand Up @@ -4535,6 +4677,14 @@
"toolChoice" : {
"$ref" : "#/components/schemas/ToolChoice"
},
"toolIds" : {
"type" : "array",
"description" : "Stable IDs of explicitly selected shared tools.",
"items" : {
"type" : "string",
"description" : "Stable IDs of explicitly selected shared tools."
}
},
"topK" : {
"type" : "integer",
"format" : "int32"
Expand Down Expand Up @@ -4564,6 +4714,133 @@
}
}
},
"ToolConfig" : {
"type" : "object",
"properties" : {
"values" : {
"type" : "object",
"additionalProperties" : {
"type" : "object"
}
}
}
},
"ToolDescriptor" : {
"type" : "object",
"properties" : {
"category" : {
"type" : "string"
},
"configurationSchema" : {
"type" : "array",
"items" : {
"type" : "object",
"additionalProperties" : {
"type" : "object"
}
}
},
"configured" : {
"type" : "boolean"
},
"description" : {
"type" : "string"
},
"displayDescription" : {
"type" : "string"
},
"displayName" : {
"type" : "string"
},
"enabled" : {
"type" : "boolean"
},
"group" : {
"$ref" : "#/components/schemas/ToolGroupDescriptor"
},
"id" : {
"type" : "string"
},
"inputSchema" : {
"type" : "object",
"additionalProperties" : {
"type" : "object"
}
},
"localName" : {
"type" : "string"
},
"name" : {
"type" : "string"
},
"outputSchema" : {
"type" : "object",
"additionalProperties" : {
"type" : "object"
}
},
"pluginName" : {
"type" : "string"
},
"status" : {
"type" : "string"
},
"tags" : {
"type" : "array",
"items" : {
"type" : "string"
}
}
}
},
"ToolEnabledRequest" : {
"type" : "object",
"properties" : {
"enabled" : {
"type" : "boolean"
}
}
},
"ToolGroupDescriptor" : {
"type" : "object",
"properties" : {
"description" : {
"type" : "string"
},
"displayName" : {
"type" : "string"
},
"id" : {
"type" : "string"
},
"presets" : {
"type" : "array",
"items" : {
"$ref" : "#/components/schemas/ToolPresetDescriptor"
}
}
}
},
"ToolPresetDescriptor" : {
"type" : "object",
"properties" : {
"description" : {
"type" : "string"
},
"displayName" : {
"type" : "string"
},
"id" : {
"type" : "string"
},
"toolIds" : {
"type" : "array",
"items" : {
"type" : "string"
}
}
}
},
"UIMessageChunk" : {
"type" : "object",
"properties" : {
Expand Down
63 changes: 63 additions & 0 deletions api/src/main/java/run/halo/aifoundation/AiToolService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package run.halo.aifoundation;

import java.util.List;
import org.pf4j.ExtensionPoint;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;
import run.halo.aifoundation.tool.ToolDefinition;
import run.halo.aifoundation.tool.ToolDescriptor;

/**
* Cross-plugin entry point for tools contributed by enabled Halo plugins.
*
* <p>Obtain this service through {@code ExtensionGetter.getEnabledExtension(AiToolService.class)}. Tool selections use
* the catalog {@link ToolDescriptor#id()}, not the model-facing name. No tools are selected implicitly. The caller
* remains responsible for its own access policy and must pass trusted caller identity through the reactive subscriber
* context; a provider must check any domain-specific permissions before performing an operation.
*
* <pre>{@code
* extensionGetter.getEnabledExtension(AiToolService.class)
* .flatMap(service -> service.resolveTools(List.of("article-tools/list_posts")))
* .flatMap(tools -> model.generateText(GenerateTextRequest.builder()
* .tools(tools)
* .messages(messages)
* .build()));
* }</pre>
*/
public interface AiToolService extends ExtensionPoint {

/**
* Lists tools contributed by enabled, valid providers, including globally disabled or unconfigured tools so
* administrators can manage their state and configuration.
*
* @return serializable metadata without executors or secret values
*/
Flux<ToolDescriptor> listTools();

/**
* Resolves an explicit selection, preserving selection order, for a generation request.
*
* <p>Empty or null selections resolve to no tools. Blank, duplicate, unavailable, globally disabled, or
* unconfigured IDs fail with {@link IllegalArgumentException}. Resolve tools for each generation request. Tools
* using the default permission policy are excluded when unauthorized; tools opting into execution-time rejection
* remain in the result. Selection order is preserved. Execution always rechecks declared permissions, availability,
* enabled state, configuration readiness, and approval mode; changed schemas or approval modes require resolving
* again. Dynamic predicates and lifecycle callbacks remain request-scoped. Providers must enforce authorization in
* the executor independently of approval decisions.
*
* @param toolIds stable catalog IDs, or {@code null} for no tools
* @return request-scoped executable definitions in selection order after permission filtering
*/
Mono<List<ToolDefinition>> resolveTools(List<String> toolIds);

/**
* Explicitly resolves globally enabled, configured tools according to their permission policies.
*
* <p>Unavailable tools and unauthorized tools using resolution-time filtering are excluded. Tools opting into
* execution-time rejection remain in the result. Executors retain their authorization, approval and lifecycle
* behavior. Consumers should normally prefer an explicit selection when only a subset is needed.
*
* @return all ready definitions permitted by their declared resolution policies
*/
Mono<List<ToolDefinition>> resolveAllTools();
}
Loading
Loading