]> git.giacomolli.uk - onechat/commitdiff
Give the rebuild its own call limit
authorAnderson A. Giacomolli <redacted>
Mon, 9 Nov 2026 21:56:19 +0000 (18:56 -0300)
committerAnderson A. Giacomolli <redacted>
Mon, 9 Nov 2026 21:56:19 +0000 (18:56 -0300)
A rebuild summarizes the whole merged log, so it can need more calls
than a probe sample. The import of two chats estimates 647 calls, close
to the 660 calls of the probe, and a stop at the limit swaps nothing and
wastes the calls. The rebuild now stops after 1,500 calls, and the quota
stop still guards the account. The probe keeps its own limit of 660
calls.

Issue: b0b8bf9

README.rst
build_run.go
probe.go
rebuild.go
whatsapp_import.go
whatsapp_import_test.go

index 9893fc40944ca89fc6675e97ebb724036d901b1a..d32c14bea23925849fa2181a376f453d33d4b98f 100644 (file)
@@ -401,13 +401,14 @@ exports before import: their text goes to the model as chat history.
 
 The import merges the full log in date order and builds its tree with
 real compactor calls, the agent prompt, and the agent cache key. It uses
-the probe's 660-call and 15-quota-point limits and prints the same usage
-report. Its estimate is about 1.3 calls per merged message, not a cost
-guarantee. A stopped or failed run leaves the agent unchanged. A new run
-starts over. Success keeps the other agent files and renames the old
-directory to ``agent-backup-TIMESTAMP`` before it installs the new one.
-Keep the backup until the new memory is checked, then start the daemon.
-Message IDs change to their positions in the merged log.
+a limit of 1,500 calls and the probe's 15-quota-point limit, and prints
+the same usage report. Its estimate is about 1.3 calls per merged
+message, not a cost guarantee. A stopped or failed run leaves the agent
+unchanged. A new run starts over. Success keeps the other agent files
+and renames the old directory to ``agent-backup-TIMESTAMP`` before it
+installs the new one. Keep the backup until the new memory is checked,
+then start the daemon. Message IDs change to their positions in the
+merged log.
 
 ***********
  Schedules
index da75679d321cd31e0ea3a74f9b770c8b874d63c6..9c27ff2146b7451a9d7c5c0a5e08864575a69a3e 100644 (file)
@@ -22,9 +22,6 @@ const buildLineBytes = 1 << 20
 // buildQuotaLimit is the largest increase in used quota points of a run.
 const buildQuotaLimit = 15.0
 
-// buildCallLimit is the most model calls of a run.
-const buildCallLimit = 660
-
 // BuildRun appends messages, builds their tree, and stops the run by the rules
 // of buildStop.
 type BuildRun struct {
index f5553ce5b73ec164e213f0b0be22b990f8b34223..d788fa99cfe7d2f95269be231b0815c04c10ff95 100644 (file)
--- a/probe.go
+++ b/probe.go
@@ -18,13 +18,16 @@ const (
        // probeName is the agent name of a probe run. The cache key comes from
        // it.
        probeName = "Probe"
+
+       // probeCallLimit is the most model calls of a probe run.
+       probeCallLimit = 660
 )
 
 // probe runs "onechat probe LOG COUNT [BUILDS]". It appends the first COUNT
 // messages of LOG, one JSON object {kind, text} per line, to a new chat in
 // probe/ in the data directory, and builds its tree with the real compactor.
 // Before each user message it waits for the builds, as a turn does. It stops at
-// the first failed call, after buildCallLimit calls, or when the used percent
+// the first failed call, after probeCallLimit calls, or when the used percent
 // of a quota window grows by more than buildQuotaLimit points. At the end it
 // reports the calls, the time per call, the calls at once, the cached share,
 // the quota, the retries, and the line sizes. BUILDS, from 1 to buildMax,
@@ -97,7 +100,7 @@ func probe(ctx context.Context, args []string, out io.Writer) (err error) {
 
        usagePath := filepath.Join(root, "usage.jsonl")
        client := newModelClient(address, auth, "onechat-"+probeName, usagePath)
-       client.LimitCalls(buildCallLimit)
+       client.LimitCalls(probeCallLimit)
 
        summarizer := ProbeSlotSummarizer{
                inner: newCompactor(client, probePrompt, config.Compactor),
index 52c0861eabfac5463057319bba263a80755bd295..91b5ae516498da3e5b91d2f4aed898c7230a7b02 100644 (file)
@@ -15,6 +15,11 @@ import (
        "time"
 )
 
+// rebuildCallLimit is the most model calls of a rebuild. A rebuild summarizes
+// the whole merged log, which can need more calls than a probe sample, and the
+// quota stop of the build run still guards the account.
+const rebuildCallLimit = 1500
+
 // rebuild merges added messages with the log of agent, in date order, and
 // builds a new memory beside it. The caller holds the token lock. The model
 // uses the original agent prompt and cache key. A failed or stopped build
@@ -55,7 +60,7 @@ func rebuild(ctx context.Context, agent *Agent, added []DatedMessage, client *Mo
                return "", fmt.Errorf("open rebuilt memory: %w", err)
        }
 
-       client.LimitCalls(buildCallLimit)
+       client.LimitCalls(rebuildCallLimit)
 
        run := BuildRun{
                memory:    memory,
index 81eb808816935547fbab2778d4099a19d2f6fa44..7071c8369495d05e29463f95bcaec5390d1147ab 100644 (file)
@@ -211,7 +211,7 @@ func (p WhatsAppImportPlan) Write(out io.Writer) error {
                "owner: " + owner,
                fmt.Sprintf("bytes: %d (new batch text)", p.bytes),
                fmt.Sprintf("messages: %d (merged log)", p.messages),
-               fmt.Sprintf("estimated calls: %.0f (about 1.3 per message, limit %d)", estimate, buildCallLimit),
+               fmt.Sprintf("estimated calls: %.0f (about 1.3 per message, limit %d)", estimate, rebuildCallLimit),
        }
 
        _, err = io.WriteString(out, strings.Join(lines, "\n")+"\n")
index d735f4c8b9aad51a72ac147d326c93b5e51d8e49..f93cd19d772112f545579268b954aa3af75c6a0f 100644 (file)
@@ -248,7 +248,7 @@ func TestWhatsAppImportPlanCommandDoesNotChangeAgentOrCallModel(t *testing.T) {
        require.NoError(t, whatsappImport(t.Context(), []string{"-n", whatsappImportSample(t)}, &report))
        require.Equal(t, before, rebuildTestSnapshot(t, agent.dir))
 
-       for _, want := range []string{"chats: 1", "Book Club", "batches: 5", "dates: ", "cutoff: none", "bytes: ", "messages: 6", "estimated calls: 8", "owner: unknown"} {
+       for _, want := range []string{"chats: 1", "Book Club", "batches: 5", "dates: ", "cutoff: none", "bytes: ", "messages: 6", "estimated calls: 8 (about 1.3 per message, limit 1500)", "owner: unknown"} {
                require.Contains(t, report.String(), want)
        }