First Commit
ci / go (push) Waiting to run
ci / go-db (agent) (push) Waiting to run
ci / go-db (config) (push) Waiting to run
ci / go-db (db) (push) Waiting to run
ci / go-db (evidence) (push) Waiting to run
ci / go-db (llmrec) (push) Waiting to run
ci / go-db (server) (push) Waiting to run
web / web (push) Waiting to run
docs / links (push) Canceled after 0s
detections / detections (push) Canceled after 0s

This commit is contained in:
dela
2026-10-09 08:38:16 +08:00
commit 0335d572de
756 changed files with 201663 additions and 0 deletions
+51
View File
@@ -0,0 +1,51 @@
package agent
import (
"encoding/json"
"github.com/Autumn-27/norma/llm"
actool "github.com/Autumn-27/norma/tool"
)
// deferredSystem builds an agent's system-prompt segments and cache boundary from
// its DeferredInfo. When globally-available MCP tools are present, their names + a
// "prefer core tools" instruction render into a <available-deferred-tools> block
// placed as the LAST system-prompt segment, with DynamicBoundary set so the whole
// (session-fixed) system prompt — including the block — is cached (design doc
// §2.1 / C1). Skill-gated MCP names are NOT in this block; they surface when their
// skill loads. Returns a single plain segment + boundary 0 when there is no global
// block to add.
func deferredSystem(sysText string, def DeferredInfo) (system []string, boundary int) {
sysText += def.FindingGuidance
block := actool.RenderDeferredToolsBlock(def.GlobalNames)
if block == "" {
return []string{sysText}, 0
}
system = []string{sysText, block}
boundary = len(system) // b >= len → whole system prompt cached (SDK guard)
return system, boundary
}
// seedUnlockFromHistory replays prior Skill() invocations in the conversation so
// their skill-gated MCPs are re-unlocked on a resumed session (design doc C2). The
// main agent builds a fresh session each turn; its in-memory unlock set would
// otherwise reset, leaving the model able to see a skill-revealed tool name yet
// unable to call it. No-op when unlockSkill is nil (no deferred tools).
func seedUnlockFromHistory(msgs []llm.Message, unlockSkill func(string)) {
if unlockSkill == nil {
return
}
for _, m := range msgs {
for _, b := range m.ToolUses() {
if b.Name != "Skill" {
continue
}
var in struct {
Name string `json:"name"`
}
if json.Unmarshal(b.Input, &in) == nil && in.Name != "" {
unlockSkill(in.Name)
}
}
}
}