9p: call Agent() directly for all agent operations
Session pass-throughs are removed. All agent operations go through sess.Core.Agent().Method() — proper encapsulation boundary. Session-level: Bus(), Close(), SetEnv(), CWD(), SetCWD(), Interrupt(), Queue(), InjectSystemEvent(), SetSessionID(), SaveSession(). Agent-level (via .Agent()): Submit(), State(), Reply(), BackendName(), ModelName(), IsRunning(), CtxSz(), UsageStr(), Context(), etc.
This commit is contained in:
parent
f142601f5f
commit
50601ebf46
38
dbus.go
38
dbus.go
|
|
@ -137,7 +137,7 @@ func (a *DBusAdapter) startWatcher(id string, sess *mgr.Session) {
|
||||||
|
|
||||||
// State watcher
|
// State watcher
|
||||||
go func() {
|
go func() {
|
||||||
current := sess.Core.State()
|
current := sess.Core.Agent().State()
|
||||||
for {
|
for {
|
||||||
next, ok := sess.Core.WaitChange(ctx, agent.WatchState, current)
|
next, ok := sess.Core.WaitChange(ctx, agent.WatchState, current)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
@ -153,7 +153,7 @@ func (a *DBusAdapter) startWatcher(id string, sess *mgr.Session) {
|
||||||
|
|
||||||
// Agent watcher — emits ConfigChanged when the agent name changes
|
// Agent watcher — emits ConfigChanged when the agent name changes
|
||||||
go func() {
|
go func() {
|
||||||
current := sess.Core.AgentName()
|
current := sess.Core.Agent().Name()
|
||||||
for {
|
for {
|
||||||
next, ok := sess.Core.WaitChange(ctx, "agent", current)
|
next, ok := sess.Core.WaitChange(ctx, "agent", current)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
@ -275,7 +275,7 @@ func (a *DBusAdapter) ListSessions() ([]string, *dbus.Error) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
result = append(result, fmt.Sprintf("%s\t%s\t%s\t%s",
|
result = append(result, fmt.Sprintf("%s\t%s\t%s\t%s",
|
||||||
id, sess.Core.State(), sess.Core.ModelName(), sess.Core.AgentName()))
|
id, sess.Core.Agent().State(), sess.Core.Agent().ModelName(), sess.Core.Agent().Name()))
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
@ -301,7 +301,7 @@ func (a *DBusAdapter) Submit(sessionID, prompt string) (bool, *dbus.Error) {
|
||||||
if sess == nil {
|
if sess == nil {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
go sess.Core.Submit(sess.Ctx, prompt)
|
go sess.Core.Agent().Submit(sess.Ctx, prompt)
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -314,7 +314,7 @@ func (a *DBusAdapter) ReactTo(sessionID, responseID, emoji string) (bool, *dbus.
|
||||||
if sess == nil {
|
if sess == nil {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
if err := sess.Core.ReactTo(responseID, emoji); err != nil {
|
if err := sess.Core.Agent().React(responseID, emoji); err != nil {
|
||||||
return false, dbus.MakeFailedError(err)
|
return false, dbus.MakeFailedError(err)
|
||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
|
|
@ -334,7 +334,7 @@ func (a *DBusAdapter) GetState(sessionID string) (string, *dbus.Error) {
|
||||||
if sess == nil {
|
if sess == nil {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
return sess.Core.State(), nil
|
return sess.Core.Agent().State(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *DBusAdapter) GetChat(sessionID string, offset int64) (string, int64, *dbus.Error) {
|
func (a *DBusAdapter) GetChat(sessionID string, offset int64) (string, int64, *dbus.Error) {
|
||||||
|
|
@ -361,7 +361,7 @@ func (a *DBusAdapter) GetUsage(sessionID string) (string, *dbus.Error) {
|
||||||
if sess == nil {
|
if sess == nil {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
return sess.Core.Usage(), nil
|
return sess.Core.Agent().UsageStr(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *DBusAdapter) GetCost(sessionID string) (string, *dbus.Error) {
|
func (a *DBusAdapter) GetCost(sessionID string) (string, *dbus.Error) {
|
||||||
|
|
@ -369,7 +369,7 @@ func (a *DBusAdapter) GetCost(sessionID string) (string, *dbus.Error) {
|
||||||
if sess == nil {
|
if sess == nil {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
return sess.Core.Cost(), nil
|
return sess.Core.Agent().CostStr(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *DBusAdapter) GetConfig(sessionID string) (string, *dbus.Error) {
|
func (a *DBusAdapter) GetConfig(sessionID string) (string, *dbus.Error) {
|
||||||
|
|
@ -378,11 +378,11 @@ func (a *DBusAdapter) GetConfig(sessionID string) (string, *dbus.Error) {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
fmt.Fprintf(&sb, "model=%s\n", sess.Core.ModelName())
|
fmt.Fprintf(&sb, "model=%s\n", sess.Core.Agent().ModelName())
|
||||||
fmt.Fprintf(&sb, "backend=%s\n", sess.Core.BackendName())
|
fmt.Fprintf(&sb, "backend=%s\n", sess.Core.Agent().BackendName())
|
||||||
fmt.Fprintf(&sb, "agent=%s\n", sess.Core.AgentName())
|
fmt.Fprintf(&sb, "agent=%s\n", sess.Core.Agent().Name())
|
||||||
fmt.Fprintf(&sb, "cwd=%s\n", sess.Core.CWD())
|
fmt.Fprintf(&sb, "cwd=%s\n", sess.Core.CWD())
|
||||||
fmt.Fprintf(&sb, "state=%s\n", sess.Core.State())
|
fmt.Fprintf(&sb, "state=%s\n", sess.Core.Agent().State())
|
||||||
return sb.String(), nil
|
return sb.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -393,7 +393,7 @@ func (a *DBusAdapter) SetConfig(sessionID, key, value string) (bool, *dbus.Error
|
||||||
}
|
}
|
||||||
switch key {
|
switch key {
|
||||||
case "model":
|
case "model":
|
||||||
sess.Core.Submit(sess.Ctx, "/model "+value)
|
sess.Core.Agent().Submit(sess.Ctx, "/model "+value)
|
||||||
case "cwd":
|
case "cwd":
|
||||||
if err := sess.Core.SetCWD(value); err != nil {
|
if err := sess.Core.SetCWD(value); err != nil {
|
||||||
return false, nil
|
return false, nil
|
||||||
|
|
@ -409,7 +409,7 @@ func (a *DBusAdapter) GetReactions(sessionID string) (string, *dbus.Error) {
|
||||||
if sess == nil {
|
if sess == nil {
|
||||||
return "{}", nil
|
return "{}", nil
|
||||||
}
|
}
|
||||||
data, err := json.Marshal(sess.Core.Reactions())
|
data, err := json.Marshal(sess.Core.Agent().Reactions())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", dbus.MakeFailedError(err)
|
return "", dbus.MakeFailedError(err)
|
||||||
}
|
}
|
||||||
|
|
@ -421,7 +421,7 @@ func (a *DBusAdapter) GetContext(sessionID string) (string, *dbus.Error) {
|
||||||
if sess == nil {
|
if sess == nil {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
msgs := sess.Core.Context()
|
msgs := sess.Core.Agent().Context()
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
enc := json.NewEncoder(&sb)
|
enc := json.NewEncoder(&sb)
|
||||||
enc.SetEscapeHTML(false)
|
enc.SetEscapeHTML(false)
|
||||||
|
|
@ -655,7 +655,7 @@ func (a *DBusAdapter) GetSystemPrompt(sessionID string) (string, *dbus.Error) {
|
||||||
if sess == nil {
|
if sess == nil {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
return sess.Core.SystemPrompt(), nil
|
return sess.Core.Agent().SystemPrompt(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *DBusAdapter) GetContextSize(sessionID string) (string, *dbus.Error) {
|
func (a *DBusAdapter) GetContextSize(sessionID string) (string, *dbus.Error) {
|
||||||
|
|
@ -663,7 +663,7 @@ func (a *DBusAdapter) GetContextSize(sessionID string) (string, *dbus.Error) {
|
||||||
if sess == nil {
|
if sess == nil {
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
return sess.Core.CtxSz(), nil
|
return sess.Core.Agent().CtxSz(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *DBusAdapter) GetPreviousPrompt(sessionID string) (string, *dbus.Error) {
|
func (a *DBusAdapter) GetPreviousPrompt(sessionID string) (string, *dbus.Error) {
|
||||||
|
|
@ -682,7 +682,7 @@ func (a *DBusAdapter) Compact(sessionID string) (bool, *dbus.Error) {
|
||||||
if sess == nil {
|
if sess == nil {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
sess.Core.Submit(sess.Ctx, "/compact")
|
sess.Core.Agent().Submit(sess.Ctx, "/compact")
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -691,7 +691,7 @@ func (a *DBusAdapter) ClearContext(sessionID string) (bool, *dbus.Error) {
|
||||||
if sess == nil {
|
if sess == nil {
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
sess.Core.Submit(sess.Ctx, "/clear")
|
sess.Core.Agent().Submit(sess.Ctx, "/clear")
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
34
main_test.go
34
main_test.go
|
|
@ -326,7 +326,7 @@ func TestSessionManagerInterruptAll(t *testing.T) {
|
||||||
defer sess.Cancel()
|
defer sess.Cancel()
|
||||||
|
|
||||||
// Submit in background to make it "running"
|
// Submit in background to make it "running"
|
||||||
go sess.Core.Submit(sess.Ctx, "hello")
|
go sess.Core.Agent().Submit(sess.Ctx, "hello")
|
||||||
time.Sleep(50 * time.Millisecond) // let it enter thinking state
|
time.Sleep(50 * time.Millisecond) // let it enter thinking state
|
||||||
s.AddSession(sess)
|
s.AddSession(sess)
|
||||||
|
|
||||||
|
|
@ -381,7 +381,7 @@ func TestSessionManagerRenameErrors(t *testing.T) {
|
||||||
}
|
}
|
||||||
// running
|
// running
|
||||||
sess := testBlockingSession("r")
|
sess := testBlockingSession("r")
|
||||||
go sess.Core.Submit(sess.Ctx, "hello")
|
go sess.Core.Agent().Submit(sess.Ctx, "hello")
|
||||||
time.Sleep(50 * time.Millisecond)
|
time.Sleep(50 * time.Millisecond)
|
||||||
s.AddSession(sess)
|
s.AddSession(sess)
|
||||||
if err := s.Tree().Rename("r", "r2"); err == nil {
|
if err := s.Tree().Rename("r", "r2"); err == nil {
|
||||||
|
|
@ -566,8 +566,8 @@ func TestSessionFileStoreWritePrompt(t *testing.T) {
|
||||||
testStoreWrite(t, sf, "prompt", []byte("hello agent"))
|
testStoreWrite(t, sf, "prompt", []byte("hello agent"))
|
||||||
// Verify state is back to idle (Submit completed)
|
// Verify state is back to idle (Submit completed)
|
||||||
time.Sleep(50 * time.Millisecond)
|
time.Sleep(50 * time.Millisecond)
|
||||||
if sess.Core.State() != "idle" {
|
if sess.Core.Agent().State() != "idle" {
|
||||||
t.Errorf("state = %q; want idle after submit", sess.Core.State())
|
t.Errorf("state = %q; want idle after submit", sess.Core.Agent().State())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -577,7 +577,7 @@ func TestSessionFileStoreWriteFifoIn(t *testing.T) {
|
||||||
sf := newTestSessionFileStore(t, sess)
|
sf := newTestSessionFileStore(t, sess)
|
||||||
|
|
||||||
testStoreWrite(t, sf, "fifo.in", []byte("inject this"))
|
testStoreWrite(t, sf, "fifo.in", []byte("inject this"))
|
||||||
item, ok := sess.Core.PopQueue()
|
item, ok := sess.Core.Agent().PopQueue()
|
||||||
if !ok || item != "inject this" {
|
if !ok || item != "inject this" {
|
||||||
t.Errorf("PopQueue() = %q, %v; want inject this, true", item, ok)
|
t.Errorf("PopQueue() = %q, %v; want inject this, true", item, ok)
|
||||||
}
|
}
|
||||||
|
|
@ -606,14 +606,14 @@ func TestSessionFileStoreWriteBackendModelAgent(t *testing.T) {
|
||||||
// With real session + NewBackend func, it switches backend
|
// With real session + NewBackend func, it switches backend
|
||||||
testStoreWrite(t, sf, "cfg", []byte("backend=openai"))
|
testStoreWrite(t, sf, "cfg", []byte("backend=openai"))
|
||||||
time.Sleep(50 * time.Millisecond)
|
time.Sleep(50 * time.Millisecond)
|
||||||
if sess.Core.BackendName() != "openai" {
|
if sess.Core.Agent().BackendName() != "openai" {
|
||||||
t.Errorf("BackendName() = %q; want openai", sess.Core.BackendName())
|
t.Errorf("BackendName() = %q; want openai", sess.Core.Agent().BackendName())
|
||||||
}
|
}
|
||||||
|
|
||||||
testStoreWrite(t, sf, "cfg", []byte("model=gpt-4"))
|
testStoreWrite(t, sf, "cfg", []byte("model=gpt-4"))
|
||||||
time.Sleep(50 * time.Millisecond)
|
time.Sleep(50 * time.Millisecond)
|
||||||
if sess.Core.ModelName() != "gpt-4" {
|
if sess.Core.Agent().ModelName() != "gpt-4" {
|
||||||
t.Errorf("ModelName() = %q; want gpt-4", sess.Core.ModelName())
|
t.Errorf("ModelName() = %q; want gpt-4", sess.Core.Agent().ModelName())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -622,7 +622,7 @@ func TestSessionFileStoreWriteBackendWhileRunning(t *testing.T) {
|
||||||
defer sess.Cancel()
|
defer sess.Cancel()
|
||||||
|
|
||||||
// Make session running
|
// Make session running
|
||||||
go sess.Core.Submit(sess.Ctx, "hello")
|
go sess.Core.Agent().Submit(sess.Ctx, "hello")
|
||||||
time.Sleep(50 * time.Millisecond)
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
|
||||||
sf := newTestSessionFileStore(t, sess)
|
sf := newTestSessionFileStore(t, sess)
|
||||||
|
|
@ -647,7 +647,7 @@ func TestSessionFileStoreWriteParams(t *testing.T) {
|
||||||
sf := newTestSessionFileStore(t, sess)
|
sf := newTestSessionFileStore(t, sess)
|
||||||
|
|
||||||
testStoreWrite(t, sf, "cfg", []byte("maxTokens=2048"))
|
testStoreWrite(t, sf, "cfg", []byte("maxTokens=2048"))
|
||||||
p := sess.Core.GenerationParams()
|
p := sess.Core.Agent().GenParams()
|
||||||
if p.MaxTokens != 2048 {
|
if p.MaxTokens != 2048 {
|
||||||
t.Errorf("MaxTokens = %d; want 2048", p.MaxTokens)
|
t.Errorf("MaxTokens = %d; want 2048", p.MaxTokens)
|
||||||
}
|
}
|
||||||
|
|
@ -657,7 +657,7 @@ func TestSessionFileStoreWriteParamsWhileRunning(t *testing.T) {
|
||||||
sess := testBlockingSession("s1")
|
sess := testBlockingSession("s1")
|
||||||
defer sess.Cancel()
|
defer sess.Cancel()
|
||||||
|
|
||||||
go sess.Core.Submit(sess.Ctx, "hello")
|
go sess.Core.Agent().Submit(sess.Ctx, "hello")
|
||||||
time.Sleep(50 * time.Millisecond)
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
|
||||||
sf := newTestSessionFileStore(t, sess)
|
sf := newTestSessionFileStore(t, sess)
|
||||||
|
|
@ -673,7 +673,7 @@ func TestSessionFileStoreHandleCtl(t *testing.T) {
|
||||||
defer sess.Cancel()
|
defer sess.Cancel()
|
||||||
|
|
||||||
// Make session running for interrupt test
|
// Make session running for interrupt test
|
||||||
go sess.Core.Submit(sess.Ctx, "hello")
|
go sess.Core.Agent().Submit(sess.Ctx, "hello")
|
||||||
time.Sleep(50 * time.Millisecond)
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
|
||||||
sf := newTestSessionFileStore(t, sess)
|
sf := newTestSessionFileStore(t, sess)
|
||||||
|
|
@ -681,7 +681,7 @@ func TestSessionFileStoreHandleCtl(t *testing.T) {
|
||||||
// stop — interrupts the running session
|
// stop — interrupts the running session
|
||||||
testStoreWrite(t, sf, "ctl", []byte("stop"))
|
testStoreWrite(t, sf, "ctl", []byte("stop"))
|
||||||
time.Sleep(50 * time.Millisecond)
|
time.Sleep(50 * time.Millisecond)
|
||||||
if sess.Core.IsRunning() {
|
if sess.Core.Agent().IsRunning() {
|
||||||
t.Error("ctl stop should interrupt (session should not be running)")
|
t.Error("ctl stop should interrupt (session should not be running)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -730,7 +730,7 @@ func TestSessionFileStoreBlockingRead(t *testing.T) {
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
||||||
// Submit triggers state change: idle → thinking
|
// Submit triggers state change: idle → thinking
|
||||||
go sess.Core.Submit(sess.Ctx, "trigger")
|
go sess.Core.Agent().Submit(sess.Ctx, "trigger")
|
||||||
|
|
||||||
select {
|
select {
|
||||||
case v := <-done:
|
case v := <-done:
|
||||||
|
|
@ -1067,12 +1067,12 @@ func TestSessionInterrupt(t *testing.T) {
|
||||||
sess := testBlockingSession("s1")
|
sess := testBlockingSession("s1")
|
||||||
defer sess.Cancel()
|
defer sess.Cancel()
|
||||||
|
|
||||||
go sess.Core.Submit(sess.Ctx, "hello")
|
go sess.Core.Agent().Submit(sess.Ctx, "hello")
|
||||||
time.Sleep(50 * time.Millisecond)
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
|
||||||
sess.Interrupt()
|
sess.Interrupt()
|
||||||
time.Sleep(50 * time.Millisecond)
|
time.Sleep(50 * time.Millisecond)
|
||||||
if sess.Core.IsRunning() {
|
if sess.Core.Agent().IsRunning() {
|
||||||
t.Error("session should not be running after interrupt")
|
t.Error("session should not be running after interrupt")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -241,10 +241,10 @@ func (s *Manager) CreateSession(args []string) (string, error) {
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
|
|
||||||
// HACK: Load the agent now that the session mount is active.
|
// HACK: Load the agent now that the session mount is active.
|
||||||
core.Submit(ctx, "/agent "+agentName)
|
core.Agent().Submit(ctx, "/agent "+agentName)
|
||||||
|
|
||||||
s.cfg.Log.Info("new session %s (backend=%s model=%s agent=%s)",
|
s.cfg.Log.Info("new session %s (backend=%s model=%s agent=%s)",
|
||||||
sessID, core.BackendName(), core.ModelName(), core.AgentName())
|
sessID, core.Agent().BackendName(), core.Agent().ModelName(), core.Agent().Name())
|
||||||
if s.cfg.OnSessionCreated != nil {
|
if s.cfg.OnSessionCreated != nil {
|
||||||
s.cfg.OnSessionCreated(sessID, sess)
|
s.cfg.OnSessionCreated(sessID, sess)
|
||||||
}
|
}
|
||||||
|
|
@ -271,7 +271,7 @@ func (s *Manager) renameSession(old, new string) error {
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
return fmt.Errorf("session already exists: %s", newID)
|
return fmt.Errorf("session already exists: %s", newID)
|
||||||
}
|
}
|
||||||
if sess.Core.IsRunning() {
|
if sess.Core.Agent().IsRunning() {
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
return fmt.Errorf("cannot rename while agent is running")
|
return fmt.Errorf("cannot rename while agent is running")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -286,7 +286,7 @@ func (s *Manager) PeerSubmit(sessID, peerID, prompt string) error {
|
||||||
if !isPeer {
|
if !isPeer {
|
||||||
return fmt.Errorf("%s is not a peer of %s", peerID, sessID)
|
return fmt.Errorf("%s is not a peer of %s", peerID, sessID)
|
||||||
}
|
}
|
||||||
go peer.Core.Submit(peer.Ctx, prompt)
|
go peer.Core.Agent().Submit(peer.Ctx, prompt)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -291,7 +291,7 @@ func (s *Manager) waitIdle(poll, timeout time.Duration) {
|
||||||
allIdle := true
|
allIdle := true
|
||||||
s.mu.RLock()
|
s.mu.RLock()
|
||||||
for _, sess := range s.sessions {
|
for _, sess := range s.sessions {
|
||||||
if sess.Core.State() != "idle" {
|
if sess.Core.Agent().State() != "idle" {
|
||||||
allIdle = false
|
allIdle = false
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
@ -332,11 +332,11 @@ func (s *Manager) index() []byte {
|
||||||
for _, id := range ids {
|
for _, id := range ids {
|
||||||
sess := s.sessions[id]
|
sess := s.sessions[id]
|
||||||
sess.mu.RLock()
|
sess.mu.RLock()
|
||||||
state := sess.Core.State()
|
state := sess.Core.Agent().State()
|
||||||
cwd := sess.Core.CWD()
|
cwd := sess.Core.CWD()
|
||||||
be := sess.Core.BackendName()
|
be := sess.Core.Agent().BackendName()
|
||||||
model := sess.Core.ModelName()
|
model := sess.Core.Agent().ModelName()
|
||||||
agent := sess.Core.AgentName()
|
agent := sess.Core.Agent().Name()
|
||||||
sess.mu.RUnlock()
|
sess.mu.RUnlock()
|
||||||
fmt.Fprintf(&sb, "%s\t%s\t%s\t%s\t%s\t%s\n", id, state, cwd, be, model, agent)
|
fmt.Fprintf(&sb, "%s\t%s\t%s\t%s\t%s\t%s\n", id, state, cwd, be, model, agent)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ package mgr
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"sync"
|
"sync"
|
||||||
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"ollie/session"
|
"ollie/session"
|
||||||
|
|
@ -53,7 +54,8 @@ func (sess *Session) CachedListModels() string {
|
||||||
sess.modelsMu.Unlock()
|
sess.modelsMu.Unlock()
|
||||||
|
|
||||||
// Cache miss — fetch and store.
|
// Cache miss — fetch and store.
|
||||||
result := sess.Core.ListModels()
|
models := sess.Core.Agent().ListModels()
|
||||||
|
result := strings.Join(models, "\n")
|
||||||
sess.modelsMu.Lock()
|
sess.modelsMu.Lock()
|
||||||
sess.modelsCache = result
|
sess.modelsCache = result
|
||||||
sess.modelsCacheAt = time.Now()
|
sess.modelsCacheAt = time.Now()
|
||||||
|
|
|
||||||
|
|
@ -129,7 +129,7 @@ func (h *sessionHelper) fileSpec(name string, mode os.FileMode) fs.FileSpec {
|
||||||
}
|
}
|
||||||
case "reactions":
|
case "reactions":
|
||||||
fs.Read = func() ([]byte, error) {
|
fs.Read = func() ([]byte, error) {
|
||||||
data, err := json.Marshal(h.sess.Core.Reactions())
|
data, err := json.Marshal(h.sess.Core.Agent().Reactions())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -151,7 +151,7 @@ func (h *sessionHelper) fileSpec(name string, mode os.FileMode) fs.FileSpec {
|
||||||
}
|
}
|
||||||
case "fifo.out":
|
case "fifo.out":
|
||||||
fs.Read = func() ([]byte, error) {
|
fs.Read = func() ([]byte, error) {
|
||||||
item, ok := h.sess.Core.PopQueue()
|
item, ok := h.sess.Core.Agent().PopQueue()
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
@ -203,7 +203,7 @@ func (h *sessionHelper) fileSpec(name string, mode os.FileMode) fs.FileSpec {
|
||||||
h.sess.prevPrompt = []byte(input)
|
h.sess.prevPrompt = []byte(input)
|
||||||
h.sess.mu.Unlock()
|
h.sess.mu.Unlock()
|
||||||
go func() {
|
go func() {
|
||||||
h.sess.Core.Submit(h.sess.Ctx, input)
|
h.sess.Core.Agent().Submit(h.sess.Ctx, input)
|
||||||
h.sess.EnsureTrailingNewline()
|
h.sess.EnsureTrailingNewline()
|
||||||
}()
|
}()
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -264,7 +264,7 @@ func (h *sessionHelper) fileSpec(name string, mode os.FileMode) fs.FileSpec {
|
||||||
if req.Emoji == "" {
|
if req.Emoji == "" {
|
||||||
return fmt.Errorf("react: emoji is required")
|
return fmt.Errorf("react: emoji is required")
|
||||||
}
|
}
|
||||||
return h.sess.Core.ReactTo(req.ResponseID, req.Emoji)
|
return h.sess.Core.Agent().React(req.ResponseID, req.Emoji)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -275,11 +275,11 @@ func (h *sessionHelper) fileSpec(name string, mode os.FileMode) fs.FileSpec {
|
||||||
defer cancel()
|
defer cancel()
|
||||||
context.AfterFunc(h.sess.Ctx, cancel)
|
context.AfterFunc(h.sess.Ctx, cancel)
|
||||||
if base == "" {
|
if base == "" {
|
||||||
base = h.sess.Core.State()
|
base = h.sess.Core.Agent().State()
|
||||||
}
|
}
|
||||||
v, ok := h.sess.Core.WaitChange(ctx, agent.WatchState, base)
|
v, ok := h.sess.Core.WaitChange(ctx, agent.WatchState, base)
|
||||||
if !ok {
|
if !ok {
|
||||||
s := h.sess.Core.State()
|
s := h.sess.Core.Agent().State()
|
||||||
return []byte(s + "\n"), s, nil
|
return []byte(s + "\n"), s, nil
|
||||||
}
|
}
|
||||||
return []byte(v + "\n"), v, nil
|
return []byte(v + "\n"), v, nil
|
||||||
|
|
@ -294,18 +294,18 @@ func (h *sessionHelper) content(name string) string {
|
||||||
defer h.sess.mu.RUnlock()
|
defer h.sess.mu.RUnlock()
|
||||||
switch name {
|
switch name {
|
||||||
case "usage":
|
case "usage":
|
||||||
return h.sess.Core.Usage() + "\n"
|
return h.sess.Core.Agent().UsageStr() + "\n"
|
||||||
case "cost":
|
case "cost":
|
||||||
return h.sess.Core.Cost()
|
return h.sess.Core.Agent().CostStr()
|
||||||
case "ctxsz":
|
case "ctxsz":
|
||||||
return h.sess.Core.CtxSz() + "\n"
|
return h.sess.Core.Agent().CtxSz() + "\n"
|
||||||
case "models":
|
case "models":
|
||||||
h.log.Debug("content(models) called")
|
h.log.Debug("content(models) called")
|
||||||
return h.sess.CachedListModels() + "\n"
|
return h.sess.CachedListModels() + "\n"
|
||||||
case "systemprompt":
|
case "systemprompt":
|
||||||
return h.sess.Core.SystemPrompt()
|
return h.sess.Core.Agent().SystemPrompt()
|
||||||
case "state":
|
case "state":
|
||||||
return h.sess.Core.State() + "\n"
|
return h.sess.Core.Agent().State() + "\n"
|
||||||
case "offset":
|
case "offset":
|
||||||
return fmt.Sprintf("%d\n", h.sess.ChatOffset)
|
return fmt.Sprintf("%d\n", h.sess.ChatOffset)
|
||||||
case "env":
|
case "env":
|
||||||
|
|
@ -316,7 +316,7 @@ func (h *sessionHelper) content(name string) string {
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
enc := json.NewEncoder(&sb)
|
enc := json.NewEncoder(&sb)
|
||||||
enc.SetEscapeHTML(false)
|
enc.SetEscapeHTML(false)
|
||||||
for _, m := range h.sess.Core.Context() {
|
for _, m := range h.sess.Core.Agent().Context() {
|
||||||
enc.Encode(m)
|
enc.Encode(m)
|
||||||
}
|
}
|
||||||
return sb.String()
|
return sb.String()
|
||||||
|
|
@ -374,12 +374,12 @@ func (h *sessionHelper) envContent() string {
|
||||||
func (h *sessionHelper) cfgContent() string {
|
func (h *sessionHelper) cfgContent() string {
|
||||||
h.sess.mu.RLock()
|
h.sess.mu.RLock()
|
||||||
defer h.sess.mu.RUnlock()
|
defer h.sess.mu.RUnlock()
|
||||||
p := h.sess.Core.GenerationParams()
|
p := h.sess.Core.Agent().GenParams()
|
||||||
var sb strings.Builder
|
var sb strings.Builder
|
||||||
fmt.Fprintf(&sb, "name=%s\n", h.sess.id)
|
fmt.Fprintf(&sb, "name=%s\n", h.sess.id)
|
||||||
fmt.Fprintf(&sb, "backend=%s\n", h.sess.Core.BackendName())
|
fmt.Fprintf(&sb, "backend=%s\n", h.sess.Core.Agent().BackendName())
|
||||||
fmt.Fprintf(&sb, "model=%s\n", h.sess.Core.ModelName())
|
fmt.Fprintf(&sb, "model=%s\n", h.sess.Core.Agent().ModelName())
|
||||||
fmt.Fprintf(&sb, "agent=%s\n", h.sess.Core.AgentName())
|
fmt.Fprintf(&sb, "agent=%s\n", h.sess.Core.Agent().Name())
|
||||||
fmt.Fprintf(&sb, "cwd=%s\n", h.sess.Core.CWD())
|
fmt.Fprintf(&sb, "cwd=%s\n", h.sess.Core.CWD())
|
||||||
fmt.Fprintf(&sb, "remote=%s\n", h.sess.remote)
|
fmt.Fprintf(&sb, "remote=%s\n", h.sess.remote)
|
||||||
fmt.Fprintf(&sb, "maxTokens=%d\n", p.MaxTokens)
|
fmt.Fprintf(&sb, "maxTokens=%d\n", p.MaxTokens)
|
||||||
|
|
@ -450,12 +450,12 @@ func (h *sessionHelper) cfgContent() string {
|
||||||
} else {
|
} else {
|
||||||
sb.WriteString("verbosity=\n")
|
sb.WriteString("verbosity=\n")
|
||||||
}
|
}
|
||||||
fmt.Fprintf(&sb, "compactionModel=%s\n", h.sess.Core.CompactionModel())
|
fmt.Fprintf(&sb, "compactionModel=%s\n", h.sess.Core.Agent().CompactionModel())
|
||||||
return sb.String()
|
return sb.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *sessionHelper) handleCfg(input string) error {
|
func (h *sessionHelper) handleCfg(input string) error {
|
||||||
p := h.sess.Core.GenerationParams()
|
p := h.sess.Core.Agent().GenParams()
|
||||||
hasParams := false
|
hasParams := false
|
||||||
var deferredBackend, deferredModel string
|
var deferredBackend, deferredModel string
|
||||||
for _, line := range strings.Split(input, "\n") {
|
for _, line := range strings.Split(input, "\n") {
|
||||||
|
|
@ -473,7 +473,7 @@ func (h *sessionHelper) handleCfg(input string) error {
|
||||||
if v == "" {
|
if v == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if h.sess.Core.IsRunning() {
|
if h.sess.Core.Agent().IsRunning() {
|
||||||
return fmt.Errorf("cannot rename while agent is running")
|
return fmt.Errorf("cannot rename while agent is running")
|
||||||
}
|
}
|
||||||
if err := h.rename(v); err != nil {
|
if err := h.rename(v); err != nil {
|
||||||
|
|
@ -483,15 +483,15 @@ func (h *sessionHelper) handleCfg(input string) error {
|
||||||
if v == "" {
|
if v == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if h.sess.Core.IsRunning() {
|
if h.sess.Core.Agent().IsRunning() {
|
||||||
return fmt.Errorf("cannot switch %s while agent is running", k)
|
return fmt.Errorf("cannot switch %s while agent is running", k)
|
||||||
}
|
}
|
||||||
h.sess.Core.Submit(h.sess.Ctx, "/agent "+v)
|
h.sess.Core.Agent().Submit(h.sess.Ctx, "/agent "+v)
|
||||||
case "backend", "model":
|
case "backend", "model":
|
||||||
if v == "" {
|
if v == "" {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if h.sess.Core.IsRunning() {
|
if h.sess.Core.Agent().IsRunning() {
|
||||||
return fmt.Errorf("cannot switch %s while agent is running", k)
|
return fmt.Errorf("cannot switch %s while agent is running", k)
|
||||||
}
|
}
|
||||||
// Defer backend/model until after the loop so they override
|
// Defer backend/model until after the loop so they override
|
||||||
|
|
@ -610,22 +610,22 @@ func (h *sessionHelper) handleCfg(input string) error {
|
||||||
hasParams = true
|
hasParams = true
|
||||||
p.Verbosity = v
|
p.Verbosity = v
|
||||||
case "compactionModel":
|
case "compactionModel":
|
||||||
h.sess.Core.SetCompactionModel(v)
|
h.sess.Core.Agent().SetCompactionModel(v)
|
||||||
// state → read-only, silently ignored
|
// state → read-only, silently ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Apply backend/model after agent= so manual overrides win.
|
// Apply backend/model after agent= so manual overrides win.
|
||||||
if deferredBackend != "" {
|
if deferredBackend != "" {
|
||||||
h.sess.Core.Submit(h.sess.Ctx, "/backend "+deferredBackend)
|
h.sess.Core.Agent().Submit(h.sess.Ctx, "/backend "+deferredBackend)
|
||||||
}
|
}
|
||||||
if deferredModel != "" {
|
if deferredModel != "" {
|
||||||
h.sess.Core.Submit(h.sess.Ctx, "/model "+deferredModel)
|
h.sess.Core.Agent().Submit(h.sess.Ctx, "/model "+deferredModel)
|
||||||
}
|
}
|
||||||
if hasParams {
|
if hasParams {
|
||||||
if h.sess.Core.IsRunning() {
|
if h.sess.Core.Agent().IsRunning() {
|
||||||
return fmt.Errorf("cannot change params while agent is running")
|
return fmt.Errorf("cannot change params while agent is running")
|
||||||
}
|
}
|
||||||
return h.sess.Core.SetGenerationParams(p)
|
h.sess.Core.Agent().SetGenParams(p)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -680,7 +680,7 @@ func (h *sessionHelper) handleCtl(input string) error {
|
||||||
"agents", "agent", "sessions", "cwd", "skills",
|
"agents", "agent", "sessions", "cwd", "skills",
|
||||||
"tools", "context", "usage", "cost", "history",
|
"tools", "context", "usage", "cost", "history",
|
||||||
"irw", "help":
|
"irw", "help":
|
||||||
h.sess.Core.Submit(h.sess.Ctx, "/"+input)
|
h.sess.Core.Agent().Submit(h.sess.Ctx, "/"+input)
|
||||||
default:
|
default:
|
||||||
return fmt.Errorf("unknown ctl command: %s", cmd[0])
|
return fmt.Errorf("unknown ctl command: %s", cmd[0])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
Reference in New Issue