feat(agentic): expose session get/list commands
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
8828e89e62
commit
5ba7886deb
3 changed files with 151 additions and 0 deletions
|
|
@ -8,6 +8,10 @@ import (
|
|||
|
||||
func (s *PrepSubsystem) registerSessionCommands() {
|
||||
c := s.Core()
|
||||
c.Command("session/get", core.Command{Description: "Read a stored session by session ID", Action: s.cmdSessionGet})
|
||||
c.Command("agentic:session/get", core.Command{Description: "Read a stored session by session ID", Action: s.cmdSessionGet})
|
||||
c.Command("session/list", core.Command{Description: "List stored sessions with optional filters", Action: s.cmdSessionList})
|
||||
c.Command("agentic:session/list", core.Command{Description: "List stored sessions with optional filters", Action: s.cmdSessionList})
|
||||
c.Command("session/start", core.Command{Description: "Start a stored session for a plan", Action: s.cmdSessionStart})
|
||||
c.Command("agentic:session/start", core.Command{Description: "Start a stored session for a plan", Action: s.cmdSessionStart})
|
||||
c.Command("session/continue", core.Command{Description: "Continue a stored session from saved context", Action: s.cmdSessionContinue})
|
||||
|
|
@ -28,6 +32,97 @@ func (s *PrepSubsystem) registerSessionCommands() {
|
|||
c.Command("agentic:session/replay", core.Command{Description: "Build replay context for a stored session", Action: s.cmdSessionReplay})
|
||||
}
|
||||
|
||||
// core-agent session get ses-abc123
|
||||
func (s *PrepSubsystem) cmdSessionGet(options core.Options) core.Result {
|
||||
sessionID := optionStringValue(options, "session_id", "session-id", "id", "_arg")
|
||||
if sessionID == "" {
|
||||
core.Print(nil, "usage: core-agent session get <session-id>")
|
||||
return core.Result{Value: core.E("agentic.cmdSessionGet", "session_id is required", nil), OK: false}
|
||||
}
|
||||
|
||||
result := s.handleSessionGet(s.commandContext(), core.NewOptions(
|
||||
core.Option{Key: "session_id", Value: sessionID},
|
||||
))
|
||||
if !result.OK {
|
||||
err := commandResultError("agentic.cmdSessionGet", result)
|
||||
core.Print(nil, "error: %v", err)
|
||||
return core.Result{Value: err, OK: false}
|
||||
}
|
||||
|
||||
output, ok := result.Value.(SessionOutput)
|
||||
if !ok {
|
||||
err := core.E("agentic.cmdSessionGet", "invalid session get output", nil)
|
||||
core.Print(nil, "error: %v", err)
|
||||
return core.Result{Value: err, OK: false}
|
||||
}
|
||||
|
||||
core.Print(nil, "session: %s", output.Session.SessionID)
|
||||
core.Print(nil, "status: %s", output.Session.Status)
|
||||
core.Print(nil, "agent: %s", output.Session.AgentType)
|
||||
if output.Session.PlanSlug != "" {
|
||||
core.Print(nil, "plan: %s", output.Session.PlanSlug)
|
||||
}
|
||||
if output.Session.Summary != "" {
|
||||
core.Print(nil, "summary: %s", output.Session.Summary)
|
||||
}
|
||||
if output.Session.CreatedAt != "" {
|
||||
core.Print(nil, "started: %s", output.Session.CreatedAt)
|
||||
}
|
||||
if output.Session.UpdatedAt != "" {
|
||||
core.Print(nil, "updated: %s", output.Session.UpdatedAt)
|
||||
}
|
||||
if output.Session.EndedAt != "" {
|
||||
core.Print(nil, "ended: %s", output.Session.EndedAt)
|
||||
}
|
||||
if len(output.Session.ContextSummary) > 0 {
|
||||
core.Print(nil, "context: %d item(s)", len(output.Session.ContextSummary))
|
||||
}
|
||||
if len(output.Session.WorkLog) > 0 {
|
||||
core.Print(nil, "work log: %d item(s)", len(output.Session.WorkLog))
|
||||
}
|
||||
if len(output.Session.Artifacts) > 0 {
|
||||
core.Print(nil, "artifacts: %d item(s)", len(output.Session.Artifacts))
|
||||
}
|
||||
if len(output.Session.Handoff) > 0 {
|
||||
core.Print(nil, "handoff: %d item(s)", len(output.Session.Handoff))
|
||||
}
|
||||
|
||||
return core.Result{Value: output, OK: true}
|
||||
}
|
||||
|
||||
// core-agent session list --status=active --plan=ax-follow-up
|
||||
func (s *PrepSubsystem) cmdSessionList(options core.Options) core.Result {
|
||||
result := s.handleSessionList(s.commandContext(), core.NewOptions(
|
||||
core.Option{Key: "plan_slug", Value: optionStringValue(options, "plan_slug", "plan")},
|
||||
core.Option{Key: "agent_type", Value: optionStringValue(options, "agent_type", "agent")},
|
||||
core.Option{Key: "status", Value: optionStringValue(options, "status")},
|
||||
core.Option{Key: "limit", Value: optionIntValue(options, "limit")},
|
||||
))
|
||||
if !result.OK {
|
||||
err := commandResultError("agentic.cmdSessionList", result)
|
||||
core.Print(nil, "error: %v", err)
|
||||
return core.Result{Value: err, OK: false}
|
||||
}
|
||||
|
||||
output, ok := result.Value.(SessionListOutput)
|
||||
if !ok {
|
||||
err := core.E("agentic.cmdSessionList", "invalid session list output", nil)
|
||||
core.Print(nil, "error: %v", err)
|
||||
return core.Result{Value: err, OK: false}
|
||||
}
|
||||
|
||||
if output.Count == 0 {
|
||||
core.Print(nil, "no sessions")
|
||||
return core.Result{Value: output, OK: true}
|
||||
}
|
||||
|
||||
for _, session := range output.Sessions {
|
||||
core.Print(nil, " %-10s %-10s %-24s %s", session.Status, session.AgentType, session.SessionID, sessionPlanSlug(session))
|
||||
}
|
||||
core.Print(nil, "%d session(s)", output.Count)
|
||||
return core.Result{Value: output, OK: true}
|
||||
}
|
||||
|
||||
// core-agent session start ax-follow-up --agent-type=codex
|
||||
func (s *PrepSubsystem) cmdSessionStart(options core.Options) core.Result {
|
||||
planSlug := optionStringValue(options, "plan_slug", "plan", "_arg")
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ func TestCommandsSession_RegisterSessionCommands_Good(t *testing.T) {
|
|||
|
||||
s.registerSessionCommands()
|
||||
|
||||
assert.Contains(t, c.Commands(), "session/get")
|
||||
assert.Contains(t, c.Commands(), "agentic:session/get")
|
||||
assert.Contains(t, c.Commands(), "session/list")
|
||||
assert.Contains(t, c.Commands(), "agentic:session/list")
|
||||
assert.Contains(t, c.Commands(), "session/handoff")
|
||||
assert.Contains(t, c.Commands(), "agentic:session/handoff")
|
||||
assert.Contains(t, c.Commands(), "session/start")
|
||||
|
|
@ -39,6 +43,54 @@ func TestCommandsSession_RegisterSessionCommands_Good(t *testing.T) {
|
|||
assert.Contains(t, c.Commands(), "agentic:session/replay")
|
||||
}
|
||||
|
||||
func TestCommandsSession_CmdSessionGet_Good(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, "/v1/sessions/ses-get", r.URL.Path)
|
||||
require.Equal(t, http.MethodGet, r.Method)
|
||||
_, _ = w.Write([]byte(`{"data":{"session_id":"ses-get","plan_slug":"ax-follow-up","agent_type":"codex","status":"active","summary":"Working","created_at":"2026-03-31T12:00:00Z","updated_at":"2026-03-31T12:30:00Z","work_log":[{"type":"checkpoint","message":"started"}],"artifacts":[{"path":"pkg/agentic/session.go","action":"modified"}]}}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
subsystem := testPrepWithPlatformServer(t, server, "secret-token")
|
||||
|
||||
output := captureStdout(t, func() {
|
||||
result := subsystem.cmdSessionGet(core.NewOptions(core.Option{Key: "_arg", Value: "ses-get"}))
|
||||
require.True(t, result.OK)
|
||||
})
|
||||
|
||||
assert.Contains(t, output, "session: ses-get")
|
||||
assert.Contains(t, output, "plan: ax-follow-up")
|
||||
assert.Contains(t, output, "work log: 1 item(s)")
|
||||
assert.Contains(t, output, "artifacts: 1 item(s)")
|
||||
}
|
||||
|
||||
func TestCommandsSession_CmdSessionList_Good(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, "/v1/sessions", r.URL.Path)
|
||||
require.Equal(t, "ax-follow-up", r.URL.Query().Get("plan_slug"))
|
||||
require.Equal(t, "codex", r.URL.Query().Get("agent_type"))
|
||||
require.Equal(t, "active", r.URL.Query().Get("status"))
|
||||
require.Equal(t, "5", r.URL.Query().Get("limit"))
|
||||
_, _ = w.Write([]byte(`{"data":[{"session_id":"ses-1","plan_slug":"ax-follow-up","agent_type":"codex","status":"active"},{"session_id":"ses-2","agent_type":"claude","status":"paused"}],"count":2}`))
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
subsystem := testPrepWithPlatformServer(t, server, "secret-token")
|
||||
|
||||
output := captureStdout(t, func() {
|
||||
result := subsystem.cmdSessionList(core.NewOptions(
|
||||
core.Option{Key: "plan_slug", Value: "ax-follow-up"},
|
||||
core.Option{Key: "agent_type", Value: "codex"},
|
||||
core.Option{Key: "status", Value: "active"},
|
||||
core.Option{Key: "limit", Value: 5},
|
||||
))
|
||||
require.True(t, result.OK)
|
||||
})
|
||||
|
||||
assert.Contains(t, output, "ses-1")
|
||||
assert.Contains(t, output, "2 session(s)")
|
||||
}
|
||||
|
||||
func TestCommandsSession_CmdSessionStart_Good(t *testing.T) {
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
require.Equal(t, "/v1/sessions", r.URL.Path)
|
||||
|
|
|
|||
|
|
@ -1422,6 +1422,10 @@ func TestCommands_RegisterCommands_Good_AllRegistered(t *testing.T) {
|
|||
assert.Contains(t, cmds, "plan/delete")
|
||||
assert.Contains(t, cmds, "agentic:plan-cleanup")
|
||||
assert.Contains(t, cmds, "session/start")
|
||||
assert.Contains(t, cmds, "session/get")
|
||||
assert.Contains(t, cmds, "agentic:session/get")
|
||||
assert.Contains(t, cmds, "session/list")
|
||||
assert.Contains(t, cmds, "agentic:session/list")
|
||||
assert.Contains(t, cmds, "agentic:session/start")
|
||||
assert.Contains(t, cmds, "session/continue")
|
||||
assert.Contains(t, cmds, "agentic:session/continue")
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue