From 227739638b021bef72d2ba81047506a242490d69 Mon Sep 17 00:00:00 2001 From: Virgil Date: Sat, 4 Apr 2026 02:45:56 +0000 Subject: [PATCH] feat(process): add Core stdin task --- actions.go | 12 ++++++++++++ service.go | 15 +++++++++++++++ service_test.go | 23 +++++++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/actions.go b/actions.go index 6686456..88a9095 100644 --- a/actions.go +++ b/actions.go @@ -82,6 +82,18 @@ type TaskProcessOutput struct { ID string } +// TaskProcessInput writes data to the stdin of a managed process through Core.PERFORM. +// +// Example: +// +// c.PERFORM(process.TaskProcessInput{ID: "proc-1", Input: "hello\n"}) +type TaskProcessInput struct { + // ID identifies a managed process started by this service. + ID string + // Input is written verbatim to the process stdin pipe. + Input string +} + // TaskProcessList requests a snapshot of managed processes through Core.PERFORM. // If RunningOnly is true, only active processes are returned. // diff --git a/service.go b/service.go index 21d8c0b..5d0a465 100644 --- a/service.go +++ b/service.go @@ -624,6 +624,21 @@ func (s *Service) handleTask(c *core.Core, task core.Task) core.Result { } return core.Result{Value: output, OK: true} + case TaskProcessInput: + if m.ID == "" { + return core.Result{Value: coreerr.E("Service.handleTask", "task process input requires an id", nil), OK: false} + } + + proc, err := s.Get(m.ID) + if err != nil { + return core.Result{Value: err, OK: false} + } + + if err := proc.SendInput(m.Input); err != nil { + return core.Result{Value: err, OK: false} + } + + return core.Result{OK: true} case TaskProcessList: procs := s.List() if m.RunningOnly { diff --git a/service_test.go b/service_test.go index bd381ed..7e17775 100644 --- a/service_test.go +++ b/service_test.go @@ -753,6 +753,29 @@ func TestService_OnStartup(t *testing.T) { require.True(t, ok) assert.Contains(t, output, "snapshot-output") }) + + t.Run("registers process.input task", func(t *testing.T) { + svc, c := newTestService(t) + + err := svc.OnStartup(context.Background()) + require.NoError(t, err) + + proc, err := svc.Start(context.Background(), "cat") + require.NoError(t, err) + + result := c.PERFORM(TaskProcessInput{ + ID: proc.ID, + Input: "typed-through-core\n", + }) + require.True(t, result.OK) + + err = proc.CloseStdin() + require.NoError(t, err) + + <-proc.Done() + + assert.Contains(t, proc.Output(), "typed-through-core") + }) } func TestService_RunWithOptions(t *testing.T) {