feat(agentic): add session log command aliases

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-01 23:08:29 +00:00
parent 90a9eb256c
commit b1b51c04f9
2 changed files with 109 additions and 0 deletions

View file

@ -14,6 +14,8 @@ func (s *PrepSubsystem) registerSessionCommands() {
c.Command("agentic:session/end", core.Command{Description: "End a stored session with status, summary, and handoff notes", Action: s.cmdSessionEnd})
c.Command("session/complete", core.Command{Description: "Mark a stored session completed with status, summary, and handoff notes", Action: s.cmdSessionEnd})
c.Command("agentic:session/complete", core.Command{Description: "Mark a stored session completed with status, summary, and handoff notes", Action: s.cmdSessionEnd})
c.Command("session/log", core.Command{Description: "Add a work log entry to a stored session", Action: s.cmdSessionLog})
c.Command("agentic:session/log", core.Command{Description: "Add a work log entry to a stored session", Action: s.cmdSessionLog})
c.Command("session/resume", core.Command{Description: "Resume a paused or handed-off session from local cache", Action: s.cmdSessionResume})
c.Command("agentic:session/resume", core.Command{Description: "Resume a paused or handed-off session from local cache", Action: s.cmdSessionResume})
c.Command("session/replay", core.Command{Description: "Build replay context for a stored session", Action: s.cmdSessionReplay})
@ -109,6 +111,48 @@ func (s *PrepSubsystem) cmdSessionEnd(options core.Options) core.Result {
return core.Result{Value: output, OK: true}
}
// core-agent session log ses-abc123 --message="Checked build" --type=checkpoint
func (s *PrepSubsystem) cmdSessionLog(options core.Options) core.Result {
sessionID := optionStringValue(options, "session_id", "session-id", "id", "_arg")
message := optionStringValue(options, "message")
entryType := optionStringValue(options, "type")
if entryType == "" {
entryType = "info"
}
if sessionID == "" {
core.Print(nil, "usage: core-agent session log <session-id> --message=\"Checked build\" [--type=checkpoint] [--data='{\"key\":\"value\"}']")
return core.Result{Value: core.E("agentic.cmdSessionLog", "session_id is required", nil), OK: false}
}
if message == "" {
core.Print(nil, "usage: core-agent session log <session-id> --message=\"Checked build\" [--type=checkpoint] [--data='{\"key\":\"value\"}']")
return core.Result{Value: core.E("agentic.cmdSessionLog", "message is required", nil), OK: false}
}
result := s.handleSessionLog(s.commandContext(), core.NewOptions(
core.Option{Key: "session_id", Value: sessionID},
core.Option{Key: "message", Value: message},
core.Option{Key: "type", Value: entryType},
core.Option{Key: "data", Value: optionAnyMapValue(options, "data")},
))
if !result.OK {
err := commandResultError("agentic.cmdSessionLog", result)
core.Print(nil, "error: %v", err)
return core.Result{Value: err, OK: false}
}
output, ok := result.Value.(SessionLogOutput)
if !ok {
err := core.E("agentic.cmdSessionLog", "invalid session log output", nil)
core.Print(nil, "error: %v", err)
return core.Result{Value: err, OK: false}
}
core.Print(nil, "session: %s", sessionID)
core.Print(nil, "type: %s", entryType)
core.Print(nil, "logged: %s", output.Logged)
return core.Result{Value: output, OK: true}
}
func (s *PrepSubsystem) cmdSessionResume(options core.Options) core.Result {
sessionID := optionStringValue(options, "session_id", "session-id", "id", "_arg")
if sessionID == "" {

View file

@ -25,6 +25,8 @@ func TestCommandsSession_RegisterSessionCommands_Good(t *testing.T) {
assert.Contains(t, c.Commands(), "agentic:session/end")
assert.Contains(t, c.Commands(), "session/complete")
assert.Contains(t, c.Commands(), "agentic:session/complete")
assert.Contains(t, c.Commands(), "session/log")
assert.Contains(t, c.Commands(), "agentic:session/log")
assert.Contains(t, c.Commands(), "session/resume")
assert.Contains(t, c.Commands(), "agentic:session/resume")
assert.Contains(t, c.Commands(), "session/replay")
@ -161,6 +163,69 @@ func TestCommandsSession_CmdSessionEnd_Ugly_InvalidResponse(t *testing.T) {
assert.False(t, result.OK)
}
func TestCommandsSession_CmdSessionLog_Good(t *testing.T) {
dir := t.TempDir()
t.Setenv("CORE_WORKSPACE", dir)
s := newTestPrep(t)
require.NoError(t, writeSessionCache(&Session{
SessionID: "ses-log",
AgentType: "codex",
Status: "active",
WorkLog: []map[string]any{
{"type": "checkpoint", "message": "build passed"},
},
}))
result := s.cmdSessionLog(core.NewOptions(
core.Option{Key: "session_id", Value: "ses-log"},
core.Option{Key: "message", Value: "Checked build"},
core.Option{Key: "type", Value: "checkpoint"},
core.Option{Key: "data", Value: map[string]any{"repo": "go-io"}},
))
require.True(t, result.OK)
output, ok := result.Value.(SessionLogOutput)
require.True(t, ok)
assert.True(t, output.Success)
assert.Equal(t, "Checked build", output.Logged)
cached, err := readSessionCache("ses-log")
require.NoError(t, err)
require.NotNil(t, cached)
require.Len(t, cached.WorkLog, 2)
assert.Equal(t, "checkpoint", cached.WorkLog[1]["type"])
assert.Equal(t, "Checked build", cached.WorkLog[1]["message"])
}
func TestCommandsSession_CmdSessionLog_Bad_MissingMessage(t *testing.T) {
s := newTestPrep(t)
result := s.cmdSessionLog(core.NewOptions(core.Option{Key: "session_id", Value: "ses-log"}))
assert.False(t, result.OK)
require.Error(t, result.Value.(error))
assert.Contains(t, result.Value.(error).Error(), "message is required")
}
func TestCommandsSession_CmdSessionLog_Ugly_CorruptedCacheFallsBackToRemoteError(t *testing.T) {
dir := t.TempDir()
t.Setenv("CORE_WORKSPACE", dir)
s := newTestPrep(t)
require.True(t, fs.EnsureDir(sessionCacheRoot()).OK)
require.True(t, fs.WriteAtomic(sessionCachePath("ses-bad"), "{not-json").OK)
result := s.cmdSessionLog(core.NewOptions(
core.Option{Key: "session_id", Value: "ses-bad"},
core.Option{Key: "message", Value: "Checked build"},
))
assert.False(t, result.OK)
require.Error(t, result.Value.(error))
assert.Contains(t, result.Value.(error).Error(), "no platform API key configured")
}
func TestCommandsSession_CmdSessionResume_Good(t *testing.T) {
dir := t.TempDir()
t.Setenv("CORE_WORKSPACE", dir)