MoonBit 目录 = 包:本目录是一个包,不能再建子文件夹(子文件夹 = 子包, 会破坏 inherent methods 与包环约束,见 docs/report/sdk-split-feasibility.md)。 包内组织靠功能组分区注释 + 本导航文件。
| 文件 | 内容 |
|---|---|
| prism.mbt | Prism 门面类型 + PrismOptions/ConversionMeta/DecodedResponse + SdkProviderEndpoint |
| context.mbt | Context/SdkMessage/SdkTool 构建 + context_to_lux_request |
| 文件 | 内容 |
|---|---|
| registry.mbt | ProviderRegistration 定义 + providers_cache + 动态注册表(register/unregister/with_overrides,T6) |
| match.mbt | 路由匹配(match_provider_name / match_by_model)——唯一路由入口(静态表优先,动态表兜底) |
| 文件 | 内容 |
|---|---|
| pipeline.mbt | Prism 门面内部方法(encode/decode 样板,从自身 provider 出发) |
| codec_pipeline.mbt | 通用 decode→IR→encode 管线(任意 source→target,无状态) |
| 文件 | 内容 |
|---|---|
| convert.mbt | convert_request/response/stream 组合入口(场景 2)+ StreamConverter 增量会话(T5)+ 类型化入口(T7) |
| 文件 | 内容 |
|---|---|
| hooks.mbt | SdkRequestHook/SdkResponseHook/SdkStreamHook + convert_*_with_hooks + 内置钩子 |
| 文件 | 内容 |
|---|---|
| snapshot.mbt | ConversationStore + restore_request_from_snapshot + convert_request_with_store |
| 文件 | 内容 |
|---|---|
| error.mbt | PrismError(LucentErrorKind 上翻)+ 保守分类器 + is_retryable |
| diagnostics.mbt | DiagnosticPolicy + enforce_policy + DiagnosticCollector |
| 文件 | 内容 |
|---|---|
| schema.mbt | ProviderSchema/FieldConstraint |
| event.mbt | PrismToolCall/PrismToolResult/PrismThinking |
facade (prism/context) ──► match ◄── pipeline
│
registry(providers_cache + dynamic_providers)
▲
convert ◄─► codec_pipeline
▲
hooks / snapshot / error / diagnostics(只消费 IR 与注册表;
禁止反向依赖 provider——单向依赖图护栏)type SdkStreamHook = (Array[LucentStreamEvent], Array[ConversionDiagnostic]) -> Array[LucentStreamEvent]fn Context::add_assistant_turn(self : Context, text : String, tool_calls : Array[SdkToolCall]) -> Contextpub struct ConversationStore {
get : (String) -> ConversationSnapshot?
put : (ConversationSnapshot) -> Unit
}fn ConversationStore::new(get : (String) -> ConversationSnapshot?, put : (ConversationSnapshot) -> Unit) -> ConversationStorepub struct ConversionMeta {
source_provider : String
diagnostics : Array[ConversionDiagnostic]
provider_payload : Json?
extra_fields : Map[String, Json]?
}fn ConversionMeta::new(source_provider : String, diagnostics : Array[ConversionDiagnostic], provider_payload : Json?, extra_fields : Map[String, Json]?) -> ConversionMetalet collector = DiagnosticCollector::new()
collector.add_all(result.diagnostics())
// 周期性:
log(collector.summary())
collector.reset()fn DiagnosticCollector::add_all(self : DiagnosticCollector, diagnostics : Array[ConversionDiagnostic]) -> Unitfn DiagnosticCollector::enforce(self : DiagnosticCollector, policy : DiagnosticPolicy) -> Result[Unit, String]pub struct FieldConstraint {
min_val : Double?
max_val : Double?
required : Bool
allowed_values : Array[String]?
}fn FieldConstraint::new(min_val : Double?, max_val : Double?, required : Bool, allowed_values : Array[String]?) -> FieldConstraintpub struct Prism {
provider : String
}fn Prism::complete(self : Prism, text : String, opts : PrismOptions, send : (String) -> Result[String, String]) -> Result[String, String]fn Prism::decode_response_typed(self : Prism, json_str : String) -> Result[DecodedResponse, PrismError]fn Prism::decode_response_with_diagnostics(self : Prism, json_str : String) -> Result[ConversionResult[LucentResponse], String]fn Prism::decode_response_with_meta(self : Prism, json_str : String) -> Result[DecodedResponse, String]fn Prism::encode_request(self : Prism, text : String, opts : PrismOptions) -> Result[String, String]fn Prism::encode_request_typed(self : Prism, text : String, opts : PrismOptions) -> Result[String, PrismError]fn Prism::encode_request_with_diagnostics(self : Prism, text : String, opts : PrismOptions) -> Result[ConversionResult[String], String]fn Prism::encode_stream_request(self : Prism, text : String, opts : PrismOptions) -> Result[String, String]let events = prism.stream(ctx, send)?
let ctx = prism.events_to_context(ctx, events) // 回填 assistant 回合
// 执行工具…
let ctx = ctx.add_tool_result(id, result, false) // 注入结果
// 第二轮请求(provider 不再拒绝 tool_result)fn Prism::stream(self : Prism, ctx : Context, send : (String) -> Result[String, String]) -> Result[Array[PrismEvent], String]pub struct PrismError {
kind : LucentErrorKind
message : String
provider : String?
} derive(Eq, Debug)pub(all) enum PrismEvent {
TextDelta(String)
ToolCall(PrismToolCall)
ToolResult(PrismToolResult)
Thinking(PrismThinking)
Finish(PrismFinishReason)
}pub(all) enum PrismFinishReason {
Stop
Length
ToolCalls
ContentFilter
Error
}pub struct PrismOptions {
model : String?
temperature : Double?
max_tokens : Int?
store : Bool?
extras : Map[String, Json]?
tool_choice : LucentToolChoice?
reasoning_enabled : Bool?
reasoning_effort : LucentReasoningEffort?
structured_output : LucentStructuredOutput?
parallel_tool_calls : Bool?
}fn PrismOptions::new(model : String?, temperature : Double?, max_tokens : Int?, store : Bool?, extras : Map[String, Json]?) -> PrismOptionsfn PrismOptions::with_reasoning(self : PrismOptions, enabled : Bool?, effort : LucentReasoningEffort?) -> PrismOptionsfn PrismOptions::with_structured_output(self : PrismOptions, output : LucentStructuredOutput) -> PrismOptionspub struct PrismThinking {
text : String
signature : String?
redacted : Bool
}pub struct PrismToolCall {
id : String
name : String
arguments_json : String
}pub struct PrismToolResult {
tool_use_id : String
content : String
is_error : Bool
}pub struct ProviderRegistration {
name : String
aliases : Array[String]
capability : ProviderCapability
model_pattern : String
schema : ProviderSchema
request_decode : (String) -> Result[ConversionResult[LucentRequest], String]
request_encode : (LucentRequest) -> Result[ConversionResult[String], String]
response_decode : (String) -> Result[ConversionResult[LucentResponse], String]
response_encode : (LucentResponse) -> Result[ConversionResult[String], String]
events_decode : (String) -> Result[ConversionResult[Array[LucentStreamEvent]], String]
events_encode : (Array[LucentStreamEvent]) -> Result[ConversionResult[String], String]
events_encode_with_ctx : (Array[LucentStreamEvent], LucentConversationMeta?) -> Result[ConversionResult[String], String]
base_url : String?
auth_header : String?
api_version : String?
}fn ProviderRegistration::from_metadata(metadata : ProviderMeta, request_decode : (String) -> Result[ConversionResult[LucentRequest], String], request_encode : (LucentRequest) -> Result[ConversionResult[String], String], response_decode : (String) -> Result[ConversionResult[LucentResponse], String], response_encode : (LucentResponse) -> Result[ConversionResult[String], String], events_decode : (String) -> Result[ConversionResult[Array[LucentStreamEvent]], String], events_encode : (Array[LucentStreamEvent]) -> Result[ConversionResult[String], String], events_encode_with_ctx : (Array[LucentStreamEvent], LucentConversationMeta?) -> Result[ConversionResult[String], String], base_url : String?, auth_header : String?, api_version : String?) -> ProviderRegistrationfn ProviderRegistration::new(name : String, aliases : Array[String], capability : ProviderCapability, model_pattern : String, schema : ProviderSchema, request_decode : (String) -> Result[ConversionResult[LucentRequest], String], request_encode : (LucentRequest) -> Result[ConversionResult[String], String], response_decode : (String) -> Result[ConversionResult[LucentResponse], String], response_encode : (LucentResponse) -> Result[ConversionResult[String], String], events_decode : (String) -> Result[ConversionResult[Array[LucentStreamEvent]], String], events_encode : (Array[LucentStreamEvent]) -> Result[ConversionResult[String], String], events_encode_with_ctx : (Array[LucentStreamEvent], LucentConversationMeta?) -> Result[ConversionResult[String], String], base_url : String?, auth_header : String?, api_version : String?) -> ProviderRegistrationfn ProviderRegistration::with_overrides(self : ProviderRegistration, overrides : RegistrationOverrides) -> ProviderRegistrationpub struct ProviderSchema {
provider_name : String
temperature : FieldConstraint
top_p : FieldConstraint
top_k : FieldConstraint
max_output_tokens : FieldConstraint
resp_min_choices : Int
supports_tools : Bool
supports_system_instruction : Bool
supported_reasoning_efforts : Array[String]?
extra_checks : Array[() -> Array[String]]?
}pub struct RegistrationOverrides {
name : String?
aliases : Array[String]?
model_pattern : String?
base_url : String?
auth_header : String?
api_version : String?
}pub struct SdkMessage {
role : String
content : String
tool_use_id : String?
is_error : Bool?
tool_calls : Array[SdkToolCall]
}fn SdkMessage::tool_call(id : String, name : String, arguments_json : String, content : String) -> SdkMessagepub struct SdkProviderEndpoint {
base_url : String?
auth_header : String?
api_version : String?
}pub struct SdkTool {
name : String
description : String
parameters_json : String
}pub struct SdkToolCall {
id : String
name : String
arguments_json : String
}pub struct StreamConverter {
source : ProviderRegistration
target : ProviderRegistration
splitter : SseFrameSplitter
stream_ctx : LucentConversationMeta?
open_blocks : Array[Int]
held_events : Array[LucentStreamEvent]
}let conv = StreamConverter::new("openai", "messages")?
for chunk in upstream_chunks {
let frames = conv.feed(chunk)? // 立即转发给下游
downstream.write(frames)
}
let tail = conv.finish()? // 冲刷尾部半帧fn convert_request(source : String, json_str : String, target : String) -> Result[ConversionResult[String], String]fn convert_request_typed(source : String, json_str : String, target : String) -> Result[ConversionResult[String], PrismError]fn convert_request_with_hooks(source : String, json_str : String, target : String, hooks : Array[(LucentRequest, Array[ConversionDiagnostic]) -> LucentRequest]) -> Result[ConversionResult[String], String]fn convert_request_with_store(source : String, json_str : String, target : String, store : ConversationStore) -> Result[ConversionResult[String], String]fn convert_response(source : String, json_str : String, target : String) -> Result[ConversionResult[String], String]fn convert_response_typed(source : String, json_str : String, target : String) -> Result[ConversionResult[String], PrismError]fn convert_response_with_hooks(source : String, json_str : String, target : String, hooks : Array[(LucentResponse, Array[ConversionDiagnostic]) -> LucentResponse]) -> Result[ConversionResult[String], String]fn convert_response_with_meta(source : String, json_str : String, target : String) -> Result[ConvertMetaResult, String]fn convert_stream(source : String, sse_str : String, target : String) -> Result[ConversionResult[String], String]fn convert_stream_typed(source : String, sse_str : String, target : String) -> Result[ConversionResult[String], PrismError]fn convert_stream_with_hooks(source : String, sse_str : String, target : String, hooks : Array[(Array[LucentStreamEvent], Array[ConversionDiagnostic]) -> Array[LucentStreamEvent]]) -> Result[ConversionResult[String], String]fn[T] enforce_policy(value : T, diagnostics : Array[ConversionDiagnostic], policy : DiagnosticPolicy) -> Result[T, String]fn hook_append_instructions(text : String) -> ((LucentRequest, Array[ConversionDiagnostic]) -> LucentRequest)fn hook_clamp_max_tokens(limit : Int) -> ((LucentRequest, Array[ConversionDiagnostic]) -> LucentRequest)fn hook_filter_tools(allowed : Array[String]) -> ((LucentRequest, Array[ConversionDiagnostic]) -> LucentRequest)fn hook_set_model(model : String) -> ((LucentRequest, Array[ConversionDiagnostic]) -> LucentRequest)fn hook_stream_drop_after_error() -> ((Array[LucentStreamEvent], Array[ConversionDiagnostic]) -> Array[LucentStreamEvent])fn restore_request_from_snapshot(req : LucentRequest, snapshot : ConversationSnapshot) -> LucentRequestfn store_snapshot_from_response(store : ConversationStore, req : LucentRequest, response : LucentResponse) -> Unitfn unregister_provider(name : String) -> BoolInstall
Download zipA unified LLM protocol middleware converting between OpenAI, Anthropic, Gemini and other provider formats via the Lucent IR neutral protocol