Let compiled plugins prepare startup after host defaults merge
Why: RDM's sandbox policy must run after HostOptions are merged and be able to refuse startup when bwrap is missing. Evidence: go test ./pkg/extension/ ./cmd/agent-system/ -count=1 passed on this tree (SELF). Impact: InProc.Prepare and PrepareCompiled; serve applies plugin rewrites before app.Run. Refs: feature/svc-plugin-host-options Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -120,13 +120,23 @@ func main() {
|
||||
if !cliSet["execBackend"] && execBackendResolved == "" {
|
||||
execBackendResolved = pluginDefaults.ExecBackend
|
||||
}
|
||||
extOpt := extension.Options{
|
||||
Addr: resolved.Addr, DataDir: resolved.DataDir, PluginsDir: resolved.PluginsDir,
|
||||
DisableUploadIndexing: pluginDefaults.DisableUploadIndexing,
|
||||
DisableConvCardMirror: pluginDefaults.DisableConvCardMirror,
|
||||
DisableExecTools: disableExec, ExecBackend: execBackendResolved,
|
||||
}
|
||||
if err := extension.PrepareCompiled(&extOpt); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "agent-system:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := app.Run(app.Options{
|
||||
Addr: resolved.Addr, DataDir: resolved.DataDir, PluginsDir: resolved.PluginsDir, ForceMock: resolved.Mock,
|
||||
StorageDSN: resolved.StorageDSN, ArtifactsDir: resolved.ArtifactsDir, AuthMode: resolved.AuthMode,
|
||||
InstanceID: resolved.Instance, InsecureListen: resolved.InsecureListen, AllowedHosts: resolved.AllowedHosts(),
|
||||
DisableUploadIndexing: pluginDefaults.DisableUploadIndexing,
|
||||
DisableConvCardMirror: pluginDefaults.DisableConvCardMirror,
|
||||
DisableExecTools: disableExec, ExecBackend: execBackendResolved, ExecDepsDir: resolved.ExecDepsDir,
|
||||
DisableUploadIndexing: extOpt.DisableUploadIndexing,
|
||||
DisableConvCardMirror: extOpt.DisableConvCardMirror,
|
||||
DisableExecTools: extOpt.DisableExecTools, ExecBackend: extOpt.ExecBackend, ExecDepsDir: resolved.ExecDepsDir,
|
||||
ExecWorkspace: resolved.ExecWorkspace,
|
||||
Tier: resolved.Tier,
|
||||
PGPool: store.PoolOptions{
|
||||
|
||||
@@ -184,6 +184,8 @@ type InProc struct {
|
||||
HostOptions func() Options
|
||||
// CLI 可选。组合二进制在基座 serve 旗标上挂接插件专属旗标(如 bootstrap-admin)。
|
||||
CLI *CLIHook
|
||||
// Prepare 可选。基座合并 HostOptions 之后、进入服务之前调用,可改写 opt 或拒绝启动。
|
||||
Prepare func(opt *Options) error
|
||||
}
|
||||
|
||||
// Options 是下游自有二进制的启动参数,字段与 agent-system serve 对齐。
|
||||
@@ -277,6 +279,22 @@ func RunCLIHooks(opt Options) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
// PrepareCompiled 在 HostOptions 合并进 opt 之后调用各插件 Prepare。任一错误拒绝启动。
|
||||
func PrepareCompiled(opt *Options) error {
|
||||
if opt == nil {
|
||||
return errors.New("extension: nil options")
|
||||
}
|
||||
for _, e := range Compiled() {
|
||||
if e.Prepare == nil {
|
||||
continue
|
||||
}
|
||||
if err := e.Prepare(opt); err != nil {
|
||||
return fmt.Errorf("extension: %s: %w", e.ID, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RegisterCompiled 在 init 中登记进程内扩展。
|
||||
func RegisterCompiled(e InProc) {
|
||||
mu.Lock()
|
||||
|
||||
@@ -40,6 +40,32 @@ func TestMergeHostOptionsORAndExecConflict(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPrepareCompiledCanRejectStartup(t *testing.T) {
|
||||
ResetCompiled()
|
||||
t.Cleanup(ResetCompiled)
|
||||
RegisterCompiled(InProc{
|
||||
ID: "rdm",
|
||||
Prepare: func(opt *Options) error {
|
||||
if opt.ExecBackend == "sandbox" {
|
||||
return errors.New("no bwrap")
|
||||
}
|
||||
opt.DisableExecTools = true
|
||||
return nil
|
||||
},
|
||||
})
|
||||
opt := Options{ExecBackend: "sandbox"}
|
||||
if err := PrepareCompiled(&opt); err == nil {
|
||||
t.Fatal("expected prepare error")
|
||||
}
|
||||
opt.ExecBackend = "direct"
|
||||
if err := PrepareCompiled(&opt); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !opt.DisableExecTools {
|
||||
t.Fatal("prepare should be able to rewrite options")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCLIHookHandlesBeforeServe(t *testing.T) {
|
||||
ResetCompiled()
|
||||
t.Cleanup(ResetCompiled)
|
||||
|
||||
@@ -34,6 +34,7 @@ MergeHostOptions
|
||||
NewHostClient
|
||||
NewScopedHost
|
||||
Options
|
||||
PrepareCompiled
|
||||
ProjectHost
|
||||
ProjectHost.EnsureProject
|
||||
ProjectHost.OwnedProject
|
||||
|
||||
Reference in New Issue
Block a user