터미널 세션 core와 CLI mode executor 경계를 분리해 후속 remote terminal bridge가 재사용할 내부 실행 기반을 만든다. adapter 기본값과 vLLM experimental surface도 명시해 production 실행 경로가 mock fallback이나 미구현 실행으로 숨지 않게 한다.
97 lines
2.6 KiB
Go
97 lines
2.6 KiB
Go
package adapters
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"iop/apps/node/internal/runtime"
|
|
)
|
|
|
|
// LifecycleAdapter is an optional interface for adapters that need start/stop lifecycle management.
|
|
type LifecycleAdapter interface {
|
|
Start(ctx context.Context) error
|
|
Stop(ctx context.Context) error
|
|
}
|
|
|
|
// Registry holds all registered adapters by name.
|
|
type Registry struct {
|
|
adapters map[string]runtime.Adapter
|
|
order []string // insertion order for lifecycle and diagnostics
|
|
}
|
|
|
|
func NewRegistry() *Registry {
|
|
return &Registry{adapters: make(map[string]runtime.Adapter)}
|
|
}
|
|
|
|
// Register adds an adapter. The first registered adapter becomes the default.
|
|
func (r *Registry) Register(a runtime.Adapter) {
|
|
name := a.Name()
|
|
if _, exists := r.adapters[name]; !exists {
|
|
r.order = append(r.order, name)
|
|
}
|
|
r.adapters[name] = a
|
|
}
|
|
|
|
func (r *Registry) Get(name string) (runtime.Adapter, bool) {
|
|
a, ok := r.adapters[name]
|
|
return a, ok
|
|
}
|
|
|
|
// All returns all registered adapters in registration order.
|
|
func (r *Registry) All() []runtime.Adapter {
|
|
out := make([]runtime.Adapter, 0, len(r.order))
|
|
for _, name := range r.order {
|
|
out = append(out, r.adapters[name])
|
|
}
|
|
return out
|
|
}
|
|
|
|
// MustGet returns the adapter or panics — useful during bootstrap validation.
|
|
func (r *Registry) MustGet(name string) runtime.Adapter {
|
|
a, ok := r.Get(name)
|
|
if !ok {
|
|
panic(fmt.Sprintf("adapter %q not registered", name))
|
|
}
|
|
return a
|
|
}
|
|
|
|
// Start calls Start on all registered LifecycleAdapters in registration order.
|
|
// On failure, already-started adapters are stopped in reverse order before returning.
|
|
func (r *Registry) Start(ctx context.Context) error {
|
|
started := make([]string, 0, len(r.order))
|
|
for _, name := range r.order {
|
|
lc, ok := r.adapters[name].(LifecycleAdapter)
|
|
if !ok {
|
|
continue
|
|
}
|
|
if err := lc.Start(ctx); err != nil {
|
|
for i := len(started) - 1; i >= 0; i-- {
|
|
if startedLC, ok := r.adapters[started[i]].(LifecycleAdapter); ok {
|
|
_ = startedLC.Stop(context.Background())
|
|
}
|
|
}
|
|
return fmt.Errorf("adapter %q start: %w", name, err)
|
|
}
|
|
started = append(started, name)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Stop calls Stop on all registered LifecycleAdapters in reverse registration order.
|
|
// All adapters are stopped even if some fail; the first error is returned.
|
|
func (r *Registry) Stop(ctx context.Context) error {
|
|
var firstErr error
|
|
for i := len(r.order) - 1; i >= 0; i-- {
|
|
name := r.order[i]
|
|
lc, ok := r.adapters[name].(LifecycleAdapter)
|
|
if !ok {
|
|
continue
|
|
}
|
|
if err := lc.Stop(ctx); err != nil {
|
|
if firstErr == nil {
|
|
firstErr = fmt.Errorf("adapter %q stop: %w", name, err)
|
|
}
|
|
}
|
|
}
|
|
return firstErr
|
|
}
|