]> git.giacomolli.uk - onechat/commitdiff
Reflow comments and expand event literals
authorAnderson A. Giacomolli <redacted>
Wed, 11 Nov 2026 13:59:17 +0000 (10:59 -0300)
committerAnderson A. Giacomolli <redacted>
Wed, 11 Nov 2026 13:59:17 +0000 (10:59 -0300)
Comment paragraphs use the repository reflow tool, and event literals
put each field on its own line. The Telegram request comment
distinguishes method-bearing setup errors from safe network causes. Code
behavior and error values stay unchanged.

Issue: 3cdc678

14 files changed:
chain.go
chatgpt.go
config.go
daemon.go
prompt.go
subagent_run.go
subagent_run_test.go
telegram.go
telegram_api.go
terminal_test.go
tools.go
view_layout.go
whatsapp_groups.go
whatsapp_state_test.go

index 59ce563524543d058a7809633451f09a867f02ef..f201812d31ba2440309c7e151e2d0b9df2c26f45 100644 (file)
--- a/chain.go
+++ b/chain.go
@@ -22,10 +22,10 @@ type ChainClient interface {
 // answer. The replies, the tool calls, and the results go to the log of tools
 // as they happen. The thoughts never do.
 //
-// Each later request begins with the whole input of the request before it,
-// then its output items, then the tool results. The output items hold the
-// reasoning with its encrypted content, because the calls do not store it. So
-// each request begins with all of the previous one and reads it from the prompt
+// Each later request begins with the whole input of the request before it, then
+// its output items, then the tool results. The output items hold the reasoning
+// with its encrypted content, because the calls do not store it. So each
+// request begins with all of the previous one and reads it from the prompt
 // cache. The messages of take join each later request after the tool results.
 type Chain struct {
        client  ChainClient
@@ -43,8 +43,7 @@ type ChainFunctionCall struct {
        CallID    string `json:"call_id"`
 }
 
-// ChainFunctionCallOutput is the input item with the result of a function
-// call.
+// ChainFunctionCallOutput is the input item with the result of a function call.
 type ChainFunctionCallOutput struct {
        Type   string `json:"type"`
        CallID string `json:"call_id"`
@@ -52,8 +51,7 @@ type ChainFunctionCallOutput struct {
 }
 
 // Run runs the chain from input, the input of its first request, and returns
-// the text of the final answer. An error of a log write wraps
-// errChainLogWrite.
+// the text of the final answer. An error of a log write wraps errChainLogWrite.
 func (c *Chain) Run(ctx context.Context, input []any) (string, error) {
        request := c.request
        for request.Turn = "first"; ; request.Turn = "next" {
@@ -77,9 +75,9 @@ func (c *Chain) Run(ctx context.Context, input []any) (string, error) {
 }
 
 // handle logs the replies of response and runs its tool calls. It returns the
-// input of the next request: input, the output items, the tool results, and
-// the messages of take. After the final answer it returns no input, and the
-// replies of the answer as its text.
+// input of the next request: input, the output items, the tool results, and the
+// messages of take. After the final answer it returns no input, and the replies
+// of the answer as its text.
 func (c *Chain) handle(ctx context.Context, input []any, response ModelResponse) ([]any, string, error) {
        var (
                outputs []any
index ad40abd8d365627ff7d4720ebc394b4112f3857e..89476fece0fc8ff3028ff3b5b465ec1aa86215bb 100644 (file)
@@ -134,8 +134,8 @@ func (a *ChatGPTAuth) Authorize(ctx context.Context, header http.Header) error {
 }
 
 // Login runs the device code login. It writes the link and the code for the
-// user to out, waits until the user approves the code, and writes the tokens
-// to the token file.
+// user to out, waits until the user approves the code, and writes the tokens to
+// the token file.
 func (a *ChatGPTAuth) Login(ctx context.Context, out io.Writer) error {
        a.mutex.Lock()
        defer a.mutex.Unlock()
index fb24c20111448c3baac9597ae2c7e2b6eab98307..d96a1a3b126c85bb3b3a8fdf214d4ec5935eac8f 100644 (file)
--- a/config.go
+++ b/config.go
@@ -78,8 +78,8 @@ func (c Config) validate() error {
        return nil
 }
 
-// defaultConfig returns the settings that apply when config.json does not
-// set them.
+// defaultConfig returns the settings that apply when config.json does not set
+// them.
 func defaultConfig() Config {
        return Config{
                Endpoint: configEndpointChatGPT,
index 9f71d801be1c985ee70590e7118e69eeba91abbb..ea253180228d342a5343a3915a6efcbdb88afe18 100644 (file)
--- a/daemon.go
+++ b/daemon.go
@@ -44,9 +44,9 @@ type DaemonClient struct {
        once   sync.Once
 }
 
-// Accept serves each client of listener until the listener closes. A new
-// client gets a ready event with the name of the agent, and a busy event when a
-// turn runs.
+// Accept serves each client of listener until the listener closes. A new client
+// gets a ready event with the name of the agent, and a busy event when a turn
+// runs.
 func (h *DaemonHub) Accept(ctx context.Context, listener net.Listener, l *TurnLoop) {
        for {
                conn, err := listener.Accept()
@@ -167,8 +167,8 @@ func (h *DaemonHub) send(client *DaemonClient, event Event) {
        }
 }
 
-// remove removes client, closes its connection, and ends its writer. The
-// caller holds the mutex.
+// remove removes client, closes its connection, and ends its writer. The caller
+// holds the mutex.
 func (h *DaemonHub) remove(client *DaemonClient) {
        delete(h.clients, client)
        client.once.Do(func() {
index 0571ecfc9cc103ec40a384b8e885f923faaab579..896038bda70cceb4dc516bc5995fccac73da972b 100644 (file)
--- a/prompt.go
+++ b/prompt.go
@@ -453,8 +453,8 @@ func promptObjectSchema(properties map[string]any) map[string]any {
        }
 }
 
-// promptEffortEnum returns the values of the effort of spawn: promptEfforts
-// and null.
+// promptEffortEnum returns the values of the effort of spawn: promptEfforts and
+// null.
 func promptEffortEnum() []any {
        values := make([]any, 0, len(promptEfforts)+1)
        for _, effort := range promptEfforts {
index 3df12ce74483725ed8d97883f938cd99bff175fc..1da858890c7992707dfed02e96b1ee36aedfeb33 100644 (file)
@@ -53,8 +53,8 @@ var errSubagentClosed = errors.New("the daemon stops, so no subagent starts")
 // work.json in the directory of the agent holds the names of the running
 // subagents. Each start and each end of a run writes it whole, but Close does
 // not, so after a stop of the daemon it names the runs that the stop cut, and
-// Resume goes on with them. The logs alone cannot tell this, because a stop
-// can cut a run just after its final reply.
+// Resume goes on with them. The logs alone cannot tell this, because a stop can
+// cut a run just after its final reply.
 //
 // Spawn and Tell split the view with the layout of the agent, which has no
 // lock. They are tools, so they run in the goroutine of the turns, as each
@@ -418,8 +418,8 @@ func (r *SubagentRuns) load() ([]string, error) {
        return file.Running, nil
 }
 
-// save writes the names of the running subagents to work.json. The caller
-// holds the mutex.
+// save writes the names of the running subagents to work.json. The caller holds
+// the mutex.
 func (r *SubagentRuns) save() error {
        file := SubagentWorkFile{
                Running: append([]string{}, slices.Sorted(maps.Keys(r.running))...),
@@ -558,8 +558,8 @@ func (r *SubagentRuns) chain(ctx context.Context, run *SubagentRun) (string, err
        return chain.Run(ctx, input)
 }
 
-// take returns the messages of Tell that wait for a request of run, and
-// removes them.
+// take returns the messages of Tell that wait for a request of run, and removes
+// them.
 func (r *SubagentRuns) take(run *SubagentRun) []Message {
        r.mutex.Lock()
        defer r.mutex.Unlock()
index efd387cccde2270fab18a6459758c3e8d112c446..389a4bf2d56ce11ff3c589f0a835fafb03d33e76 100644 (file)
@@ -532,8 +532,8 @@ func TestRestartReportsASubagentThatCannotGoOn(t *testing.T) {
 }
 
 // subagentTestStart runs a loop of agent with its memory and subagents in the
-// agent directory, as the daemon does. The returned function stops the loop
-// and closes the files.
+// agent directory, as the daemon does. The returned function stops the loop and
+// closes the files.
 func subagentTestStart(t *testing.T, agent *Agent, server *ModelFake, events *TurnEventRecorder, logger *slog.Logger) (*TurnLoop, *Memory, func()) {
        t.Helper()
 
@@ -562,8 +562,7 @@ func subagentTestStart(t *testing.T, agent *Agent, server *ModelFake, events *Tu
        }
 }
 
-// subagentTestChat returns each message of the chat in memory as
-// "kind: text".
+// subagentTestChat returns each message of the chat in memory as "kind: text".
 func subagentTestChat(t *testing.T, memory *Memory) []string {
        t.Helper()
 
@@ -593,8 +592,8 @@ func subagentTestLastItem(call ModelFakeCall) map[string]any {
        return input[len(input)-1].(map[string]any)
 }
 
-// subagentTestText returns the text of the user message item, or "" for
-// another item.
+// subagentTestText returns the text of the user message item, or "" for another
+// item.
 func subagentTestText(item map[string]any) string {
        content, _ := item["content"].([]any)
 
index 59ea9b4d928a1247e8e54cff2f1871c9b565c002..4f19c6242ba6f631c8aa8c07d97f06407588d04f 100644 (file)
@@ -74,10 +74,10 @@ type TelegramConfig struct {
 // itself, and as message entities only when Telegram refuses a rich message.
 // The rest is plain text. Tool calls do not go to the chat.
 //
-// The offset file holds the ID of the next update. It moves past an update
-// only after the message of the update is durable in the log, so a restart
-// does not lose a message. A crash between the flush and the offset write
-// makes Telegram send the update again, and the message repeats once.
+// The offset file holds the ID of the next update. It moves past an update only
+// after the message of the update is durable in the log, so a restart does not
+// lose a message. A crash between the flush and the offset write makes Telegram
+// send the update again, and the message repeats once.
 //
 // A failed Bot API call waits and tries again, from telegramRetryDelay up to
 // telegramRetryLimit, or as long as the Bot API asks. It never stops the agent.
index 3a44a0d201e3552386045ab668b8ae72bc65e177..0d44852f133e59d167543b967627d03b09bb1b73 100644 (file)
@@ -333,8 +333,8 @@ func (b *TelegramAPI) SendTyping(ctx context.Context, chat int64) error {
 
 // call sends one call of method with the JSON params and decodes its result
 // into result, when result is not nil. The call can take up to timeout. Its
-// errors tell the cause in plain words, with no method name, so that a log line
-// can say first what the call was for.
+// request setup errors name the method. Network and answer errors give a safe
+// cause, so the caller can add the operation without exposing the request URL.
 func (b *TelegramAPI) call(ctx context.Context, timeout time.Duration, method string, params, result any) error {
        ctx, cancel := context.WithTimeout(ctx, timeout)
        defer cancel()
index c93c46f84644e05a39b7ad424b68fecfeba7a1ac..6f451d8386ab4eb584617c7b279785f30863058f 100644 (file)
@@ -47,34 +47,56 @@ func TestEventText(t *testing.T) {
                text  string
        }{
                {
-                       name:  "reply as it is",
-                       event: Event{Kind: "reply", Text: "Done."},
-                       text:  "Done.",
+                       name: "reply as it is",
+                       event: Event{
+                               Kind: "reply",
+                               Text: "Done.",
+                       },
+                       text: "Done.",
                },
                {
-                       name:  "own user message not shown",
-                       event: Event{Kind: "user", Text: "typed", Source: terminalSource},
-                       text:  "",
+                       name: "own user message not shown",
+                       event: Event{
+                               Kind:   "user",
+                               Text:   "typed",
+                               Source: terminalSource,
+                       },
+                       text: "",
                },
                {
-                       name:  "user message of another source marked",
-                       event: Event{Kind: "user", Text: "from the phone", Source: "telegram"},
-                       text:  "[telegram] from the phone",
+                       name: "user message of another source marked",
+                       event: Event{
+                               Kind:   "user",
+                               Text:   "from the phone",
+                               Source: "telegram",
+                       },
+                       text: "[telegram] from the phone",
                },
                {
-                       name:  "start of a subagent",
-                       event: Event{Kind: "subagent", Text: "GreenOtter"},
-                       text:  "[GreenOtter] started",
+                       name: "start of a subagent",
+                       event: Event{
+                               Kind: "subagent",
+                               Text: "GreenOtter",
+                       },
+                       text: "[GreenOtter] started",
                },
                {
-                       name:  "report of a subagent whole",
-                       event: Event{Kind: "work", Text: "[GreenOtter]\nThere are 3 files.\n\nFull chat: zoom(\"GreenOtter\")", Source: "GreenOtter", Status: subagentFinished},
-                       text:  "[GreenOtter]\nThere are 3 files.\n\nFull chat: zoom(\"GreenOtter\")",
+                       name: "report of a subagent whole",
+                       event: Event{
+                               Kind:   "work",
+                               Text:   "[GreenOtter]\nThere are 3 files.\n\nFull chat: zoom(\"GreenOtter\")",
+                               Source: "GreenOtter",
+                               Status: subagentFinished,
+                       },
+                       text: "[GreenOtter]\nThere are 3 files.\n\nFull chat: zoom(\"GreenOtter\")",
                },
                {
-                       name:  "long result cut",
-                       event: Event{Kind: "echo", Text: strings.Repeat("line\n", 12)},
-                       text:  "[result] " + strings.Repeat("line\n", 9) + "line\n[2 more lines]",
+                       name: "long result cut",
+                       event: Event{
+                               Kind: "echo",
+                               Text: strings.Repeat("line\n", 12),
+                       },
+                       text: "[result] " + strings.Repeat("line\n", 9) + "line\n[2 more lines]",
                },
        }
 
index 94885ff43c01d45538518a70c3fe3544cb211f69..191bb251df369a99984dbbc683ac593b13b9d364 100644 (file)
--- a/tools.go
+++ b/tools.go
@@ -544,8 +544,7 @@ func (b *Toolbox) read(path string) (text string, err error) {
        return output.String(), nil
 }
 
-// write replaces the file at path with text, and makes its missing
-// directories.
+// write replaces the file at path with text, and makes its missing directories.
 func (b *Toolbox) write(path, text string) (string, error) {
        path = b.path(path)
        err := os.MkdirAll(filepath.Dir(path), 0o755)
@@ -561,8 +560,8 @@ func (b *Toolbox) write(path, text string) (string, error) {
        return fmt.Sprintf("wrote %d bytes to %s", len(text), path), nil
 }
 
-// edit replaces the one occurrence of old in the file at path with
-// replacement. It keeps the mode of the file.
+// edit replaces the one occurrence of old in the file at path with replacement.
+// It keeps the mode of the file.
 func (b *Toolbox) edit(path, old, replacement string) (string, error) {
        path = b.path(path)
        data, err := os.ReadFile(path)
@@ -592,8 +591,7 @@ func (b *Toolbox) edit(path, old, replacement string) (string, error) {
        return "edited " + path, nil
 }
 
-// path returns path, relative to the working directory when it is not
-// absolute.
+// path returns path, relative to the working directory when it is not absolute.
 func (b *Toolbox) path(path string) string {
        if filepath.IsAbs(path) {
                return path
index a2d4825a7d57b82897e798ec64a9e4913579509f..560abb21042ad854cb2e61fcbff4d0703b8ce624 100644 (file)
@@ -22,10 +22,10 @@ const viewLayoutFileName = "layout.json"
 // layout read the view of the turn before from the prompt cache in each of 10
 // turns, and with the view in one message it missed once in 5.
 //
-// The first message starts with "<chat>\n". The closing tag goes into the
-// state message after the view, so that no view message changes when lines
-// come. The layout keeps the line count and a hash of the text of each message
-// in layout.json, so it outlives a restart.
+// The first message starts with "<chat>\n". The closing tag goes into the state
+// message after the view, so that no view message changes when lines come. The
+// layout keeps the line count and a hash of the text of each message in
+// layout.json, so it outlives a restart.
 type ViewLayout struct {
        path     string
        Messages []ViewLayoutMessage `json:"messages"`
@@ -63,8 +63,8 @@ func loadViewLayout(path string) (*ViewLayout, error) {
 }
 
 // Split returns the view messages for lines and saves the layout. It keeps the
-// earlier messages up to the first one whose text differs, and puts the rest
-// of the lines into one new message.
+// earlier messages up to the first one whose text differs, and puts the rest of
+// the lines into one new message.
 func (l *ViewLayout) Split(lines []string) ([]string, error) {
        var (
                texts []string
index 5eedd5dc29e804472fcc4e6ca803c84c62454a4b..bc8bb2f67c29bd4e72ad5c9696ac1ef049541f20 100644 (file)
@@ -28,8 +28,8 @@ const (
 // WhatsAppGroups holds the names of the groups of the account, by the ID of the
 // group. They come from the events of the groups and from reads of the groups
 // from WhatsApp, and they stay in memory only. triedAt is the time of the last
-// read, and readAt the time of the last read that succeeded. The mutex
-// protects all fields after logger.
+// read, and readAt the time of the last read that succeeded. The mutex protects
+// all fields after logger.
 type WhatsAppGroups struct {
        logger *slog.Logger
 
index 1cfedeef567521bb4f1f18226cec6ed21cbe390f..86e83daf9eafc1cb5898e782ee7364ba5b1ab02b 100644 (file)
@@ -154,8 +154,8 @@ func TestWhatsAppStateKeepsTheLastSendRecords(t *testing.T) {
        require.True(t, found)
 }
 
-// whatsappTestState opens the batches of the state file at path with the
-// times of the plan.
+// whatsappTestState opens the batches of the state file at path with the times
+// of the plan.
 func whatsappTestState(t *testing.T, path string) *WhatsAppState {
        t.Helper()