144 lines
5.5 KiB
Go
144 lines
5.5 KiB
Go
package app
|
||
|
||
import (
|
||
"encoding/json"
|
||
"fmt"
|
||
"strings"
|
||
"unicode/utf8"
|
||
|
||
"infinite-canvas/backend/internal/prompts"
|
||
)
|
||
|
||
const (
|
||
cloudAgentCompilerVersion = "cloud-agent-policy-compiler/v4"
|
||
cloudAgentDefaultReasoning = "off"
|
||
)
|
||
|
||
type cloudAgentPolicySnapshot struct {
|
||
SystemPolicyID string `json:"systemPolicyId"`
|
||
SystemPolicyVersion int `json:"systemPolicyVersion"`
|
||
SystemPolicyHash string `json:"systemPolicyHash"`
|
||
MediaPolicyID string `json:"mediaPolicyId"`
|
||
MediaPolicyVersion int `json:"mediaPolicyVersion"`
|
||
MediaPolicyHash string `json:"mediaPolicyHash"`
|
||
CapabilitySetVersion string `json:"capabilitySetVersion"`
|
||
CapabilitySetHash string `json:"capabilitySetHash"`
|
||
ReasoningMode string `json:"reasoningMode"`
|
||
CompilerVersion string `json:"compilerVersion"`
|
||
ProfileRevision string `json:"profileRevision,omitempty"`
|
||
ProfileHash string `json:"profileHash,omitempty"`
|
||
}
|
||
|
||
type cloudAgentProfileSnapshot struct {
|
||
Revision string `json:"revision"`
|
||
Hash string `json:"hash"`
|
||
Layers []AgentProfileLayer `json:"layers"`
|
||
}
|
||
|
||
func cloudAgentReasoningMode(req CloudAgentRequest) string {
|
||
mode := strings.ToLower(strings.TrimSpace(req.ReasoningMode))
|
||
if mode == "off" || mode == "auto" || mode == "deep" {
|
||
return mode
|
||
}
|
||
return cloudAgentDefaultReasoning
|
||
}
|
||
|
||
func cloudAgentReasoningEnabled(mode string) bool { return mode == "auto" || mode == "deep" }
|
||
|
||
func cloudAgentCapabilityGuide() string {
|
||
var b strings.Builder
|
||
b.WriteString("节点能力速查(由服务端能力注册表生成,只用于自主路由,不是工具授权):\n")
|
||
for _, descriptor := range canvasCapabilityRegistry.List() {
|
||
b.WriteString("- ")
|
||
b.WriteString(descriptor.Label)
|
||
b.WriteString("(")
|
||
b.WriteString(descriptor.Type)
|
||
b.WriteString("):")
|
||
b.WriteString(descriptor.Purpose)
|
||
if len(descriptor.GoodFor) > 0 {
|
||
b.WriteString(" 适合:")
|
||
b.WriteString(strings.Join(descriptor.GoodFor, "、"))
|
||
b.WriteString("。")
|
||
}
|
||
if len(descriptor.NotIdealFor) > 0 {
|
||
b.WriteString(" 不适合:")
|
||
b.WriteString(strings.Join(descriptor.NotIdealFor, "、"))
|
||
b.WriteString("。")
|
||
}
|
||
if len(descriptor.Tradeoffs) > 0 {
|
||
b.WriteString(" 维护取舍:")
|
||
b.WriteString(strings.Join(descriptor.Tradeoffs, ";"))
|
||
b.WriteString("。")
|
||
}
|
||
connection, _ := json.Marshal(map[string]any{
|
||
"inputKind": descriptor.InputKind, "canSource": descriptor.Connection.CanSource,
|
||
"canTarget": descriptor.Connection.CanTarget, "canReference": descriptor.Connection.CanReference,
|
||
"acceptedInputKinds": descriptor.Connection.AcceptedInputKinds,
|
||
"rejectedInputKinds": descriptor.Connection.RejectedInputKinds,
|
||
"maxInputCount": descriptor.Connection.MaxInputCount,
|
||
})
|
||
b.WriteString(" 连线能力:")
|
||
b.Write(connection)
|
||
b.WriteString("\n")
|
||
}
|
||
return b.String()
|
||
}
|
||
|
||
func compileCloudAgentPolicies(req CloudAgentRequest, skills []cloudAgentSkill, canvasSummary string, profile cloudAgentProfileSnapshot, anchors ...cloudAgentCreativeAnchor) (string, cloudAgentPolicySnapshot, error) {
|
||
system, media, err := prompts.LoadAgentPolicies()
|
||
if err != nil {
|
||
return "", cloudAgentPolicySnapshot{}, err
|
||
}
|
||
mode := cloudAgentReasoningMode(req)
|
||
capabilityHash := cloudAgentCapabilitySetHash()
|
||
snapshot := cloudAgentPolicySnapshot{
|
||
SystemPolicyID: system.ID, SystemPolicyVersion: system.Version, SystemPolicyHash: system.Hash,
|
||
MediaPolicyID: media.ID, MediaPolicyVersion: media.Version, MediaPolicyHash: media.Hash,
|
||
CapabilitySetVersion: cloudAgentCapabilitySetVersion, CapabilitySetHash: capabilityHash,
|
||
ReasoningMode: mode, CompilerVersion: cloudAgentCompilerVersion,
|
||
ProfileRevision: profile.Revision, ProfileHash: profile.Hash,
|
||
}
|
||
var b strings.Builder
|
||
b.WriteString(system.Text)
|
||
b.WriteString("\n\n")
|
||
b.WriteString(media.Text)
|
||
b.WriteString("\n\n")
|
||
b.WriteString(cloudAgentCapabilityGuide())
|
||
// Behavior belongs to versioned policies; the compiler only projects facts.
|
||
context := map[string]any{
|
||
"source": "server_snapshot", "permissionMode": req.PermissionMode,
|
||
"reasoningMode": mode,
|
||
"budget": map[string]any{
|
||
"maxCredits": req.Budget.MaxCredits, "maxSteps": cloudAgentStepLimit(req),
|
||
"maxGenerationTasks": req.Budget.MaxGenerationTasks, "maxVideoSeconds": req.Budget.MaxVideoSeconds,
|
||
},
|
||
"maxToolCalls": cloudAgentMaxToolCalls, "maxOutputBytes": cloudAgentMaxOutputBytes,
|
||
"canvasSummary": canvasSummary,
|
||
}
|
||
if len(anchors) > 0 {
|
||
// User intent remains in user messages, never frozen into system context.
|
||
context["referenceCandidates"] = anchors[0].ReferenceAssets
|
||
}
|
||
manifests := make([]map[string]any, 0, len(skills))
|
||
for _, skill := range skills {
|
||
manifests = append(manifests, map[string]any{"skillId": skill.ID, "name": skill.Name, "version": skill.Version, "hash": skill.Hash, "entryPath": cloudAgentSkillEntryPath, "files": cloudAgentSkillPaths(skill)})
|
||
}
|
||
context["skills"] = manifests
|
||
layers := make([]map[string]any, 0, len(profile.Layers))
|
||
for _, layer := range profile.Layers {
|
||
layers = append(layers, map[string]any{"scope": layer.Scope, "revision": layer.Revision, "hash": layer.Hash, "characters": utf8.RuneCountInString(layer.Content)})
|
||
}
|
||
context["profileLayers"] = layers
|
||
encoded, err := json.Marshal(context)
|
||
if err != nil {
|
||
return "", cloudAgentPolicySnapshot{}, fmt.Errorf("encode Agent execution context: %w", err)
|
||
}
|
||
b.WriteString("\n\n本轮执行上下文:\n")
|
||
b.Write(encoded)
|
||
text := strings.TrimSpace(b.String())
|
||
if text == "" {
|
||
return "", cloudAgentPolicySnapshot{}, fmt.Errorf("compiled Agent policy is empty")
|
||
}
|
||
return text, snapshot, nil
|
||
}
|