session: define Core interface at consumer, use concrete *session.Session
Core interface defined in 9p/session/core.go lists the methods the 9P layer needs. The real *session.Session satisfies it implicitly. Test stubs continue to work via interface satisfaction.
This commit is contained in:
parent
50f4a06d2e
commit
cf894920fa
|
|
@ -165,7 +165,7 @@ func newTestSessionManagerWithCore(t *testing.T) *session.Manager {
|
||||||
Sink: sink,
|
Sink: sink,
|
||||||
ReadFile: func(string) ([]byte, error) { return []byte("#!/bin/sh\n"), nil },
|
ReadFile: func(string) ([]byte, error) { return []byte("#!/bin/sh\n"), nil },
|
||||||
MkdirAll: func(string, os.FileMode) error { return nil },
|
MkdirAll: func(string, os.FileMode) error { return nil },
|
||||||
NewCore: func(sessionID, agentName, cwd string) (agent.Session, error) {
|
NewCore: func(sessionID, agentName, cwd string) (session.Core, error) {
|
||||||
return &stubCore{state: "idle", backend_: "stub", model: "m", agentName: agentName, cwd: cwd}, nil
|
return &stubCore{state: "idle", backend_: "stub", model: "m", agentName: agentName, cwd: cwd}, nil
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
@ -1221,7 +1221,7 @@ func TestSessionManagerCreateSessionEnvExpansion(t *testing.T) {
|
||||||
Sink: sink,
|
Sink: sink,
|
||||||
ReadFile: func(string) ([]byte, error) { return []byte("#!/bin/sh\n"), nil },
|
ReadFile: func(string) ([]byte, error) { return []byte("#!/bin/sh\n"), nil },
|
||||||
MkdirAll: func(string, os.FileMode) error { return nil },
|
MkdirAll: func(string, os.FileMode) error { return nil },
|
||||||
NewCore: func(sessionID, agentName, cwd string) (agent.Session, error) {
|
NewCore: func(sessionID, agentName, cwd string) (session.Core, error) {
|
||||||
gotCwd = cwd
|
gotCwd = cwd
|
||||||
return &stubCore{state: "idle", backend_: "stub", model: "m", agentName: agentName, cwd: cwd}, nil
|
return &stubCore{state: "idle", backend_: "stub", model: "m", agentName: agentName, cwd: cwd}, nil
|
||||||
},
|
},
|
||||||
|
|
@ -1248,7 +1248,7 @@ func TestSessionManagerCreateSessionTildeExpansion(t *testing.T) {
|
||||||
Sink: sink,
|
Sink: sink,
|
||||||
ReadFile: func(string) ([]byte, error) { return []byte("#!/bin/sh\n"), nil },
|
ReadFile: func(string) ([]byte, error) { return []byte("#!/bin/sh\n"), nil },
|
||||||
MkdirAll: func(string, os.FileMode) error { return nil },
|
MkdirAll: func(string, os.FileMode) error { return nil },
|
||||||
NewCore: func(sessionID, agentName, cwd string) (agent.Session, error) {
|
NewCore: func(sessionID, agentName, cwd string) (session.Core, error) {
|
||||||
gotCwd = cwd
|
gotCwd = cwd
|
||||||
return &stubCore{state: "idle", backend_: "stub", model: "m", agentName: agentName, cwd: cwd}, nil
|
return &stubCore{state: "idle", backend_: "stub", model: "m", agentName: agentName, cwd: cwd}, nil
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
package session
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/simonfxr/pubsub"
|
||||||
|
agent "ollie/session"
|
||||||
|
"ollie/backend"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Core is the interface that a session implementation must satisfy.
|
||||||
|
// Defined here (at the consumer) rather than in ollie/session so that
|
||||||
|
// the core package exports only a concrete struct with no interface overhead.
|
||||||
|
// Tests can substitute a lightweight stub.
|
||||||
|
type Core interface {
|
||||||
|
Submit(ctx context.Context, input string)
|
||||||
|
Interrupt(cause error) bool
|
||||||
|
Inject(prompt string)
|
||||||
|
Queue(prompt string)
|
||||||
|
PopQueue() (string, bool)
|
||||||
|
Bus() *pubsub.Bus
|
||||||
|
IsRunning() bool
|
||||||
|
State() string
|
||||||
|
Reply() string
|
||||||
|
AgentName() string
|
||||||
|
BackendName() string
|
||||||
|
ModelName() string
|
||||||
|
CWD() string
|
||||||
|
SetCWD(dir string) error
|
||||||
|
SetSessionID(newID string) error
|
||||||
|
Context() []backend.Message
|
||||||
|
SystemPrompt() string
|
||||||
|
GenerationParams() backend.GenerationParams
|
||||||
|
SetGenerationParams(params backend.GenerationParams) error
|
||||||
|
CompactionModel() string
|
||||||
|
SetCompactionModel(model string)
|
||||||
|
Usage() string
|
||||||
|
Cost() string
|
||||||
|
CtxSz() string
|
||||||
|
ListModels() string
|
||||||
|
WaitChange(ctx context.Context, field, current string) (string, bool)
|
||||||
|
SaveSession(path string) error
|
||||||
|
Close()
|
||||||
|
Detach() bool
|
||||||
|
ListDetached() []agent.DetachedInfo
|
||||||
|
SignalDetached(pid, signal int) error
|
||||||
|
GetDetachedOutput(pid int) (string, error)
|
||||||
|
DismissDetached(pid int) bool
|
||||||
|
InjectSystemEvent(content string)
|
||||||
|
React(emoji string)
|
||||||
|
ReactTo(responseID, emoji string) error
|
||||||
|
Reactions() map[string]string
|
||||||
|
ToolCallCount() int64
|
||||||
|
SetEnv(key, value string)
|
||||||
|
}
|
||||||
|
|
@ -29,7 +29,7 @@ type Session struct {
|
||||||
mu sync.RWMutex
|
mu sync.RWMutex
|
||||||
id string
|
id string
|
||||||
uname string // immutable user principal (numeric UID), set at creation
|
uname string // immutable user principal (numeric UID), set at creation
|
||||||
Core agent.Session
|
Core Core
|
||||||
Ctx context.Context
|
Ctx context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
log []byte
|
log []byte
|
||||||
|
|
@ -46,7 +46,7 @@ type Session struct {
|
||||||
modelsCacheAt time.Time
|
modelsCacheAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSession(id string, core agent.Session, ctx context.Context, cancel context.CancelFunc) *Session {
|
func NewSession(id string, core Core, ctx context.Context, cancel context.CancelFunc) *Session {
|
||||||
sess := &Session{id: id, Core: core, Ctx: ctx, cancel: cancel}
|
sess := &Session{id: id, Core: core, Ctx: ctx, cancel: cancel}
|
||||||
sess.startEventLog()
|
sess.startEventLog()
|
||||||
return sess
|
return sess
|
||||||
|
|
@ -236,7 +236,7 @@ type ManagerConfig struct {
|
||||||
MkdirAll func(string, os.FileMode) error
|
MkdirAll func(string, os.FileMode) error
|
||||||
// NewCore, if non-nil, replaces the default backend.New + agent.New
|
// NewCore, if non-nil, replaces the default backend.New + agent.New
|
||||||
// path. It receives the session ID, agent name, and cwd, and returns a Core.
|
// path. It receives the session ID, agent name, and cwd, and returns a Core.
|
||||||
NewCore func(sessionID, agentName, cwd string) (agent.Session, error)
|
NewCore func(sessionID, agentName, cwd string) (Core, error)
|
||||||
// Strict rejects inline code steps; only tool steps are allowed.
|
// Strict rejects inline code steps; only tool steps are allowed.
|
||||||
Strict bool
|
Strict bool
|
||||||
// Yolo skips the landrun sandbox.
|
// Yolo skips the landrun sandbox.
|
||||||
|
|
@ -1122,7 +1122,7 @@ func (s *Manager) CreateSession(args []string) (string, error) {
|
||||||
return "", fmt.Errorf("session already exists: %s", sessID)
|
return "", fmt.Errorf("session already exists: %s", sessID)
|
||||||
}
|
}
|
||||||
|
|
||||||
var core agent.Session
|
var core Core
|
||||||
var sessPtr *Session
|
var sessPtr *Session
|
||||||
uname := s.nextUname()
|
uname := s.nextUname()
|
||||||
if s.cfg.NewCore != nil {
|
if s.cfg.NewCore != nil {
|
||||||
|
|
|
||||||
Reference in New Issue