refactor: unify agent history and harden runtime diagnostics
Preserve user guidance through history compression, stabilize Flash index targets, and retire withdrawn checks without applying stale verdicts. Improve runtime diagnostics, tool responses, and history rendering. Simplify documentation and comments. Validation: 2076 tests passed in the full suite; 381 affected tests and 26 frontend tests passed after cleanup. Ruff and the quality ratchet passed.
This commit is contained in:
1 parent
e983180b5b
commit
5d92939d91
127 files changed
+13738
-1988
No files matched your search
@@ -725,21 +725,31 @@ export function getCompressionLabel(tool: any): string {
|
||||
: 'earlier steps';
|
||||
const rangeCapitalized = range.charAt(0).toUpperCase() + range.slice(1);
|
||||
const status = String(tool?.status || '').toLowerCase();
|
||||
const phase = getCompressionPhase(tool);
|
||||
|
||||
if (status === 'failed') {
|
||||
if (status === 'failed' || phase === 'failed') {
|
||||
return `Couldn't condense ${range} yet; keeping the full record and retrying later`;
|
||||
}
|
||||
if (status !== 'success') {
|
||||
return String(args.note || '').toLowerCase() === 'retrying'
|
||||
? `Retrying the memory summary for ${range}…`
|
||||
: `Condensing ${range} into a short memory to free up room…`;
|
||||
const note = String(args.note || '').toLowerCase();
|
||||
if (note === 'retrying') return `Retrying the memory summary for ${range}…`;
|
||||
if (note === 'held' || phase === 'ready') {
|
||||
const swapAt = Number(args.swap_at_tokens);
|
||||
const heldContext = Number(args.context_tokens);
|
||||
const heldParts = [`Short memory for ${range} is ready; keeping the full record until working memory fills up`];
|
||||
if (heldContext > 0 && swapAt > 0) {
|
||||
heldParts.push(`≈ ${formatTokenFigure(heldContext)} of ${formatTokenFigure(swapAt)} tokens`);
|
||||
}
|
||||
return heldParts.join(' · ');
|
||||
}
|
||||
return `Condensing ${range} into a short memory to free up room…`;
|
||||
}
|
||||
|
||||
const parts: string[] = [];
|
||||
const source = Number(args.source_tokens);
|
||||
const summary = Number(args.summary_tokens);
|
||||
if (args.forced) {
|
||||
parts.push(`${rangeCapitalized} replaced by a brief snapshot (memory was nearly full)`);
|
||||
parts.push(`${rangeCapitalized} condensed into a recap to free up memory`);
|
||||
} else {
|
||||
parts.push(`${rangeCapitalized} condensed into a short memory`);
|
||||
if (source > 0 && summary > 0) {
|
||||
@@ -758,6 +768,57 @@ export function getCompressionLabel(tool: any): string {
|
||||
return parts.join(' · ');
|
||||
}
|
||||
|
||||
/**
|
||||
* Plain-language phases of one compress_history line. Mirrors
|
||||
* COMPRESSION_PHASES in artemis/memory/chunking.py: the backend writes
|
||||
* `args.phase`; the trace `status` (running/success/failed) is left alone.
|
||||
*/
|
||||
export type CompressionPhase = 'summarizing' | 'ready' | 'applied' | 'failed';
|
||||
|
||||
const COMPRESSION_PHASES: readonly CompressionPhase[] = ['summarizing', 'ready', 'applied', 'failed'];
|
||||
|
||||
export function isCompressionTool(tool: any): boolean {
|
||||
const name = String(tool?.name || '').toLowerCase().replace(/^(_)?exec_/, '');
|
||||
return name === 'compress_history';
|
||||
}
|
||||
|
||||
/**
|
||||
* Phase of a compress_history line. Prefers the backend's `args.phase`;
|
||||
* older traces without it fall back to status + note (`held` ⇒ ready).
|
||||
*/
|
||||
export function getCompressionPhase(tool: any): CompressionPhase {
|
||||
const args = getToolArgs(tool) || {};
|
||||
const declared = String(args.phase || '').toLowerCase() as CompressionPhase;
|
||||
if (COMPRESSION_PHASES.includes(declared)) return declared;
|
||||
const status = String(tool?.status || '').toLowerCase();
|
||||
if (status === 'failed') return 'failed';
|
||||
if (status === 'success') return 'applied';
|
||||
if (String(args.note || '').toLowerCase() === 'held') return 'ready';
|
||||
return 'summarizing';
|
||||
}
|
||||
|
||||
/** One short, non-technical label per compression phase. */
|
||||
export function getCompressionPhaseLabel(tool: any): string {
|
||||
switch (getCompressionPhase(tool)) {
|
||||
case 'ready':
|
||||
return 'Summary ready; kept in reserve until the context fills up';
|
||||
case 'applied':
|
||||
return 'Replaced this stretch with its summary';
|
||||
case 'failed':
|
||||
return 'Summary failed; full record kept';
|
||||
default:
|
||||
return 'Summarizing this stretch';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A ready-but-held summary is waiting, not working: the card must not keep
|
||||
* its running pulse even though the trace status is still `running`.
|
||||
*/
|
||||
export function isCompressionWaiting(tool: any): boolean {
|
||||
return isCompressionTool(tool) && getCompressionPhase(tool) === 'ready';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Material Symbol icon for tools
|
||||
*/
|
||||
|
||||
Reference in new issue
Block a user