Why: Downstream products must extend the base through a public package and host API instead of editing internal code. Evidence: go test ./... passed, including plugin v2 assets, sidecar startup, migration v13, pending confirms, HITL timeout, hash embedder, command pairs, and the extension surface snapshot. Impact: apiVersion 2.0-experimental rejects empty network allowlists for declarative HTTP. Hash embeddings stay opt-in via models.embedding.provider=hash. Plugin secrets resolve per owner at execution time. Refs: docs/proposals/2026-10-01-plugin-contract-v2.md Co-authored-by: Cursor <cursoragent@cursor.com>
47 lines
1.1 KiB
Go
47 lines
1.1 KiB
Go
package server
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
agentcommand "agent-command"
|
|
"agent-system-backend/internal/cmdbus"
|
|
)
|
|
|
|
type pair struct {
|
|
ID string `json:"id"`
|
|
Button bool `json:"button"`
|
|
Chat bool `json:"chat"`
|
|
}
|
|
|
|
type nopAudit struct{}
|
|
|
|
func (nopAudit) AppendAudit(agentcommand.AuditEnvelope) error { return nil }
|
|
|
|
// 每个内置命令都必须在 command-pairs.json 里同时声明按钮入口与对话入口。
|
|
// 新命令漏登记则本测试失败,合入被挡住。
|
|
func TestBuiltinCommandsHaveDualEntryPairs(t *testing.T) {
|
|
raw, err := os.ReadFile(filepath.Join("testdata", "command-pairs.json"))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var pairs []pair
|
|
if err := json.Unmarshal(raw, &pairs); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
byID := map[string]pair{}
|
|
for _, p := range pairs {
|
|
byID[p.ID] = p
|
|
}
|
|
s := &Server{Bus: cmdbus.New(nopAudit{}, nil, nil)}
|
|
s.WireBuiltinCommands()
|
|
for _, cmd := range s.Bus.List() {
|
|
p, ok := byID[cmd.Spec.ID]
|
|
if !ok || !p.Button || !p.Chat {
|
|
t.Errorf("command %s missing dual-entry pair (button and chat)", cmd.Spec.ID)
|
|
}
|
|
}
|
|
}
|