Run Claude sessions on tasks with event streaming and restart recovery

This commit is contained in:
Ian Gulliver
2026-10-13 22:30:39 -07:00
parent 2328904131
commit 09951e64e7
16 changed files with 1630 additions and 170 deletions
+32 -7
View File
@@ -29,6 +29,7 @@ type HookMatcher struct {
type Options struct {
Cwd string
Model string
SessionID string
Resume string
ForkSession bool
GitName string
@@ -45,12 +46,15 @@ type Event struct {
}
type Block struct {
Type string `json:"type"`
Text string `json:"text"`
Name string `json:"name"`
Input json.RawMessage `json:"input"`
Content json.RawMessage `json:"content"`
IsError bool `json:"is_error"`
Type string `json:"type"`
ID string `json:"id"`
ToolUseID string `json:"tool_use_id"`
Text string `json:"text"`
Thinking string `json:"thinking"`
Name string `json:"name"`
Input json.RawMessage `json:"input"`
Content json.RawMessage `json:"content"`
IsError bool `json:"is_error"`
}
type Result struct {
@@ -138,6 +142,7 @@ func Start(ctx context.Context, opts Options) (*Session, error) {
pending: map[string]chan controlResult{},
hooks: map[string]HookFunc{},
servers: map[string]*mcp.Server{},
id: initialID(opts),
}
args, err := s.buildArgs(opts)
@@ -179,6 +184,16 @@ func Start(ctx context.Context, opts Options) (*Session, error) {
return s, nil
}
func initialID(opts Options) string {
if opts.SessionID != "" {
return opts.SessionID
}
if opts.ForkSession {
return ""
}
return opts.Resume
}
func (s *Session) buildArgs(opts Options) ([]string, error) {
settings, err := json.Marshal(map[string]any{
"attribution": map[string]any{"commit": "", "pr": ""},
@@ -190,7 +205,7 @@ func (s *Session) buildArgs(opts Options) ([]string, error) {
servers := map[string]any{}
for _, srv := range opts.MCPServers {
s.servers[srv.Name] = srv
servers[srv.Name] = map[string]any{"type": "sdk", "name": srv.Name}
servers[srv.Name] = map[string]any{"type": "sdk", "name": srv.Name, "alwaysLoad": true}
}
mcpConfig, err := json.Marshal(map[string]any{"mcpServers": servers})
@@ -212,6 +227,10 @@ func (s *Session) buildArgs(opts Options) ([]string, error) {
args = append(args, "--model", opts.Model)
}
if opts.SessionID != "" {
args = append(args, "--session-id="+opts.SessionID)
}
if opts.Resume != "" {
args = append(args, "--resume="+opts.Resume)
}
@@ -342,6 +361,12 @@ func (s *Session) Close() error {
return s.cmd.Wait()
}
func (s *Session) Kill() {
s.cmd.Process.Kill()
<-s.done
s.cmd.Wait()
}
func (s *Session) write(v any) error {
b, err := json.Marshal(v)
if err != nil {