agent: rename receiver s → a for clarity
The agent struct receiver was historically 's' (from when it was called 'session'). Now that session is a separate concept, rename to 'a' to match the type name.
This commit is contained in:
parent
6396167361
commit
23de2e8267
|
|
@ -12,7 +12,7 @@ import (
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *agent) handleCommand(ctx context.Context, input string) bool {
|
func (a *agent) handleCommand(ctx context.Context, input string) bool {
|
||||||
if !strings.HasPrefix(input, "/") {
|
if !strings.HasPrefix(input, "/") {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
@ -25,9 +25,9 @@ func (s *agent) handleCommand(ctx context.Context, input string) bool {
|
||||||
args := parts[1:]
|
args := parts[1:]
|
||||||
|
|
||||||
listFromHandler := func(name string) {
|
listFromHandler := func(name string) {
|
||||||
if h := s.listHandlers[name]; h != nil {
|
if h := a.listHandlers[name]; h != nil {
|
||||||
for _, item := range h() {
|
for _, item := range h() {
|
||||||
s.emit(infoEvent(" " + item))
|
a.emit(infoEvent(" " + item))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -37,88 +37,88 @@ func (s *agent) handleCommand(ctx context.Context, input string) bool {
|
||||||
"/i": func(args []string) {
|
"/i": func(args []string) {
|
||||||
prompt := strings.Join(args, " ")
|
prompt := strings.Join(args, " ")
|
||||||
if prompt == "" {
|
if prompt == "" {
|
||||||
s.emit(infoEvent("error: /i requires a prompt"))
|
a.emit(infoEvent("error: /i requires a prompt"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if s.IsRunning() {
|
if a.IsRunning() {
|
||||||
s.Inject(prompt)
|
a.Inject(prompt)
|
||||||
} else {
|
} else {
|
||||||
go s.Submit(context.Background(), prompt)
|
go a.Submit(context.Background(), prompt)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"/irw": func(args []string) {
|
"/irw": func(args []string) {
|
||||||
prompt := strings.Join(args, " ")
|
prompt := strings.Join(args, " ")
|
||||||
if prompt == "" {
|
if prompt == "" {
|
||||||
s.emit(infoEvent("error: /irw requires a prompt"))
|
a.emit(infoEvent("error: /irw requires a prompt"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.injectRewrite(prompt)
|
a.injectRewrite(prompt)
|
||||||
},
|
},
|
||||||
|
|
||||||
"/backend": func(args []string) {
|
"/backend": func(args []string) {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
s.emit(infoEvent(s.runtime.Backend.Name()))
|
a.emit(infoEvent(a.runtime.Backend.Name()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if s.IsRunning() {
|
if a.IsRunning() {
|
||||||
s.emit(infoEvent("error: cannot switch backend while agent is running"))
|
a.emit(infoEvent("error: cannot switch backend while agent is running"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
be, err := s.newBackend(args[0])
|
be, err := a.newBackend(args[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.emit(infoEvent(fmt.Sprintf("error: failed to switch backend: %v", err)))
|
a.emit(infoEvent(fmt.Sprintf("error: failed to switch backend: %v", err)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.runtime.Backend = be
|
a.runtime.Backend = be
|
||||||
s.emit(infoEvent(fmt.Sprintf("switched backend to: %s (model: %s)", be.Name(), be.Model())))
|
a.emit(infoEvent(fmt.Sprintf("switched backend to: %s (model: %s)", be.Name(), be.Model())))
|
||||||
},
|
},
|
||||||
|
|
||||||
"/models": func(args []string) {
|
"/models": func(args []string) {
|
||||||
models := s.runtime.Backend.Models(ctx)
|
models := a.runtime.Backend.Models(ctx)
|
||||||
if len(models) == 0 {
|
if len(models) == 0 {
|
||||||
s.emit(infoEvent("no models available"))
|
a.emit(infoEvent("no models available"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
slices.Sort(models)
|
slices.Sort(models)
|
||||||
current := s.runtime.Backend.Model()
|
current := a.runtime.Backend.Model()
|
||||||
for _, m := range models {
|
for _, m := range models {
|
||||||
marker := " "
|
marker := " "
|
||||||
if m == current {
|
if m == current {
|
||||||
marker = "* "
|
marker = "* "
|
||||||
}
|
}
|
||||||
s.emit(infoEvent(marker + m))
|
a.emit(infoEvent(marker + m))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"/model": func(args []string) {
|
"/model": func(args []string) {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
s.emit(infoEvent(s.runtime.Backend.Model()))
|
a.emit(infoEvent(a.runtime.Backend.Model()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.runtime.Backend.SetModel(args[0])
|
a.runtime.Backend.SetModel(args[0])
|
||||||
s.emit(infoEvent("switched model to: " + args[0]))
|
a.emit(infoEvent("switched model to: " + args[0]))
|
||||||
},
|
},
|
||||||
|
|
||||||
"/maxsteps": func(args []string) {
|
"/maxsteps": func(args []string) {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
if s.runtime.MaxSteps == 0 {
|
if a.runtime.MaxSteps == 0 {
|
||||||
s.emit(infoEvent("maxsteps: unlimited"))
|
a.emit(infoEvent("maxsteps: unlimited"))
|
||||||
} else {
|
} else {
|
||||||
s.emit(infoEvent(fmt.Sprintf("maxsteps: %d", s.runtime.MaxSteps)))
|
a.emit(infoEvent(fmt.Sprintf("maxsteps: %d", a.runtime.MaxSteps)))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
n, err := strconv.Atoi(args[0])
|
n, err := strconv.Atoi(args[0])
|
||||||
if err != nil || n < 0 {
|
if err != nil || n < 0 {
|
||||||
s.emit(infoEvent("error: maxsteps requires a non-negative integer (0 = unlimited)"))
|
a.emit(infoEvent("error: maxsteps requires a non-negative integer (0 = unlimited)"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.runtime.MaxSteps = n
|
a.runtime.MaxSteps = n
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
s.emit(infoEvent("maxsteps: unlimited"))
|
a.emit(infoEvent("maxsteps: unlimited"))
|
||||||
} else {
|
} else {
|
||||||
s.emit(infoEvent(fmt.Sprintf("maxsteps: %d", n)))
|
a.emit(infoEvent(fmt.Sprintf("maxsteps: %d", n)))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -140,48 +140,48 @@ func (s *agent) handleCommand(ctx context.Context, input string) bool {
|
||||||
}
|
}
|
||||||
seen[name] = true
|
seen[name] = true
|
||||||
marker := " "
|
marker := " "
|
||||||
if name == s.agentName {
|
if name == a.agentName {
|
||||||
marker = "* "
|
marker = "* "
|
||||||
}
|
}
|
||||||
s.emit(infoEvent(marker + name))
|
a.emit(infoEvent(marker + name))
|
||||||
found = true
|
found = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
s.emit(infoEvent("no agents found"))
|
a.emit(infoEvent("no agents found"))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"/agent": func(args []string) {
|
"/agent": func(args []string) {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
s.emit(infoEvent("active agent: " + s.agentName))
|
a.emit(infoEvent("active agent: " + a.agentName))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if s.IsRunning() {
|
if a.IsRunning() {
|
||||||
s.emit(infoEvent("error: cannot switch agent while agent is running"))
|
a.emit(infoEvent("error: cannot switch agent while agent is running"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
name := args[0]
|
name := args[0]
|
||||||
cfgPath := AgentConfigPath(s.agentsDir, name)
|
cfgPath := AgentConfigPath(a.agentsDir, name)
|
||||||
f, err := os.Open(cfgPath)
|
f, err := os.Open(cfgPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.emit(infoEvent(fmt.Sprintf("error: agent %q: %v", name, err)))
|
a.emit(infoEvent(fmt.Sprintf("error: agent %q: %v", name, err)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cfg, err := Load(f)
|
cfg, err := Load(f)
|
||||||
f.Close()
|
f.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.emit(infoEvent(fmt.Sprintf("error: agent %q: %v", name, err)))
|
a.emit(infoEvent(fmt.Sprintf("error: agent %q: %v", name, err)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
d := s.newDispatcher()
|
d := a.newDispatcher()
|
||||||
env := []string{"OLLIE_SESSION_ID=" + s.sess.ID(), "OLLIE_UNAME=" + s.sess.Uname()}
|
env := []string{"OLLIE_SESSION_ID=" + a.sess.ID(), "OLLIE_UNAME=" + a.sess.Uname()}
|
||||||
env = append(env, s.promptEnvExtra...)
|
env = append(env, a.promptEnvExtra...)
|
||||||
rt := BuildRuntime(cfg, d, s.sess.CWD(), env, s.baseLayers...)
|
rt := BuildRuntime(cfg, d, a.sess.CWD(), env, a.baseLayers...)
|
||||||
if rt.CfgBackend != "" {
|
if rt.CfgBackend != "" {
|
||||||
newBe, err := s.newBackend(rt.CfgBackend)
|
newBe, err := a.newBackend(rt.CfgBackend)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.emit(infoEvent(fmt.Sprintf("error: backend %q: %v", rt.CfgBackend, err)))
|
a.emit(infoEvent(fmt.Sprintf("error: backend %q: %v", rt.CfgBackend, err)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if rt.CfgModel != "" {
|
if rt.CfgModel != "" {
|
||||||
|
|
@ -189,47 +189,47 @@ func (s *agent) handleCommand(ctx context.Context, input string) bool {
|
||||||
}
|
}
|
||||||
rt.Backend = newBe
|
rt.Backend = newBe
|
||||||
} else {
|
} else {
|
||||||
rt.Backend = s.runtime.Backend
|
rt.Backend = a.runtime.Backend
|
||||||
if rt.CfgModel != "" {
|
if rt.CfgModel != "" {
|
||||||
rt.Backend.SetModel(rt.CfgModel)
|
rt.Backend.SetModel(rt.CfgModel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.runtime = rt
|
a.runtime = rt
|
||||||
s.agentName = name
|
a.agentName = name
|
||||||
s.history = nil
|
a.history = nil
|
||||||
s.pushSessionEnv()
|
a.pushSessionEnv()
|
||||||
s.notifyChange()
|
a.notifyChange()
|
||||||
for _, msg := range rt.Messages {
|
for _, msg := range rt.Messages {
|
||||||
s.emit(infoEvent(msg))
|
a.emit(infoEvent(msg))
|
||||||
}
|
}
|
||||||
s.emit(infoEvent("agent: " + name))
|
a.emit(infoEvent("agent: " + name))
|
||||||
},
|
},
|
||||||
|
|
||||||
"/compact": func(args []string) {
|
"/compact": func(args []string) {
|
||||||
if s.IsRunning() {
|
if a.IsRunning() {
|
||||||
s.emit(infoEvent("error: cannot compact while agent is running"))
|
a.emit(infoEvent("error: cannot compact while agent is running"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if s.history == nil {
|
if a.history == nil {
|
||||||
s.emit(infoEvent("nothing to compact"))
|
a.emit(infoEvent("nothing to compact"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
snapshot := s.history.PreCompactionSnapshot()
|
snapshot := a.history.PreCompactionSnapshot()
|
||||||
s.setState("compacting")
|
a.setState("compacting")
|
||||||
n, err := s.runCompact(ctx, "manual")
|
n, err := a.runCompact(ctx, "manual")
|
||||||
s.setState("idle")
|
a.setState("idle")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.emit(infoEvent("compact error: " + err.Error()))
|
a.emit(infoEvent("compact error: " + err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if n == 0 {
|
if n == 0 {
|
||||||
s.emit(infoEvent("nothing to compact"))
|
a.emit(infoEvent("nothing to compact"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if s.sessionsDir != "" && s.sess.ID() != "" {
|
if a.sessionsDir != "" && a.sess.ID() != "" {
|
||||||
histPath := s.activeSessionPath(s.sess.ID(), ".compaction.jsonl")
|
histPath := a.activeSessionPath(a.sess.ID(), ".compaction.jsonl")
|
||||||
if err := os.MkdirAll(filepath.Dir(histPath), 0700); err != nil {
|
if err := os.MkdirAll(filepath.Dir(histPath), 0700); err != nil {
|
||||||
s.emit(infoEvent("compaction history save: " + err.Error()))
|
a.emit(infoEvent("compaction history save: " + err.Error()))
|
||||||
} else if data, err := json.Marshal(snapshot); err == nil {
|
} else if data, err := json.Marshal(snapshot); err == nil {
|
||||||
f, err := os.OpenFile(histPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
|
f, err := os.OpenFile(histPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
@ -238,76 +238,76 @@ func (s *agent) handleCommand(ctx context.Context, input string) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.emit(infoEvent(fmt.Sprintf("compacted %d messages", n)))
|
a.emit(infoEvent(fmt.Sprintf("compacted %d messages", n)))
|
||||||
s.saveSession()
|
a.saveSession()
|
||||||
},
|
},
|
||||||
|
|
||||||
"/context": func(args []string) {
|
"/context": func(args []string) {
|
||||||
if s.history == nil {
|
if a.history == nil {
|
||||||
s.emit(infoEvent("no active session"))
|
a.emit(infoEvent("no active session"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctxLen := s.runtime.Backend.ContextLength(ctx)
|
ctxLen := a.runtime.Backend.ContextLength(ctx)
|
||||||
if ctxLen <= 0 {
|
if ctxLen <= 0 {
|
||||||
ctxLen = defaultContextLength
|
ctxLen = defaultContextLength
|
||||||
}
|
}
|
||||||
estimated := s.history.estimateTokens()
|
estimated := a.history.estimateTokens()
|
||||||
pct := estimated * 100 / ctxLen
|
pct := estimated * 100 / ctxLen
|
||||||
s.emit(infoEvent(fmt.Sprintf("~%d / %d tokens (%d%%)", estimated, ctxLen, pct)))
|
a.emit(infoEvent(fmt.Sprintf("~%d / %d tokens (%d%%)", estimated, ctxLen, pct)))
|
||||||
s.emit(infoEvent(strings.TrimRight(s.history.contextDebug(), "\n")))
|
a.emit(infoEvent(strings.TrimRight(a.history.contextDebug(), "\n")))
|
||||||
},
|
},
|
||||||
|
|
||||||
"/cost": func(args []string) {
|
"/cost": func(args []string) {
|
||||||
if s.history == nil {
|
if a.history == nil {
|
||||||
s.emit(infoEvent("no active session"))
|
a.emit(infoEvent("no active session"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.emit(infoEvent(fmt.Sprintf("last=$%.4f session=$%.4f",
|
a.emit(infoEvent(fmt.Sprintf("last=$%.4f session=$%.4f",
|
||||||
s.history.LastTurnCostUSD, s.history.SessionCostUSD)))
|
a.history.LastTurnCostUSD, a.history.SessionCostUSD)))
|
||||||
},
|
},
|
||||||
|
|
||||||
"/usage": func(args []string) {
|
"/usage": func(args []string) {
|
||||||
if s.history == nil {
|
if a.history == nil {
|
||||||
s.emit(infoEvent("no active session"))
|
a.emit(infoEvent("no active session"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ctxLen := s.runtime.Backend.ContextLength(ctx)
|
ctxLen := a.runtime.Backend.ContextLength(ctx)
|
||||||
if ctxLen <= 0 {
|
if ctxLen <= 0 {
|
||||||
ctxLen = defaultContextLength
|
ctxLen = defaultContextLength
|
||||||
}
|
}
|
||||||
estimated := s.history.estimateTokens()
|
estimated := a.history.estimateTokens()
|
||||||
pct := estimated * 100 / ctxLen
|
pct := estimated * 100 / ctxLen
|
||||||
usageStr := fmt.Sprintf("~%d / %d tokens (%d%%) | %d in, %d out, %d requests",
|
usageStr := fmt.Sprintf("~%d / %d tokens (%d%%) | %d in, %d out, %d requests",
|
||||||
estimated, ctxLen, pct,
|
estimated, ctxLen, pct,
|
||||||
s.history.TotalInputTokens, s.history.TotalOutputTokens,
|
a.history.TotalInputTokens, a.history.TotalOutputTokens,
|
||||||
s.history.TotalRequests)
|
a.history.TotalRequests)
|
||||||
if s.history.Estimated {
|
if a.history.Estimated {
|
||||||
usageStr += " [estimated]"
|
usageStr += " [estimated]"
|
||||||
}
|
}
|
||||||
s.emit(infoEvent(usageStr))
|
a.emit(infoEvent(usageStr))
|
||||||
},
|
},
|
||||||
|
|
||||||
"/history": func(args []string) {
|
"/history": func(args []string) {
|
||||||
if s.history == nil {
|
if a.history == nil {
|
||||||
s.emit(infoEvent("no active session"))
|
a.emit(infoEvent("no active session"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, msg := range s.history.history() {
|
for _, msg := range a.history.history() {
|
||||||
preview := msg.Content
|
preview := msg.Content
|
||||||
if len(preview) > 200 {
|
if len(preview) > 200 {
|
||||||
preview = preview[:200] + "..."
|
preview = preview[:200] + "..."
|
||||||
}
|
}
|
||||||
s.emit(infoEvent(fmt.Sprintf("[%s] %s", msg.Role, preview)))
|
a.emit(infoEvent(fmt.Sprintf("[%s] %s", msg.Role, preview)))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"/clear": func(args []string) {
|
"/clear": func(args []string) {
|
||||||
if s.IsRunning() {
|
if a.IsRunning() {
|
||||||
s.emit(infoEvent("error: cannot clear while agent is running"))
|
a.emit(infoEvent("error: cannot clear while agent is running"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.history = nil
|
a.history = nil
|
||||||
s.emit(infoEvent("cleared"))
|
a.emit(infoEvent("cleared"))
|
||||||
},
|
},
|
||||||
|
|
||||||
"/sessions": func(args []string) {
|
"/sessions": func(args []string) {
|
||||||
|
|
@ -333,10 +333,10 @@ func (s *agent) handleCommand(ctx context.Context, input string) bool {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
appendSessionFiles(s.sessionsDir)
|
appendSessionFiles(a.sessionsDir)
|
||||||
appendSessionFiles(filepath.Join(s.sessionsDir, "active"))
|
appendSessionFiles(filepath.Join(a.sessionsDir, "active"))
|
||||||
|
|
||||||
cwd := s.CWD()
|
cwd := a.CWD()
|
||||||
found := false
|
found := false
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
data, readErr := os.ReadFile(file.path)
|
data, readErr := os.ReadFile(file.path)
|
||||||
|
|
@ -351,7 +351,7 @@ func (s *agent) handleCommand(ctx context.Context, input string) bool {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
marker := " "
|
marker := " "
|
||||||
if file.id == s.sess.ID() {
|
if file.id == a.sess.ID() {
|
||||||
marker = "* "
|
marker = "* "
|
||||||
}
|
}
|
||||||
goal := ""
|
goal := ""
|
||||||
|
|
@ -364,75 +364,75 @@ func (s *agent) handleCommand(ctx context.Context, input string) bool {
|
||||||
if len(goal) > 60 {
|
if len(goal) > 60 {
|
||||||
goal = goal[:60] + "..."
|
goal = goal[:60] + "..."
|
||||||
}
|
}
|
||||||
s.emit(infoEvent(marker + fmt.Sprintf("%-24s [%s] %q", file.id, ps.Agent, goal)))
|
a.emit(infoEvent(marker + fmt.Sprintf("%-24s [%s] %q", file.id, ps.Agent, goal)))
|
||||||
found = true
|
found = true
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
s.emit(infoEvent("no sessions for " + cwd))
|
a.emit(infoEvent("no sessions for " + cwd))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
"/save": func(args []string) {
|
"/save": func(args []string) {
|
||||||
if s.history == nil {
|
if a.history == nil {
|
||||||
s.emit(infoEvent("error: no active session"))
|
a.emit(infoEvent("error: no active session"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
s.emit(infoEvent("error: /save requires a name"))
|
a.emit(infoEvent("error: /save requires a name"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
name := args[0]
|
name := args[0]
|
||||||
path := s.sessionsDir + "/" + name + ".json"
|
path := a.sessionsDir + "/" + name + ".json"
|
||||||
if err := s.history.saveTo(path, name, s.agentName, s.CWD()); err != nil {
|
if err := a.history.saveTo(path, name, a.agentName, a.CWD()); err != nil {
|
||||||
s.emit(infoEvent("error: " + err.Error()))
|
a.emit(infoEvent("error: " + err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.emit(infoEvent("saved: " + path))
|
a.emit(infoEvent("saved: " + path))
|
||||||
},
|
},
|
||||||
|
|
||||||
"/resume": func(args []string) {
|
"/resume": func(args []string) {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
s.emit(infoEvent("error: /resume requires a session id or name"))
|
a.emit(infoEvent("error: /resume requires a session id or name"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if s.IsRunning() {
|
if a.IsRunning() {
|
||||||
s.emit(infoEvent("error: cannot resume while agent is running"))
|
a.emit(infoEvent("error: cannot resume while agent is running"))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
name := args[0]
|
name := args[0]
|
||||||
path := s.sessionsDir + "/" + name + ".json"
|
path := a.sessionsDir + "/" + name + ".json"
|
||||||
data, err := os.ReadFile(path)
|
data, err := os.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.emit(infoEvent(fmt.Sprintf("error: %v", err)))
|
a.emit(infoEvent(fmt.Sprintf("error: %v", err)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
var ps PersistedSession
|
var ps PersistedSession
|
||||||
if err := json.Unmarshal(data, &ps); err != nil {
|
if err := json.Unmarshal(data, &ps); err != nil {
|
||||||
s.emit(infoEvent(fmt.Sprintf("error: %v", err)))
|
a.emit(infoEvent(fmt.Sprintf("error: %v", err)))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.history = RestoreHistory(&ps)
|
a.history = RestoreHistory(&ps)
|
||||||
s.emit(infoEvent(fmt.Sprintf("resumed session %s (%d messages)", name, len(ps.Messages))))
|
a.emit(infoEvent(fmt.Sprintf("resumed session %s (%d messages)", name, len(ps.Messages))))
|
||||||
},
|
},
|
||||||
|
|
||||||
"/cwd": func(args []string) {
|
"/cwd": func(args []string) {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
s.emit(infoEvent("cwd: " + s.CWD()))
|
a.emit(infoEvent("cwd: " + a.CWD()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dir := strings.Join(args, " ")
|
dir := strings.Join(args, " ")
|
||||||
if err := s.SetCWD(dir); err != nil {
|
if err := a.SetCWD(dir); err != nil {
|
||||||
s.emit(infoEvent("error: " + err.Error()))
|
a.emit(infoEvent("error: " + err.Error()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
s.emit(infoEvent("cwd: " + dir))
|
a.emit(infoEvent("cwd: " + dir))
|
||||||
},
|
},
|
||||||
|
|
||||||
"/skills": func(args []string) { listFromHandler("skills") },
|
"/skills": func(args []string) { listFromHandler("skills") },
|
||||||
"/tools": func(args []string) { listFromHandler("tools") },
|
"/tools": func(args []string) { listFromHandler("tools") },
|
||||||
|
|
||||||
"/sp": func(args []string) {
|
"/sp": func(args []string) {
|
||||||
s.emit(infoEvent(s.runtime.Preamble))
|
a.emit(infoEvent(a.runtime.Preamble))
|
||||||
},
|
},
|
||||||
|
|
||||||
"/help": func(args []string) {
|
"/help": func(args []string) {
|
||||||
|
|
@ -466,7 +466,7 @@ func (s *agent) handleCommand(ctx context.Context, input string) bool {
|
||||||
" !<cmd> - run shell command",
|
" !<cmd> - run shell command",
|
||||||
}
|
}
|
||||||
for _, l := range lines {
|
for _, l := range lines {
|
||||||
s.emit(infoEvent(l))
|
a.emit(infoEvent(l))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
@ -475,7 +475,7 @@ func (s *agent) handleCommand(ctx context.Context, input string) bool {
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
s.emit(infoEvent(""))
|
a.emit(infoEvent(""))
|
||||||
fn(args)
|
fn(args)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
|
||||||
800
agent/core.go
800
agent/core.go
File diff suppressed because it is too large
Load Diff
Reference in New Issue