From b5704eb361bf6e5257a2af7c9ed4877ad87d5ae0 Mon Sep 17 00:00:00 2001 From: Autumn-27 <53844290+Autumn-27@users.noreply.github.com> Date: Thu, 24 Sep 2026 13:11:28 -0400 Subject: [PATCH] =?UTF-8?q?refactor(graph=5Foverview):=20related=5Ftasks?= =?UTF-8?q?=20=E5=86=B7=E5=8C=BA=E7=BB=9F=E4=B8=80=E8=B5=B0=20coldDigestsR?= =?UTF-8?q?ecent=20=E5=B9=B6=E5=B0=81=E9=A1=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - coldDigestsRecent 改为接收 store 的自由函数,主概览与关联任务概览共用 - related_tasks 的 cold_digests 由无上限的 activeDigestBodies 换成 coldDigestsRecent(ts, 6):按最新成员时间排序、每源截 6,溢出 digest id 带 inherited/source_task_id 入 cold_digests_more,仍可 expand_digest 展开 - 删除随之无用的 activeDigestBodies --- agent/tools.go | 27 ++++++++++++++++----------- agent/tools_digest.go | 35 ++++++++--------------------------- 2 files changed, 24 insertions(+), 38 deletions(-) diff --git a/agent/tools.go b/agent/tools.go index 44379db..139a03a 100644 --- a/agent/tools.go +++ b/agent/tools.go @@ -501,7 +501,7 @@ func (t *ToolSet) graphOverviewData() map[string]any { // cold-digest §6.1: 折叠冷区的 digest body,按最新成员时间降序取前 N;被截的更旧 digest // 只给裸 id(仍可 expand_digest 展开),避免冷区唯一出口被无限拉长。 const coldDigestsCap = 15 - if cds, more := t.coldDigestsRecent(coldDigestsCap); len(cds) > 0 { + if cds, more := coldDigestsRecent(t.ts, coldDigestsCap); len(cds) > 0 { out["cold_digests"] = cds // [{id, body, member_count}] —— 直接读 body (§6.1) if len(more) > 0 { out["cold_digests_more"] = more // 被截断的更旧 digest 的 id;用 expand_digest(id) 展开 @@ -558,14 +558,15 @@ func inheritedMap(m map[string]any, sourceTaskID int64) map[string]any { } const ( - relatedOverviewTotalTextRunes = 48_000 - relatedOverviewMaxTextPerSource = 8_000 - relatedOverviewMaxGoalsPerSource = 8 - relatedOverviewMaxHintsPerSource = 6 - relatedOverviewMaxFactsPerSource = 12 - relatedOverviewMaxFindingsPerTask = 6 - relatedOverviewMaxIntentsPerTask = 8 - relatedOverviewMaxScopePerSource = 12 + relatedOverviewTotalTextRunes = 48_000 + relatedOverviewMaxTextPerSource = 8_000 + relatedOverviewMaxGoalsPerSource = 8 + relatedOverviewMaxHintsPerSource = 6 + relatedOverviewMaxFactsPerSource = 12 + relatedOverviewMaxFindingsPerTask = 6 + relatedOverviewMaxIntentsPerTask = 8 + relatedOverviewMaxScopePerSource = 12 + relatedOverviewMaxDigestsPerSource = 6 ) // overviewTextBudget bounds inherited prompt text while preserving a fair slice @@ -800,14 +801,18 @@ func (t *ToolSet) relatedTaskOverviews() []map[string]any { } } item["recent_intent_results"] = intentResults - // §2 cross-task: the source task's folded cold region, read-only. Members are + // §2 cross-task: the source task's folded cold region, read-only, newest-member + // first & capped like the current task's. Members (and overflow digests) are // resolvable via expand_digest(id)/node_detail(id), which search source tasks. - if cds := activeDigestBodies(ts); len(cds) > 0 { + if cds, more := coldDigestsRecent(ts, relatedOverviewMaxDigestsPerSource); len(cds) > 0 { for _, cd := range cds { cd["inherited"] = true cd["source_task_id"] = source.Task.TaskID } item["cold_digests"] = cds + if len(more) > 0 { + item["cold_digests_more"] = more // 被截断的更旧 digest 的 id;expand_digest(id) 展开 + } } if statsErr == nil { item["node_stats"] = stats diff --git a/agent/tools_digest.go b/agent/tools_digest.go index 0b3f8d9..937116f 100644 --- a/agent/tools_digest.go +++ b/agent/tools_digest.go @@ -2,8 +2,8 @@ package agent // cold-digest §6: graph_overview folding + the restore tools. // -// activeDigestBodies — builds the folded cold region for graph_overview: -// cold_digests (flat {id, body, member_count}). +// coldDigestsRecent — builds the folded cold region for graph_overview: +// cold_digests (flat {id, body, member_count}), newest-member first, capped. // expand_digest(id) — level-1 restore: a digest's member compact list. import ( @@ -35,34 +35,15 @@ func (t *ToolSet) digestMemberEntry(store *db.ExplorationStore, id int64) map[st return m } -// activeDigestBodies returns [{id, body, member_count}] for a store's active -// digests — the folded cold region as flat bodies (§6.1). Shared by the current -// task overview and the read-only related-task overview (§2 cross-task reuse). -func activeDigestBodies(store *db.ExplorationStore) []map[string]any { - ads, err := store.ActiveDigests() - if err != nil || len(ads) == 0 { - return nil - } - out := make([]map[string]any, 0, len(ads)) - for _, d := range ads { - var p struct { - Body string `json:"body"` - } - _ = json.Unmarshal(d.Payload, &p) - ms, _ := store.DigestMembers(d.ID) - out = append(out, map[string]any{"id": d.ID, "body": p.Body, "member_count": len(ms)}) - } - return out -} - -// coldDigestsRecent returns the current task's active digests as flat bodies for +// coldDigestsRecent returns a store's active digests as flat bodies for // graph_overview, ordered by the recency of their freshest member (max member id ≈ // latest cooled node — a digest near the live frontier is likelier relevant), and // capped at `cap`. Overflow digest ids are returned separately (moreIDs) so they // stay reachable via expand_digest even when not shown inline — cold_digests is the -// only exit for folded cold nodes. -func (t *ToolSet) coldDigestsRecent(cap int) (shown []map[string]any, moreIDs []int64) { - ads, err := t.ts.ActiveDigests() +// only exit for folded cold nodes. Shared by the current task overview and the +// read-only related-task overview (§2 cross-task reuse). +func coldDigestsRecent(store *db.ExplorationStore, cap int) (shown []map[string]any, moreIDs []int64) { + ads, err := store.ActiveDigests() if err != nil || len(ads) == 0 { return nil, nil } @@ -77,7 +58,7 @@ func (t *ToolSet) coldDigestsRecent(cap int) (shown []map[string]any, moreIDs [] Body string `json:"body"` } _ = json.Unmarshal(d.Payload, &p) - ms, _ := t.ts.DigestMembers(d.ID) // sorted asc → last = freshest + ms, _ := store.DigestMembers(d.ID) // sorted asc → last = freshest var fresh int64 if len(ms) > 0 { fresh = ms[len(ms)-1]