From 3c15cd2e898165bc622efb034ce6929bc7fd5c70 Mon Sep 17 00:00:00 2001 From: Gonzalo Aune Date: Tue, 28 Jul 2026 10:13:43 +0100 Subject: [PATCH] Revert "feat: add opt-in session summaries to /repo/agent (#1494)" This reverts commit a2c2f29a6d74dd72c13af8cd29cb15243595458b. --- mcp/src/graph/neo4j.ts | 9 ----- mcp/src/graph/queries.ts | 6 --- mcp/src/repo/agent.ts | 81 ++-------------------------------------- mcp/src/repo/index.ts | 26 ++----------- mcp/src/repo/session.ts | 40 -------------------- 5 files changed, 7 insertions(+), 155 deletions(-) diff --git a/mcp/src/graph/neo4j.ts b/mcp/src/graph/neo4j.ts index 985abb3c0..fd535f2f4 100644 --- a/mcp/src/graph/neo4j.ts +++ b/mcp/src/graph/neo4j.ts @@ -1664,15 +1664,6 @@ class Db { } } - async set_agent_session_summary(session_id: string, summary: string): Promise { - const session = this.resilientSession(); - try { - await session.run(Q.SET_AGENT_SESSION_SUMMARY_QUERY, { session_id, summary }); - } finally { - await session.close(); - } - } - async list_agent_sessions(): Promise { const session = this.resilientSession(); try { diff --git a/mcp/src/graph/queries.ts b/mcp/src/graph/queries.ts index 1096bc231..e84f20f31 100644 --- a/mcp/src/graph/queries.ts +++ b/mcp/src/graph/queries.ts @@ -332,12 +332,6 @@ SET n.end_time = toInteger($end_time), RETURN n `; -export const SET_AGENT_SESSION_SUMMARY_QUERY = ` -MATCH (n:AgentSession:${Data_Bank} {node_key: $session_id}) -SET n.summary = $summary -RETURN n.node_key -`; - export const LIST_AGENT_SESSIONS_QUERY = ` MATCH (n:AgentSession) WHERE n.file = 'session://generated' diff --git a/mcp/src/repo/agent.ts b/mcp/src/repo/agent.ts index 9f17dc8c6..d5eff31b8 100644 --- a/mcp/src/repo/agent.ts +++ b/mcp/src/repo/agent.ts @@ -46,8 +46,6 @@ import { sessionExists, saveSessionConfig, saveSessionMetadata, - saveSessionSummary, - saveSummaryToGraph, SessionConfig, StepMeta, } from "./session.js"; @@ -437,8 +435,6 @@ export interface GetContextOptions { commitList?: string[]; // Skip prepending repo info to the first prompt (handler-level; recorded in config) ignoreRepoInfo?: boolean; - summarize?: boolean; - summarizePrompt?: string; // Replay mode: `prompt` is a full ModelMessage[] (including the system turn) // that is run verbatim. No system prompt is generated, no enrichment blocks // are appended, no session history is loaded, no attachments are resolved, @@ -725,6 +721,7 @@ If the user's prompt mentions a sub-agent with an @mention (e.g. "@${validSubAge model, // Transparent replay: no code-generated system prompt — the system turn // (if any) must be present inside the replayed messages array. + instructions: transparent ? undefined : instructions, tools, stopWhen, stopSequences: ["[END_OF_ANSWER]"], @@ -886,27 +883,14 @@ export async function get_context( appendSearchProvenance(sessionId, provenanceCollector.entries); } - const summaryUsage = opts.summarize - ? await summarizeAfterTurn( - prepared, - newMessages, - opts.summarizePrompt || DEFAULT_SUMMARIZE_PROMPT, - ).catch((e) => { - console.error("[summarize] failed (non-fatal):", e); - return undefined; - }) - : undefined; - await appendSessionEnd(sessionId, { end_time: new Date().toISOString(), model: modelId, provider, duration_ms: duration, status: "success", - token_usage: summaryUsage ? normalizeUsage(addUsage(usage, summaryUsage.usage)) : usage, + token_usage: usage, }); - - if (summaryUsage?.summary) saveSummaryToGraph(sessionId, summaryUsage.summary); } const final = extractFinalAnswer(steps); @@ -987,28 +971,14 @@ export async function stream_context( const stepUsage = stepMetas.length > 0 ? normalizeUsage(addUsage(...stepMetas.map((step) => step.usage))) : normalizeUsage(usage); - - const summaryUsage = opts.summarize - ? await summarizeAfterTurn( - prepared, - newMessages, - opts.summarizePrompt || DEFAULT_SUMMARIZE_PROMPT, - ).catch((e) => { - console.error("[summarize] failed (non-fatal):", e); - return undefined; - }) - : undefined; - await appendSessionEnd(sessionId, { end_time: new Date().toISOString(), model: modelId, provider, duration_ms: duration, status: "success", - token_usage: summaryUsage ? normalizeUsage(addUsage(stepUsage, summaryUsage.usage)) : stepUsage, + token_usage: stepUsage, }); - - if (summaryUsage?.summary) saveSummaryToGraph(sessionId, summaryUsage.summary); } catch (e) { const aborted = isAbortError(e); if (aborted) { @@ -1029,51 +999,6 @@ export async function stream_context( }; } -export const DEFAULT_SUMMARIZE_PROMPT = `Summarize this session for a future reader who was not here. Answer directly from the conversation above — do not use any tools. - -Write prose under exactly these three headings: - -## What happened -What was asked, what was explored, and what was concluded or delivered. Name the specific files, functions, commands, and decisions. - -## Mistakes, wrong turns, and bad assumptions -This is the most important section. Record every incorrect assumption, every dead end, every search or tool call that returned nothing useful, every fix that had to be redone, and anything that behaved differently than expected. For each one, say what was believed and what turned out to be true. If the session ran clean, say so in one line. - -## Open threads -Unfinished work, unanswered questions, and anything deliberately deferred.`; - -async function summarizeAfterTurn( - prepared: PreparedAgent, - newMessages: ModelMessage[], - summarizePrompt: string, -): Promise<{ usage: ReturnType; summary: string } | undefined> { - const { sessionId } = prepared; - if (!sessionId) return; - - const params = { - messages: [ - ...prepared.previousMessages, - ...newMessages, - { role: "user", content: summarizePrompt } as ModelMessage, - ], - providerOptions: getProviderOptions(prepared.provider as any, undefined, prepared.modelId), - ...(prepared.abortSignal ? { abortSignal: prepared.abortSignal } : {}), - }; - const result = await prepared.agent.stream(params); - - const summary = extractFinalAnswer((await result.steps) ?? []).answer.trim(); - const usage = normalizeUsage(await result.totalUsage); - console.log("===> summarize_session", { - sessionId, - cache_read: usage.cache_read, - input: usage.input, - empty: !summary, - }); - - if (summary) saveSessionSummary(sessionId, { summary }); - return { usage, summary }; -} - /* curl -X POST -H "Content-Type: application/json" -d '{"repo_url": "https://github.com/stakwork/hive", "prompt": "how does auth work in the repo"}' "http://localhost:3355/repo/agent" diff --git a/mcp/src/repo/index.ts b/mcp/src/repo/index.ts index 9198c264d..79f04a54c 100644 --- a/mcp/src/repo/index.ts +++ b/mcp/src/repo/index.ts @@ -12,7 +12,7 @@ import { startTracking, endTracking } from "../busy.js"; import { services_agent } from "./services.js"; import { mocks_agent } from "./mocks.js"; import { ModelName } from "../aieo/src/index.js"; -import { SessionConfig, loadSession, loadSessionConfig, loadSessionMetadata, loadSessionSummary, sessionExists } from "./session.js"; +import { SessionConfig, loadSession, loadSessionConfig, loadSessionMetadata, sessionExists } from "./session.js"; import { McpServer } from "./mcpServers.js"; import { existsSync } from "fs"; import path from "path"; @@ -25,7 +25,6 @@ import { abortRequest, } from "./events.js"; import { db } from "../graph/neo4j.js"; -import { isTrue } from "../graph/utils.js"; import { describe_nodes_agent, embed_nodes_agent } from "./descriptions.js"; export { services_agent, mocks_agent, describe_nodes_agent, embed_nodes_agent }; @@ -159,8 +158,6 @@ function parseAgentBody(req: Request) { const maxTurns = typeof req.body.maxTurns === "number" ? req.body.maxTurns : undefined; const headers = normalizeHeaders(req.body.headers); const ignoreRepoInfo = req.body.ignoreRepoInfo as boolean | undefined; - const summarize = req.body.summarize as boolean | undefined; - const summarizePrompt = req.body.summarizePrompt as string | undefined; // Stakwork API key for the run-research tools. Server-to-server secret // (like `pat`/`apiKey`): read off the body, never exposed to the LLM. const stakworkApiKey = req.body.stakworkApiKey as string | undefined; @@ -203,7 +200,7 @@ function parseAgentBody(req: Request) { repoUrl, username, pat, commitList, prompt, messages, toolsConfig, schema, modelName, apiKey, baseUrl, logs, sessionId, sessionConfig, mcpServers, systemOverride, mode, skills, subAgents, ggnn, stream, repoList, maxTurns, headers, - ignoreRepoInfo, attachments, _metadata, webhookUrl, summarize, summarizePrompt, + ignoreRepoInfo, attachments, _metadata, webhookUrl, stakwork: stakworkApiKey ? { apiKey: stakworkApiKey, baseUrl: stakworkBaseUrl } : undefined, googleSheets, }; @@ -405,8 +402,6 @@ export async function repo_agent(req: Request, res: Response) { _metadata: body._metadata, commitList: body.commitList, ignoreRepoInfo: body.ignoreRepoInfo, - summarize: body.summarize, - summarizePrompt: body.summarizePrompt, }, ); @@ -533,8 +528,6 @@ export async function repo_agent(req: Request, res: Response) { _metadata: body._metadata, commitList: body.commitList, ignoreRepoInfo: body.ignoreRepoInfo, - summarize: body.summarize, - summarizePrompt: body.summarizePrompt, onStepEvent: (content) => { const events = filterStepContent(content); for (const ev of events) bus.emit(ev); @@ -663,8 +656,7 @@ export async function get_agent_tools(req: Request, res: Response) { export async function get_agent_session(req: Request, res: Response) { const sessionId = req.query.session_id as string || req.query.sessionId as string; - const summarize = isTrue((req.query.summarize as string) || ""); - console.log("===> GET /repo/agent/session", { hasSessionId: Boolean(sessionId), summarize }); + console.log("===> GET /repo/agent/session", { hasSessionId: Boolean(sessionId) }); if (!sessionId) { res.status(400).json({ error: "Missing session_id" }); @@ -680,17 +672,7 @@ export async function get_agent_session(req: Request, res: Response) { const messages = loadSession(sessionId); const config = loadSessionConfig(sessionId); const _metadata = loadSessionMetadata(sessionId); - if (!summarize) { - res.json({ sessionId, messages, config, _metadata }); - return; - } - res.json({ - sessionId, - messages, - config, - _metadata, - summary: loadSessionSummary(sessionId)?.summary ?? null, - }); + res.json({ sessionId, messages, config, _metadata }); } catch (e) { console.error("Error in get_agent_session", e); res.status(500).json({ error: "Internal server error" }); diff --git a/mcp/src/repo/session.ts b/mcp/src/repo/session.ts index a5f75d7fe..c9ec99da1 100644 --- a/mcp/src/repo/session.ts +++ b/mcp/src/repo/session.ts @@ -55,10 +55,6 @@ export interface SessionInitConfig { ignoreRepoInfo?: boolean; } -export interface SessionSummary { - summary: string; -} - export interface StepMeta { step: number; turn: number; @@ -233,10 +229,6 @@ export function deleteSession(sessionId: string): void { if (existsSync(metadataPath)) { unlinkSync(metadataPath); } - const summaryPath = getSummaryFile(sessionId); - if (existsSync(summaryPath)) { - unlinkSync(summaryPath); - } deleteAttachments(sessionId); } @@ -308,36 +300,6 @@ export function loadSessionMetadata(sessionId: string): unknown | null { } } -function getSummaryFile(sessionId: string): string { - const sessionDir = path.isAbsolute(SESSIONS_DIR) - ? SESSIONS_DIR - : path.join(process.cwd(), SESSIONS_DIR); - if (!existsSync(sessionDir)) { - mkdirSync(sessionDir, { recursive: true }); - } - return path.join(sessionDir, `${sessionId}.summary.json`); -} - -export function saveSessionSummary(sessionId: string, summary: SessionSummary): void { - writeFileSync(getSummaryFile(sessionId), JSON.stringify(summary, null, 2)); -} - -export function saveSummaryToGraph(sessionId: string, summary: string): void { - void db - ?.set_agent_session_summary(sessionId, summary) - .catch((e: unknown) => console.error("[sessions] Neo4j summary write failed:", e)); -} - -export function loadSessionSummary(sessionId: string): SessionSummary | null { - const filePath = getSummaryFile(sessionId); - if (!existsSync(filePath)) return null; - try { - return JSON.parse(readFileSync(filePath, "utf-8")) as SessionSummary; - } catch { - return null; - } -} - /** * Get the file path for a session's per-step metadata sidecar. * This is separate from the conversation JSONL to avoid corrupting session replay. @@ -582,8 +544,6 @@ export function pruneExpiredSessions(): number { if (existsSync(annPath)) unlinkSync(annPath); const configPath = filePath.replace(/\.jsonl$/, ".config.json"); if (existsSync(configPath)) unlinkSync(configPath); - const summaryPath = filePath.replace(/\.jsonl$/, ".summary.json"); - if (existsSync(summaryPath)) unlinkSync(summaryPath); deleteAttachments(sessionId); pruned++; }