summary |
shortlog |
log |
commit | commitdiff |
tree
raw |
patch |
inline | side by side (from parent 1:
697c662)
Each user message event names its source client. The socket clients
submit as terminal, and the terminal client shows a user message from
any other source with the source as a mark, such as "[telegram] text".
With more than one client on one agent, each client then shows the full
conversation, so a reply always comes with its question. The log does
not keep the source.
Issue:
a143bd8
}
// eventText returns the text that the client shows for event, or "" for none.
}
// eventText returns the text that the client shows for event, or "" for none.
-// The client shows no user message, because the user typed it. A tool result
-// shows its first resultLines lines.
+// The client shows a user message only from another source, such as telegram,
+// because the user typed the others. A tool result shows its first resultLines
+// lines.
func eventText(event Event) string {
switch event.Kind {
case "ready":
return "[connected to " + event.Text + "]"
func eventText(event Event) string {
switch event.Kind {
case "ready":
return "[connected to " + event.Text + "]"
+ case "user":
+ if event.Source == terminalSource {
+ return ""
+ }
+
+ return "[" + event.Source + "] " + event.Text
case "reply":
return event.Text
case "tool":
case "reply":
return event.Text
case "tool":
// socketPathBytes is the longest path of a Unix socket on Linux.
socketPathBytes = 107
// socketPathBytes is the longest path of a Unix socket on Linux.
socketPathBytes = 107
+
+ // terminalSource is the source of the user messages from the clients of
+ // the socket.
+ terminalSource = "terminal"
)
// errTokensInUse tells that another onechat process uses the token file.
)
// errTokensInUse tells that another onechat process uses the token file.
return errors.New("empty message")
}
return errors.New("empty message")
}
- _, err := l.Submit(request.Text)
+ _, err := l.Submit(terminalSource, request.Text)
return err
case "interrupt":
return err
case "interrupt":
- name: "user message not shown",
- event: Event{Kind: "user", Text: "typed"},
+ name: "own user message not shown",
+ event: Event{Kind: "user", Text: "typed", Source: terminalSource},
+ {
+ name: "user message of another source marked",
+ event: Event{Kind: "user", Text: "from the phone", Source: "telegram"},
+ text: "[telegram] from the phone",
+ },
{
name: "long result cut",
event: Event{Kind: "echo", Text: strings.Repeat("line\n", 12)},
{
name: "long result cut",
event: Event{Kind: "echo", Text: strings.Repeat("line\n", 12)},
// Event tells the clients what the agent does as it happens. Kind is the kind
// of a logged message (user, reply, tool, echo), or one of ready, busy, idle,
// Event tells the clients what the agent does as it happens. Kind is the kind
// of a logged message (user, reply, tool, echo), or one of ready, busy, idle,
-// and error. ID is the ID of a logged message.
+// and error. ID is the ID of a logged message. Source names the client that
+// sent a user message, such as terminal or telegram, so that each client can
+// show the messages of the others.
- Kind string `json:"kind"`
- ID int `json:"id,omitempty"`
- Text string `json:"text,omitempty"`
+ Kind string `json:"kind"`
+ ID int `json:"id,omitempty"`
+ Text string `json:"text,omitempty"`
+ Source string `json:"source,omitempty"`
}
// loop runs the turns of one agent. A user message goes to the log when it
}
// loop runs the turns of one agent. A user message goes to the log when it
-// Submit logs a user message and wakes the loop. The message joins the next
-// request: the first one of a new turn, or the next one of a running turn.
-func (l *loop) Submit(text string) (Message, error) {
- message, err := l.Append("user", text)
+// Submit logs a user message from the client source and wakes the loop. The
+// message joins the next request: the first one of a new turn, or the next one
+// of a running turn.
+func (l *loop) Submit(source, text string) (Message, error) {
+ message, err := l.record("user", source, text)
if err != nil {
return Message{}, err
}
if err != nil {
return Message{}, err
}
// Append logs a message and tells the clients. The toolbox logs its calls and
// results through it.
func (l *loop) Append(kind, text string) (Message, error) {
// Append logs a message and tells the clients. The toolbox logs its calls and
// results through it.
func (l *loop) Append(kind, text string) (Message, error) {
+ return l.record(kind, "", text)
+}
+
+// record logs a message and tells the clients, with the client source of a user
+// message.
+func (l *loop) record(kind, source, text string) (Message, error) {
message, err := l.memory.Append(kind, text)
if err != nil {
return Message{}, err
}
l.notify(Event{
message, err := l.memory.Append(kind, text)
if err != nil {
return Message{}, err
}
l.notify(Event{
- Kind: kind,
- ID: message.ID,
- Text: text,
+ Kind: kind,
+ ID: message.ID,
+ Text: text,
+ Source: source,
}
test := newTestLoop(t, server)
}
test := newTestLoop(t, server)
- _, err := test.loop.Submit("Run echo hi.")
+ _, err := test.loop.Submit(terminalSource, "Run echo hi.")
require.NoError(t, err)
test.events.WaitFor(t, "idle", 1)
require.Equal(t, 2, server.Calls())
require.NoError(t, err)
test.events.WaitFor(t, "idle", 1)
require.Equal(t, 2, server.Calls())
_, err := test.memory.Append("user", "an earlier message")
require.NoError(t, err)
_, err := test.memory.Append("user", "an earlier message")
require.NoError(t, err)
- _, err = test.loop.Submit("The new message.")
+ _, err = test.loop.Submit(terminalSource, "The new message.")
require.NoError(t, err)
test.events.WaitFor(t, "idle", 1)
require.NoError(t, err)
test.events.WaitFor(t, "idle", 1)
}
test := newTestLoop(t, server)
}
test := newTestLoop(t, server)
- _, err := test.loop.Submit("first")
+ _, err := test.loop.Submit(terminalSource, "first")
require.NoError(t, err)
<-arrived
require.NoError(t, err)
<-arrived
- _, err = test.loop.Submit("second, during the turn")
+ _, err = test.loop.Submit(terminalSource, "second, during the turn")
require.NoError(t, err)
close(release)
require.NoError(t, err)
close(release)
}
test := newTestLoop(t, server)
}
test := newTestLoop(t, server)
- _, err := test.loop.Submit("first")
+ _, err := test.loop.Submit(terminalSource, "first")
require.NoError(t, err)
<-arrived
require.NoError(t, err)
<-arrived
- _, err = test.loop.Submit("second")
+ _, err = test.loop.Submit(terminalSource, "second")
require.NoError(t, err)
close(release)
require.NoError(t, err)
close(release)
_, err := test.memory.Append("echo", strings.Repeat("long output ", 100))
require.NoError(t, err)
_, err := test.memory.Append("echo", strings.Repeat("long output ", 100))
require.NoError(t, err)
- _, err = test.loop.Submit("go on")
+ _, err = test.loop.Submit(terminalSource, "go on")
require.NoError(t, err)
time.Sleep(50 * time.Millisecond)
require.NoError(t, err)
time.Sleep(50 * time.Millisecond)
}
test := newTestLoop(t, server)
}
test := newTestLoop(t, server)
- _, err := test.loop.Submit("a long task")
+ _, err := test.loop.Submit(terminalSource, "a long task")
require.NoError(t, err)
<-arrived
require.NoError(t, err)
<-arrived
require.Equal(t, []string{"user: a long task"}, test.Log(t))
require.False(t, test.loop.Interrupt())
require.Equal(t, []string{"user: a long task"}, test.Log(t))
require.False(t, test.loop.Interrupt())
- _, err = test.loop.Submit("again")
+ _, err = test.loop.Submit(terminalSource, "again")
require.NoError(t, err)
test.events.WaitFor(t, "idle", 2)
require.Equal(t, "reply: answer", test.Log(t)[2])
require.NoError(t, err)
test.events.WaitFor(t, "idle", 2)
require.Equal(t, "reply: answer", test.Log(t)[2])
}
test := newTestLoop(t, server)
}
test := newTestLoop(t, server)
- _, err := test.loop.Submit("hello")
+ _, err := test.loop.Submit(terminalSource, "hello")
require.NoError(t, err)
test.events.WaitFor(t, "idle", 1)
require.NoError(t, err)
test.events.WaitFor(t, "idle", 1)
server := newFakeResponses(t)
test := newTestLoop(t, server)
for n, text := range []string{"one", "two", "three"} {
server := newFakeResponses(t)
test := newTestLoop(t, server)
for n, text := range []string{"one", "two", "three"} {
- _, err := test.loop.Submit(text)
+ _, err := test.loop.Submit(terminalSource, text)
require.NoError(t, err)
test.events.WaitFor(t, "idle", n+1)
}
require.NoError(t, err)
test.events.WaitFor(t, "idle", n+1)
}