mirror of
https://github.com/Twigpine/zero.git
synced 2026-11-12 08:41:32 -10:00
* perf(output): add token-aware budget contract * perf(output): add semantic retention policies * perf(output): budget results after redaction * perf(output): propagate tool truncation metadata * perf(output): trace semantic budget decisions * perf(output): classify core tool output * docs(output): describe semantic output budgeting * test(output): make spill fallback portable on windows * fix(output): address semantic budgeting review findings * test(output): make hook budgeting tests portable * fix(output): retain oversized single-line file content * fix(output): apply semantic budgets to captured output * fix(output): preserve hook budgets and search paths * fix(output): preserve alias and truncation metadata * test(trace): validate output budget metadata --------- Co-authored-by: KRATOS <[email protected]>
55 lines
1.6 KiB
Go
55 lines
1.6 KiB
Go
package cli
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/Gitlawb/zero/internal/agent"
|
|
"github.com/Gitlawb/zero/internal/tools"
|
|
)
|
|
|
|
// escalate_model is a control-only tool (SideEffectNone). The stream-json tool
|
|
// call must report sideEffect "none", not "unknown", so automation sees the
|
|
// promised value.
|
|
func TestStreamJSONSideEffectReportsNoneForControlTool(t *testing.T) {
|
|
registry := tools.NewRegistry()
|
|
registry.Register(tools.NewEscalateModelTool())
|
|
if got := streamJSONSideEffect("escalate_model", registry); got != "none" {
|
|
t.Fatalf("streamJSONSideEffect(escalate_model) = %q, want none", got)
|
|
}
|
|
}
|
|
|
|
func TestExecWriterPropagatesToolResultTruncation(t *testing.T) {
|
|
for _, format := range []execOutputFormat{execOutputJSON, execOutputStreamJSON} {
|
|
t.Run(string(format), func(t *testing.T) {
|
|
var stdout, stderr bytes.Buffer
|
|
writer := execEventWriter{
|
|
stdout: &stdout,
|
|
stderr: &stderr,
|
|
format: format,
|
|
runID: "run_budget",
|
|
streamedText: &strings.Builder{},
|
|
}
|
|
writer.toolResult(agent.ToolResult{
|
|
ToolCallID: "call_budget",
|
|
Name: "read_file",
|
|
Status: tools.StatusOK,
|
|
Output: "bounded output",
|
|
Truncated: true,
|
|
})
|
|
if writer.err != nil {
|
|
t.Fatalf("toolResult: %v", writer.err)
|
|
}
|
|
var payload map[string]any
|
|
if err := json.Unmarshal(bytes.TrimSpace(stdout.Bytes()), &payload); err != nil {
|
|
t.Fatalf("decode output %q: %v", stdout.String(), err)
|
|
}
|
|
if payload["truncated"] != true {
|
|
t.Fatalf("truncated = %#v, want true; payload=%#v", payload["truncated"], payload)
|
|
}
|
|
})
|
|
}
|
|
}
|