Files
hunjing/engine/bindings/go/lingtai/lingtai.go
T
chenxin a39cec5287 ✨ feat: 灵台引擎五神齐备与 Go/Rust 官方绑定(WP-15)
- C++ 新增四模块(modules.cpp,19 个导出符号全部 hj_*):
  小周天 hj_stream:流会话(sequence/delta_index 单调)与 content.block.delta envelope 确定性编码(重放字节一致)
  烛照 hj_policy:URL 协议白名单(拒 file/javascript/data)、路径授权根与 .. 段拒绝、幂等键非空≤128、四维决策表(autonomy×risk→allow/ask/deny,非法输入 deny fail-closed)
  洛书 hj_plan:预算核算(达限/负数拒绝)
  河图 hj_recall:确定性重排(词频×稳定排序,canonical JSON 输出;非法输入 PARSE_FAILED)
- doctest 22 用例 20135 断言全绿(含每模块 golden 与确定性双跑)
- Go 绑定(cgo 自包含编译引擎源码):Engine RAII/TransformMarkdown/ValidateURL/ValidatePath/Decide/CheckBudget/RecallRerank;go test 3 用例通过(transform/rerank golden 与 C++ 字节一致)
- Rust 绑定(bindgen 生成 + 安全包装):Engine RAII(Drop 释放)、Error 枚举映射全部 HjStatus、Send/Sync(HjEngine 线程安全);cargo test 3 用例通过(同 golden)
- 三端(C++/Go/Rust)与 Python golden 一致:同一 markdown 输入在四端输出字节相同(跨端一致性首次全语言验证)
2026-09-12 13:54:12 +08:00

154 lines
4.3 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 lingtai 是灵台引擎的官方 Go 绑定(cgo,ADR-016/017)。
//
// 自包含编译引擎源码;薄封装:仅类型转换与错误映射(契约 lingtai-ffi 第 8 节)。
package lingtai
/*
#cgo CXXFLAGS: -std=c++23 -O2
#cgo CFLAGS: -I${SRCDIR}/../../include
#include <stdlib.h>
#include "hunjing/lingtai.h"
// C 桥接(C++ 编译单元在下方 sources 中声明为 C++,由 cgo 链接 C++ 编译器)
typedef int (*unused_cb)();
*/
import "C"
import (
"fmt"
"unsafe"
)
// 直接编译引擎源码(cgo 自动以 C++ 处理 .cpp 文件)
// 注:通过 #cgo LDFLAGS/CXXFLAGS 与文件列表在同目录 cxx_sources.go 中声明。
// Engine 是线程安全的引擎句柄(RAII)。
type Engine struct {
ptr *C.HjEngine
}
// New 创建引擎;ABI major 不匹配返回错误(fail-fast,不静默降级)。
func New() (*Engine, error) {
var ptr *C.HjEngine
st := C.hj_engine_new(C.HJ_ABI_VERSION, &ptr)
if st != C.HJ_OK {
return nil, fmt.Errorf("lingtai: engine init failed: %s", C.GoString(C.hj_last_error()))
}
return &Engine{ptr: ptr}, nil
}
// Close 释放引擎(幂等安全:nil 检查)。
func (e *Engine) Close() error {
if e == nil || e.ptr == nil {
return nil
}
st := C.hj_engine_free(e.ptr)
e.ptr = nil
if st != C.HJ_OK {
return fmt.Errorf("lingtai: engine free: %s", C.GoString(C.hj_last_error()))
}
return nil
}
func (e *Engine) valid() error {
if e == nil || e.ptr == nil {
return fmt.Errorf("lingtai: engine handle is nil")
}
return nil
}
// TransformVersion 返回 Markdown 解析器版本。
func TransformVersion() string { return C.GoString(C.hj_transform_version()) }
// TransformMarkdown 将 Markdown 规范化为 canonical ContentBlock JSON。
func (e *Engine) TransformMarkdown(input string) (string, error) {
if err := e.valid(); err != nil {
return "", err
}
cin := C.CString(input)
defer C.free(unsafe.Pointer(cin))
var buf *C.HjBuffer
st := C.hj_transform_markdown(e.ptr, cin, C.size_t(len(input)), &buf)
if st != C.HJ_OK {
return "", fmt.Errorf("lingtai: transform: %s", C.GoString(C.hj_last_error()))
}
defer C.hj_buffer_free(buf)
return C.GoStringN((*C.char)(C.hj_buffer_data(buf)), C.int(C.hj_buffer_len(buf))), nil
}
// ValidateURL 校验 URL 协议(仅 http/https)。
func ValidateURL(url string) error {
cu := C.CString(url)
defer C.free(unsafe.Pointer(cu))
if st := C.hj_policy_validate_url(cu); st != C.HJ_OK {
return fmt.Errorf("lingtai: url denied: %s", C.GoString(C.hj_last_error()))
}
return nil
}
// ValidatePath 校验路径在授权根内(拒绝 .. 与越界)。
func ValidatePath(path, root string) error {
cp := C.CString(path)
cr := C.CString(root)
defer C.free(unsafe.Pointer(cp))
defer C.free(unsafe.Pointer(cr))
if st := C.hj_policy_validate_path(cp, cr); st != C.HJ_OK {
return fmt.Errorf("lingtai: path denied: %s", C.GoString(C.hj_last_error()))
}
return nil
}
// PolicyDecision 是四维裁决结果。
type PolicyDecision int
const (
DecisionAllow PolicyDecision = 0
DecisionAsk PolicyDecision = 1
DecisionDeny PolicyDecision = 2
)
// Autonomy levels(契约 autonomy_level)。
const (
AutonomyIntrospective = 0
AutonomyRuleBound = 1
AutonomyApprovalReq = 2
AutonomyForbidden = 3
)
// Risk levels。
const (
RiskReadOnly = 0
RiskSideEffect = 1
RiskHighImpact = 2
)
// Decide 运行决策表(autonomy × risk → allow/ask/deny;非法输入 deny)。
func Decide(autonomy, risk int) PolicyDecision {
return PolicyDecision(C.hj_policy_decide(C.int(autonomy), C.int(risk)))
}
// CheckBudget 校验预算(used >= max 返回错误)。
func CheckBudget(used, maximum int64) error {
if st := C.hj_plan_check_budget(C.int64_t(used), C.int64_t(maximum)); st != C.HJ_OK {
return fmt.Errorf("lingtai: budget: %s", C.GoString(C.hj_last_error()))
}
return nil
}
// RecallRerank 对候选做确定性重排,返回 canonical JSON。
func (e *Engine) RecallRerank(candidatesJSON string) (string, error) {
if err := e.valid(); err != nil {
return "", err
}
cj := C.CString(candidatesJSON)
defer C.free(unsafe.Pointer(cj))
var buf *C.HjBuffer
st := C.hj_recall_rerank(cj, &buf)
if st != C.HJ_OK {
return "", fmt.Errorf("lingtai: rerank: %s", C.GoString(C.hj_last_error()))
}
defer C.hj_buffer_free(buf)
return C.GoStringN((*C.char)(C.hj_buffer_data(buf)), C.int(C.hj_buffer_len(buf))), nil
}