]> git.giacomolli.uk - onechat/blobdiff - daemon_children_test.go
Bind external events to permanent agent IDs
[onechat] / daemon_children_test.go
index b9e212f8646646473ee08512d4c54593c7e89632..8fcae369de4c8b30fefd50743e1c6b9b3f3b684e 100644 (file)
@@ -49,6 +49,7 @@ func TestDaemonToolsCreateAndTellAChildDuringATurn(t *testing.T) {
 
                modelWriteEvents(w, modelCompletedEvent(items, 100, 0, 5))
        }
 
                modelWriteEvents(w, modelCompletedEvent(items, 100, 0, 5))
        }
+
        whatsapp, _, _ := whatsappStartTest(t, dir, newTestClock())
        listener, err := daemonListenSocket(filepath.Join(dir, socketFileName))
        require.NoError(t, err)
        whatsapp, _, _ := whatsappStartTest(t, dir, newTestClock())
        listener, err := daemonListenSocket(filepath.Join(dir, socketFileName))
        require.NoError(t, err)
@@ -98,6 +99,37 @@ func TestDaemonToolsCreateAndTellAChildDuringATurn(t *testing.T) {
        }, 5*time.Second, time.Millisecond)
 }
 
        }, 5*time.Second, time.Millisecond)
 }
 
+func TestRuntimeChildAcceptsNotificationsByItsPermanentID(t *testing.T) {
+       test := newDaemonChildrenTest(t)
+       test.server.reply = func(w http.ResponseWriter, _ ModelFakeCall) {
+               modelWriteEvents(w, modelCompletedEvent([]any{modelMessageItem("")}, 100, 0, 5))
+       }
+
+       _, err := test.runtime.Create("Garden", "Keep garden plans.")
+       require.NoError(t, err)
+
+       child := test.runtime.messages.Child(test.root.agent.config.Name, "Garden")
+       require.NotNil(t, child)
+
+       receipt, err := test.runtime.messages.Notify(&NotifyInput{
+               AgentID: child.agent.config.ID,
+               Source:  "check",
+               ID:      "runtime-child",
+               Text:    "A new result.",
+       })
+       require.NoError(t, err)
+       require.Equal(t, "accepted", receipt.Status)
+       require.Eventually(t, func() bool {
+               return child.memory.Len() == 1
+       }, 10*time.Second, time.Millisecond)
+       require.Zero(t, test.root.memory.Len())
+
+       logged, err := child.memory.Message(0)
+       require.NoError(t, err)
+       require.Equal(t, "work", logged.Kind)
+       require.Contains(t, logged.Text, "Untrusted external data")
+}
+
 func TestChildCreationRefusesUsedNames(t *testing.T) {
        test := newDaemonChildrenTest(t)
        box := test.root.tools
 func TestChildCreationRefusesUsedNames(t *testing.T) {
        test := newDaemonChildrenTest(t)
        box := test.root.tools
@@ -111,6 +143,7 @@ func TestChildCreationRefusesUsedNames(t *testing.T) {
        test.root.runs.subagents.draw = func() string {
                return "BlueFox"
        }
        test.root.runs.subagents.draw = func() string {
                return "BlueFox"
        }
+
        subagent, err := test.root.runs.subagents.Create(t.Context())
        require.NoError(t, err)
        require.Equal(t, "BlueFox", subagent.name)
        subagent, err := test.root.runs.subagents.Create(t.Context())
        require.NoError(t, err)
        require.Equal(t, "BlueFox", subagent.name)
@@ -125,26 +158,27 @@ func TestChildCreationAcceptsAreaNames(t *testing.T) {
                child string
        }{
                {
                child string
        }{
                {
-                       name:  "house area",
+                       name:  "accepts house area",
                        child: "House",
                },
                {
                        child: "House",
                },
                {
-                       name:  "calendar area",
+                       name:  "accepts calendar area",
                        child: "Calendar",
                },
                {
                        child: "Calendar",
                },
                {
-                       name:  "two letters",
+                       name:  "accepts two letters",
                        child: "Ab",
                },
                {
                        child: "Ab",
                },
                {
-                       name:  "capital letters after the first",
+                       name:  "accepts capital letters after the first",
                        child: "ABcD",
                },
                {
                        child: "ABcD",
                },
                {
-                       name:  "thirty-two letters",
+                       name:  "accepts thirty-two letters",
                        child: "A" + strings.Repeat("b", 31),
                },
        }
                        child: "A" + strings.Repeat("b", 31),
                },
        }
+
        for _, tc := range testCases {
                t.Run(tc.name, func(t *testing.T) {
                        test := newDaemonChildrenTest(t)
        for _, tc := range testCases {
                t.Run(tc.name, func(t *testing.T) {
                        test := newDaemonChildrenTest(t)
@@ -169,46 +203,47 @@ func TestChildCreationRefusesInvalidAreaNames(t *testing.T) {
                child string
        }{
                {
                child string
        }{
                {
-                       name:  "empty name",
+                       name:  "refuses empty name",
                        child: "",
                },
                {
                        child: "",
                },
                {
-                       name:  "one letter",
+                       name:  "refuses one letter",
                        child: "H",
                },
                {
                        child: "H",
                },
                {
-                       name:  "thirty-three letters",
+                       name:  "refuses thirty-three letters",
                        child: "A" + strings.Repeat("b", 32),
                },
                {
                        child: "A" + strings.Repeat("b", 32),
                },
                {
-                       name:  "lowercase initial",
+                       name:  "refuses lowercase initial",
                        child: "house",
                },
                {
                        child: "house",
                },
                {
-                       name:  "two words",
+                       name:  "refuses two words",
                        child: "My House",
                },
                {
                        child: "My House",
                },
                {
-                       name:  "digit",
+                       name:  "refuses digit",
                        child: "House2",
                },
                {
                        child: "House2",
                },
                {
-                       name:  "path",
+                       name:  "refuses path",
                        child: "../House",
                },
                {
                        child: "../House",
                },
                {
-                       name:  "punctuation",
+                       name:  "refuses punctuation",
                        child: "House-",
                },
                {
                        child: "House-",
                },
                {
-                       name:  "non-ASCII initial",
+                       name:  "refuses non-ASCII initial",
                        child: "\u00c1rea",
                },
                {
                        child: "\u00c1rea",
                },
                {
-                       name:  "non-ASCII remainder",
+                       name:  "refuses non-ASCII remainder",
                        child: "Hous\u00e9",
                },
        }
                        child: "Hous\u00e9",
                },
        }
+
        for _, tc := range testCases {
                t.Run(tc.name, func(t *testing.T) {
                        test := newDaemonChildrenTest(t)
        for _, tc := range testCases {
                t.Run(tc.name, func(t *testing.T) {
                        test := newDaemonChildrenTest(t)
@@ -320,6 +355,7 @@ func TestChildNamesStayOutOfSubagentDraws(t *testing.T) {
 
                return name
        }
 
                return name
        }
+
        subagent, err := test.root.runs.subagents.Create(t.Context())
        require.NoError(t, err)
        require.Equal(t, "BlueFox", subagent.name)
        subagent, err := test.root.runs.subagents.Create(t.Context())
        require.NoError(t, err)
        require.Equal(t, "BlueFox", subagent.name)
@@ -364,6 +400,7 @@ func TestZoomReadsTheChildViewAndKeepsSubagentLogs(t *testing.T) {
        test.root.runs.subagents.draw = func() string {
                return "BlueFox"
        }
        test.root.runs.subagents.draw = func() string {
                return "BlueFox"
        }
+
        subagent, err := test.root.runs.subagents.Create(t.Context())
        require.NoError(t, err)
 
        subagent, err := test.root.runs.subagents.Create(t.Context())
        require.NoError(t, err)
 
@@ -439,6 +476,7 @@ func newDaemonChildrenTest(t *testing.T) *DaemonChildrenTest {
        test := &DaemonChildrenTest{
                server: newModelFake(t),
        }
        test := &DaemonChildrenTest{
                server: newModelFake(t),
        }
+
        agents, err := openDaemonAgents(t.Context(), t.TempDir(), test.server.URL, ModelAPIKey(modelTestKey), defaultConfig().Compactor, time.Now, discardLog())
        require.NoError(t, err)
 
        agents, err := openDaemonAgents(t.Context(), t.TempDir(), test.server.URL, ModelAPIKey(modelTestKey), defaultConfig().Compactor, time.Now, discardLog())
        require.NoError(t, err)
 
@@ -457,6 +495,7 @@ func newDaemonChildrenTest(t *testing.T) *DaemonChildrenTest {
                root:     test.root,
                messages: messages,
        }
                root:     test.root,
                messages: messages,
        }
+
        test.root.tools.children = test.runtime
        t.Cleanup(func() {
                cancel()
        test.root.tools.children = test.runtime
        t.Cleanup(func() {
                cancel()