@cydm/pie 2.6.10 → 2.6.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/builtin/extensions/ask-user/index.js +2 -2
- package/dist/builtin/extensions/plan-mode/index.js +2 -2
- package/dist/builtin/extensions/subagent/index.js +3 -3
- package/dist/builtin/extensions/todo/index.js +2 -2
- package/dist/chunks/{chunk-YUVGEY6X.js → chunk-AAEBH6KX.js} +28 -1
- package/dist/chunks/{chunk-PAC62XU4.js → chunk-HHNOENEH.js} +11 -2
- package/dist/chunks/{chunk-DFWWHVJL.js → chunk-PPEWRUMQ.js} +105 -14
- package/dist/chunks/{src-HPIBCE2I.js → src-OWQI5M6W.js} +1 -1
- package/dist/cli.js +1618 -190
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
createCliWebResearchHealthStore,
|
|
8
8
|
formatSize,
|
|
9
9
|
truncateHeadTail
|
|
10
|
-
} from "./chunks/chunk-
|
|
10
|
+
} from "./chunks/chunk-AAEBH6KX.js";
|
|
11
11
|
import {
|
|
12
12
|
AGENTS_CONTEXT_FILE_NAME,
|
|
13
13
|
AgentSessionController,
|
|
@@ -63,8 +63,8 @@ import {
|
|
|
63
63
|
setExtensionEnabledInSettings,
|
|
64
64
|
shouldPreserveExecutionStateForUserText,
|
|
65
65
|
supersedeExecutionState
|
|
66
|
-
} from "./chunks/chunk-
|
|
67
|
-
import "./chunks/chunk-
|
|
66
|
+
} from "./chunks/chunk-PPEWRUMQ.js";
|
|
67
|
+
import "./chunks/chunk-HHNOENEH.js";
|
|
68
68
|
import {
|
|
69
69
|
Deref,
|
|
70
70
|
EMPTY_ASSISTANT_CONTENT_ERROR,
|
|
@@ -63980,7 +63980,24 @@ var ProcessTerminal = class {
|
|
|
63980
63980
|
process.stdout.write(sequence);
|
|
63981
63981
|
}
|
|
63982
63982
|
}
|
|
63983
|
+
/** Bounce the dock icon once (iTerm2's OSC 1337 extension; verified live
|
|
63984
|
+
* on iTerm2 — its docs list "Post a notification"-adjacent attention as
|
|
63985
|
+
* OSC 1337 ; RequestAttention). WezTerm documents OSC 1337 only for file
|
|
63986
|
+
* upload, not attention; other terminals ignore unknown OSC per the
|
|
63987
|
+
* xterm spec, so emitting unconditionally is safe and future-proof.
|
|
63988
|
+
* Value 1 bounces exactly once; 2 would bounce until the user activates
|
|
63989
|
+
* the app, which is too pushy for a per-turn attention signal. No
|
|
63990
|
+
* Notification Center permission is involved, so this works even when
|
|
63991
|
+
* the host app's notifications are muted — the banner channel's
|
|
63992
|
+
* fallback for "I just need a dot". */
|
|
63993
|
+
requestAttention() {
|
|
63994
|
+
if (!process.stdout.isTTY) return;
|
|
63995
|
+
process.stdout.write(buildDockAttentionSequence());
|
|
63996
|
+
}
|
|
63983
63997
|
};
|
|
63998
|
+
function buildDockAttentionSequence() {
|
|
63999
|
+
return "\x1B]1337;RequestAttention=1\x07";
|
|
64000
|
+
}
|
|
63984
64001
|
var NOTIFICATION_UNSAFE_CHARS = /[\x00-\x1f\x7f-\x9f;]/g;
|
|
63985
64002
|
function sanitizeNotificationText(text) {
|
|
63986
64003
|
return text.replace(NOTIFICATION_UNSAFE_CHARS, "");
|
|
@@ -70154,6 +70171,68 @@ var SessionTraceWriter = class extends SessionTraceSnapshotWriter {
|
|
|
70154
70171
|
sessionManager;
|
|
70155
70172
|
};
|
|
70156
70173
|
|
|
70174
|
+
// src/runtime/context-signals.ts
|
|
70175
|
+
import { createHash as createHash4 } from "crypto";
|
|
70176
|
+
function applyContextSignalsToFooter(target) {
|
|
70177
|
+
if (!target.agent?.state) return;
|
|
70178
|
+
const signals = computeContextSignals(
|
|
70179
|
+
target,
|
|
70180
|
+
target.agent.state.systemPrompt ?? "",
|
|
70181
|
+
target.agent.state.tools,
|
|
70182
|
+
target.sessionManager.getMessages()
|
|
70183
|
+
);
|
|
70184
|
+
target.footer.setState({
|
|
70185
|
+
prefixHash: signals.prefixHash,
|
|
70186
|
+
prefixHashChanged: signals.prefixHashChanged,
|
|
70187
|
+
cacheHitRate: signals.cacheHitRate
|
|
70188
|
+
});
|
|
70189
|
+
}
|
|
70190
|
+
function computePromptPrefixHash(systemPrompt, tools) {
|
|
70191
|
+
return createHash4("sha256").update(
|
|
70192
|
+
JSON.stringify({
|
|
70193
|
+
systemPrompt,
|
|
70194
|
+
tools: tools.map((tool) => ({
|
|
70195
|
+
name: tool.name,
|
|
70196
|
+
description: tool.description ?? "",
|
|
70197
|
+
parameters: tool.parameters ?? null
|
|
70198
|
+
}))
|
|
70199
|
+
})
|
|
70200
|
+
).digest("hex").slice(0, 8);
|
|
70201
|
+
}
|
|
70202
|
+
function calculateCumulativeCacheHitRate(messages) {
|
|
70203
|
+
let input = 0;
|
|
70204
|
+
let cacheRead = 0;
|
|
70205
|
+
for (const message of messages) {
|
|
70206
|
+
if (message.role !== "assistant") continue;
|
|
70207
|
+
const usage = message.usage;
|
|
70208
|
+
if (!usage) continue;
|
|
70209
|
+
input += usage.input;
|
|
70210
|
+
cacheRead += usage.cacheRead;
|
|
70211
|
+
}
|
|
70212
|
+
const base = input + cacheRead;
|
|
70213
|
+
return base > 0 ? cacheRead / base : null;
|
|
70214
|
+
}
|
|
70215
|
+
var signalMemories = /* @__PURE__ */ new WeakMap();
|
|
70216
|
+
var lastSignals = /* @__PURE__ */ new WeakMap();
|
|
70217
|
+
function getLastContextSignals(hostKey) {
|
|
70218
|
+
return lastSignals.get(hostKey) ?? null;
|
|
70219
|
+
}
|
|
70220
|
+
function computeContextSignals(hostKey, systemPrompt, tools, messages) {
|
|
70221
|
+
const prefixHash = computePromptPrefixHash(systemPrompt, tools);
|
|
70222
|
+
const previous = signalMemories.get(hostKey);
|
|
70223
|
+
const prefixHashChanged = previous !== void 0 && previous.hash !== prefixHash;
|
|
70224
|
+
if (previous?.hash !== prefixHash) {
|
|
70225
|
+
signalMemories.set(hostKey, { hash: prefixHash });
|
|
70226
|
+
}
|
|
70227
|
+
const signals = {
|
|
70228
|
+
prefixHash,
|
|
70229
|
+
prefixHashChanged,
|
|
70230
|
+
cacheHitRate: calculateCumulativeCacheHitRate(messages)
|
|
70231
|
+
};
|
|
70232
|
+
lastSignals.set(hostKey, signals);
|
|
70233
|
+
return signals;
|
|
70234
|
+
}
|
|
70235
|
+
|
|
70157
70236
|
// src/commands/interactive-session-commands.ts
|
|
70158
70237
|
import * as os6 from "os";
|
|
70159
70238
|
|
|
@@ -70342,6 +70421,387 @@ var SessionSelectorComponent = class extends Container {
|
|
|
70342
70421
|
}
|
|
70343
70422
|
};
|
|
70344
70423
|
|
|
70424
|
+
// src/core/context-report.ts
|
|
70425
|
+
var APPROX_BYTES_PER_TOKEN = 4;
|
|
70426
|
+
function estimateStringTokens(text) {
|
|
70427
|
+
if (!text) return 0;
|
|
70428
|
+
return Math.ceil(Buffer.byteLength(text, "utf8") / APPROX_BYTES_PER_TOKEN);
|
|
70429
|
+
}
|
|
70430
|
+
function formatReportTokens(count) {
|
|
70431
|
+
if (count < 1e3) return String(count);
|
|
70432
|
+
if (count < 1e4) return `${(count / 1e3).toFixed(1)}k`;
|
|
70433
|
+
if (count < 1e6) return `${Math.round(count / 1e3)}k`;
|
|
70434
|
+
if (count < 1e7) return `${(count / 1e6).toFixed(1)}M`;
|
|
70435
|
+
return `${Math.round(count / 1e6)}M`;
|
|
70436
|
+
}
|
|
70437
|
+
function buildSystemPromptBlocks(systemPrompt, skillsSection, knowledgeSection) {
|
|
70438
|
+
const totalTokens = estimateStringTokens(systemPrompt);
|
|
70439
|
+
const skillsTokens = skillsSection && systemPrompt.includes(skillsSection.trim()) ? estimateStringTokens(skillsSection) : null;
|
|
70440
|
+
const knowledgeTokens = knowledgeSection && systemPrompt.includes(knowledgeSection.trim()) ? estimateStringTokens(knowledgeSection) : null;
|
|
70441
|
+
const accounted = (skillsTokens ?? 0) + (knowledgeTokens ?? 0);
|
|
70442
|
+
return {
|
|
70443
|
+
totalTokens,
|
|
70444
|
+
baseTokens: Math.max(0, totalTokens - accounted),
|
|
70445
|
+
skillsTokens,
|
|
70446
|
+
knowledgeTokens
|
|
70447
|
+
};
|
|
70448
|
+
}
|
|
70449
|
+
function escapeXmlName(name) {
|
|
70450
|
+
return name.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
70451
|
+
}
|
|
70452
|
+
function extractSkillBlocks(section) {
|
|
70453
|
+
if (!section) return [];
|
|
70454
|
+
return section.split(/(?=<skill>)/).map((block) => block.trim()).filter((block) => block.startsWith("<skill>"));
|
|
70455
|
+
}
|
|
70456
|
+
function buildSkillRows(skillsSection, skills) {
|
|
70457
|
+
const blocks = extractSkillBlocks(skillsSection);
|
|
70458
|
+
if (blocks.length === 0) {
|
|
70459
|
+
return [
|
|
70460
|
+
{
|
|
70461
|
+
id: "skills:none",
|
|
70462
|
+
label: "no skills in prompt",
|
|
70463
|
+
estTokens: 0
|
|
70464
|
+
}
|
|
70465
|
+
];
|
|
70466
|
+
}
|
|
70467
|
+
return blocks.map((block, index) => {
|
|
70468
|
+
const escapedNameMatch = block.match(/<name>([\s\S]*?)<\/name>/);
|
|
70469
|
+
const escapedName = escapedNameMatch?.[1] ?? "";
|
|
70470
|
+
const skill = skills.find((candidate) => escapeXmlName(candidate.name) === escapedName) ?? skills.find((candidate) => block.includes(escapeXmlName(candidate.name)));
|
|
70471
|
+
const estTokens = estimateStringTokens(block);
|
|
70472
|
+
const source = skill?.source ? `source:${skill.source}` : void 0;
|
|
70473
|
+
const detail = skill?.inlineContent !== void 0 ? "inline content (already loaded)" : skill?.filePath ?? void 0;
|
|
70474
|
+
return {
|
|
70475
|
+
id: `skill:${skill?.name ?? index}`,
|
|
70476
|
+
label: skill?.name ?? `<skill #${index + 1}>`,
|
|
70477
|
+
estTokens,
|
|
70478
|
+
note: source,
|
|
70479
|
+
detail,
|
|
70480
|
+
drill: {
|
|
70481
|
+
kind: "text",
|
|
70482
|
+
title: `Skill \xB7 ${skill?.name ?? `#${index + 1}`}`,
|
|
70483
|
+
text: block
|
|
70484
|
+
}
|
|
70485
|
+
};
|
|
70486
|
+
}).sort((a, b2) => b2.estTokens - a.estTokens);
|
|
70487
|
+
}
|
|
70488
|
+
function parseProjectContextSection(section) {
|
|
70489
|
+
const parts = section.split(/^### (.+)$/m);
|
|
70490
|
+
const files = [];
|
|
70491
|
+
for (let i = 1; i + 1 < parts.length + 1; i += 2) {
|
|
70492
|
+
const path34 = (parts[i] ?? "").trim();
|
|
70493
|
+
const content = (parts[i + 1] ?? "").trim();
|
|
70494
|
+
if (!path34 || !content) continue;
|
|
70495
|
+
files.push({ path: path34, content });
|
|
70496
|
+
}
|
|
70497
|
+
return files;
|
|
70498
|
+
}
|
|
70499
|
+
function buildKnowledgeRows(files) {
|
|
70500
|
+
if (files.length === 0) {
|
|
70501
|
+
return [
|
|
70502
|
+
{
|
|
70503
|
+
id: "knowledge:none",
|
|
70504
|
+
label: "no AGENTS.md files found",
|
|
70505
|
+
estTokens: 0
|
|
70506
|
+
}
|
|
70507
|
+
];
|
|
70508
|
+
}
|
|
70509
|
+
return files.map((file) => {
|
|
70510
|
+
const lineCount = file.content.split("\n").length;
|
|
70511
|
+
return {
|
|
70512
|
+
id: `knowledge:${file.path}`,
|
|
70513
|
+
label: file.path,
|
|
70514
|
+
estTokens: estimateStringTokens(file.content),
|
|
70515
|
+
note: `${lineCount} lines`,
|
|
70516
|
+
detail: `AGENTS.md`,
|
|
70517
|
+
drill: {
|
|
70518
|
+
kind: "text",
|
|
70519
|
+
title: `Project Context \xB7 ${file.path}`,
|
|
70520
|
+
text: file.content
|
|
70521
|
+
}
|
|
70522
|
+
};
|
|
70523
|
+
});
|
|
70524
|
+
}
|
|
70525
|
+
function estimateToolTokens(tool) {
|
|
70526
|
+
const parameters = tool.parameters === void 0 ? "" : JSON.stringify(tool.parameters);
|
|
70527
|
+
return estimateStringTokens(`${tool.name}
|
|
70528
|
+
${tool.description ?? ""}
|
|
70529
|
+
${parameters}`);
|
|
70530
|
+
}
|
|
70531
|
+
var MAX_TOOL_DRILL_CHARS = 6e3;
|
|
70532
|
+
function buildToolRows(tools) {
|
|
70533
|
+
if (tools.length === 0) {
|
|
70534
|
+
return [{ id: "tools:none", label: "no tools registered", estTokens: 0 }];
|
|
70535
|
+
}
|
|
70536
|
+
return tools.map((tool) => {
|
|
70537
|
+
const paramsJson = tool.parameters === void 0 ? "" : JSON.stringify(tool.parameters, null, 2);
|
|
70538
|
+
const drillText = [
|
|
70539
|
+
tool.description ? `# description
|
|
70540
|
+
${tool.description}` : "",
|
|
70541
|
+
paramsJson ? `# parameters (schema)
|
|
70542
|
+
${paramsJson}` : ""
|
|
70543
|
+
].filter(Boolean).join("\n\n").slice(0, MAX_TOOL_DRILL_CHARS);
|
|
70544
|
+
return {
|
|
70545
|
+
id: `tool:${tool.name}`,
|
|
70546
|
+
label: tool.name,
|
|
70547
|
+
estTokens: estimateToolTokens(tool),
|
|
70548
|
+
note: tool.label && tool.label !== tool.name ? tool.label : void 0,
|
|
70549
|
+
detail: tool.description?.split("\n")[0]?.slice(0, 120),
|
|
70550
|
+
drill: { kind: "text", title: `Tool \xB7 ${tool.name}`, text: drillText }
|
|
70551
|
+
};
|
|
70552
|
+
}).sort((a, b2) => b2.estTokens - a.estTokens);
|
|
70553
|
+
}
|
|
70554
|
+
function entryRoleTag(entry) {
|
|
70555
|
+
return entry.role ?? entry.type;
|
|
70556
|
+
}
|
|
70557
|
+
function buildMessageRows(entries, compactionTokensBefore) {
|
|
70558
|
+
if (entries.length === 0) {
|
|
70559
|
+
return [{ id: "messages:none", label: "active context is empty", estTokens: 0 }];
|
|
70560
|
+
}
|
|
70561
|
+
return entries.map((entry) => {
|
|
70562
|
+
const roleTag = entryRoleTag(entry);
|
|
70563
|
+
const isCompaction = entry.type === "compaction";
|
|
70564
|
+
const tokensBefore = isCompaction ? compactionTokensBefore?.(entry.id) : void 0;
|
|
70565
|
+
return {
|
|
70566
|
+
id: `entry:${entry.id}`,
|
|
70567
|
+
label: `#${entry.seq} ${roleTag}`,
|
|
70568
|
+
estTokens: entry.estTokens,
|
|
70569
|
+
roleTag,
|
|
70570
|
+
marker: isCompaction ? "\u2691" : void 0,
|
|
70571
|
+
note: isCompaction ? tokensBefore !== void 0 ? `checkpoint \xB7 context was ~${formatReportTokens(tokensBefore)} before` : "checkpoint" : entry.bodyBytes > 0 ? `${formatReportTokens(entry.bodyBytes)}B body` : void 0,
|
|
70572
|
+
detail: entry.preview,
|
|
70573
|
+
drill: { kind: "entry", entryId: entry.id }
|
|
70574
|
+
};
|
|
70575
|
+
});
|
|
70576
|
+
}
|
|
70577
|
+
var MAX_PROMPT_DRILL_CHARS = 12e3;
|
|
70578
|
+
function buildContextReportData(inputs) {
|
|
70579
|
+
const knowledgeSectionText = inputs.knowledgeFiles.map((file) => `### ${file.path}
|
|
70580
|
+
${file.content}`).join("\n\n");
|
|
70581
|
+
const blocks = buildSystemPromptBlocks(
|
|
70582
|
+
inputs.systemPrompt,
|
|
70583
|
+
inputs.skillsSection,
|
|
70584
|
+
knowledgeSectionText
|
|
70585
|
+
);
|
|
70586
|
+
const systemPromptRows = [
|
|
70587
|
+
{
|
|
70588
|
+
id: "prompt:base",
|
|
70589
|
+
label: "base prompt (persona + tool guidance + guidelines + docs)",
|
|
70590
|
+
estTokens: blocks.baseTokens,
|
|
70591
|
+
drill: {
|
|
70592
|
+
kind: "text",
|
|
70593
|
+
title: "System Prompt",
|
|
70594
|
+
text: inputs.systemPrompt.slice(0, MAX_PROMPT_DRILL_CHARS)
|
|
70595
|
+
}
|
|
70596
|
+
}
|
|
70597
|
+
];
|
|
70598
|
+
if (blocks.skillsTokens !== null || inputs.skills.length > 0) {
|
|
70599
|
+
systemPromptRows.push({
|
|
70600
|
+
id: "prompt:skills",
|
|
70601
|
+
label: "skills section",
|
|
70602
|
+
estTokens: blocks.skillsTokens ?? 0,
|
|
70603
|
+
note: `${inputs.skills.length} skills`,
|
|
70604
|
+
drill: {
|
|
70605
|
+
kind: "rows",
|
|
70606
|
+
title: "System Prompt \u203A Skills",
|
|
70607
|
+
rows: buildSkillRows(inputs.skillsSection, inputs.skills),
|
|
70608
|
+
rowKind: "plain"
|
|
70609
|
+
}
|
|
70610
|
+
});
|
|
70611
|
+
}
|
|
70612
|
+
if (blocks.knowledgeTokens !== null || inputs.knowledgeFiles.length > 0) {
|
|
70613
|
+
systemPromptRows.push({
|
|
70614
|
+
id: "prompt:knowledge",
|
|
70615
|
+
label: "project context (AGENTS.md)",
|
|
70616
|
+
estTokens: blocks.knowledgeTokens ?? 0,
|
|
70617
|
+
note: `${inputs.knowledgeFiles.length} files`,
|
|
70618
|
+
drill: {
|
|
70619
|
+
kind: "rows",
|
|
70620
|
+
title: "System Prompt \u203A Project Context",
|
|
70621
|
+
rows: buildKnowledgeRows(inputs.knowledgeFiles),
|
|
70622
|
+
rowKind: "plain"
|
|
70623
|
+
}
|
|
70624
|
+
});
|
|
70625
|
+
}
|
|
70626
|
+
const systemPromptSection = {
|
|
70627
|
+
id: "system-prompt",
|
|
70628
|
+
title: "System prompt",
|
|
70629
|
+
estTokens: blocks.totalTokens,
|
|
70630
|
+
note: `base ~${formatReportTokens(blocks.baseTokens)}`,
|
|
70631
|
+
rows: systemPromptRows
|
|
70632
|
+
};
|
|
70633
|
+
const toolRows = buildToolRows(inputs.tools);
|
|
70634
|
+
const toolsTokens = toolRows.reduce((sum, row) => sum + row.estTokens, 0);
|
|
70635
|
+
const toolsSection = {
|
|
70636
|
+
id: "tools",
|
|
70637
|
+
title: `Tools (${inputs.tools.length})`,
|
|
70638
|
+
estTokens: toolsTokens,
|
|
70639
|
+
note: toolRows[0] ? `largest: ${toolRows[0].label} ~${formatReportTokens(toolRows[0].estTokens)}` : void 0,
|
|
70640
|
+
rows: toolRows
|
|
70641
|
+
};
|
|
70642
|
+
const messageRows = buildMessageRows(inputs.entries, inputs.compactionTokensBefore);
|
|
70643
|
+
const messagesTokens = inputs.entries.reduce((sum, entry) => sum + entry.estTokens, 0);
|
|
70644
|
+
const messagesSection = {
|
|
70645
|
+
id: "messages",
|
|
70646
|
+
title: `Messages (${inputs.entries.length})`,
|
|
70647
|
+
estTokens: messagesTokens,
|
|
70648
|
+
rows: messageRows
|
|
70649
|
+
};
|
|
70650
|
+
const dynamicContextSection = {
|
|
70651
|
+
id: "dynamic-context",
|
|
70652
|
+
title: "Dynamic context",
|
|
70653
|
+
estTokens: 0,
|
|
70654
|
+
note: "unmetered",
|
|
70655
|
+
rows: [
|
|
70656
|
+
{
|
|
70657
|
+
id: "dynamic:runtime-mode",
|
|
70658
|
+
label: "runtime-mode per-turn injections are not counted in these estimates",
|
|
70659
|
+
estTokens: 0,
|
|
70660
|
+
detail: "the host injects a <runtime-mode-context> block (mode flags, date, active tool names) on every request via transformContext; it is part of the est\u2212actual gap below"
|
|
70661
|
+
}
|
|
70662
|
+
]
|
|
70663
|
+
};
|
|
70664
|
+
const roleCountsMap = /* @__PURE__ */ new Map();
|
|
70665
|
+
for (const entry of inputs.entries) {
|
|
70666
|
+
const tag = entryRoleTag(entry);
|
|
70667
|
+
roleCountsMap.set(tag, (roleCountsMap.get(tag) ?? 0) + 1);
|
|
70668
|
+
}
|
|
70669
|
+
const roleCounts = [...roleCountsMap.entries()].map(([role, count]) => ({ role, count })).sort((a, b2) => b2.count - a.count || a.role.localeCompare(b2.role));
|
|
70670
|
+
const topEntries = [...inputs.entries].sort((a, b2) => b2.estTokens - a.estTokens).slice(0, 5).map((entry) => ({
|
|
70671
|
+
seq: entry.seq,
|
|
70672
|
+
label: `${entryRoleTag(entry)} \xB7 ${entry.preview}`.trim(),
|
|
70673
|
+
estTokens: entry.estTokens
|
|
70674
|
+
}));
|
|
70675
|
+
let latestCompaction = null;
|
|
70676
|
+
for (const entry of inputs.entries) {
|
|
70677
|
+
if (entry.type === "compaction") {
|
|
70678
|
+
latestCompaction = {
|
|
70679
|
+
seq: entry.seq,
|
|
70680
|
+
tokensBefore: inputs.compactionTokensBefore?.(entry.id)
|
|
70681
|
+
};
|
|
70682
|
+
}
|
|
70683
|
+
}
|
|
70684
|
+
const estimatedTotalTokens = blocks.totalTokens + toolsTokens + messagesTokens;
|
|
70685
|
+
return {
|
|
70686
|
+
sections: [systemPromptSection, toolsSection, messagesSection, dynamicContextSection],
|
|
70687
|
+
systemPromptTokens: blocks.totalTokens,
|
|
70688
|
+
toolsTokens,
|
|
70689
|
+
messagesTokens,
|
|
70690
|
+
dynamicContextTokens: 0,
|
|
70691
|
+
estimatedTotalTokens,
|
|
70692
|
+
actualTokens: inputs.actualTokens,
|
|
70693
|
+
contextWindow: inputs.contextWindow,
|
|
70694
|
+
autoCompactLimitTokens: inputs.autoCompactLimitTokens,
|
|
70695
|
+
reserveTokens: inputs.reserveTokens,
|
|
70696
|
+
promptPrefixHash: inputs.promptPrefixHash,
|
|
70697
|
+
promptPrefixChanged: inputs.promptPrefixChanged,
|
|
70698
|
+
roleCounts,
|
|
70699
|
+
topEntries,
|
|
70700
|
+
latestCompaction,
|
|
70701
|
+
entryCount: inputs.entries.length
|
|
70702
|
+
};
|
|
70703
|
+
}
|
|
70704
|
+
var identityTheme = {
|
|
70705
|
+
bold: (text) => text,
|
|
70706
|
+
fg: (_token, text) => text
|
|
70707
|
+
};
|
|
70708
|
+
function padEndVisible(text, width) {
|
|
70709
|
+
return text.length >= width ? text : text + " ".repeat(width - text.length);
|
|
70710
|
+
}
|
|
70711
|
+
function formatReportHeadline(data) {
|
|
70712
|
+
const est = `~${formatReportTokens(data.estimatedTotalTokens)}`;
|
|
70713
|
+
if (data.contextWindow > 0) {
|
|
70714
|
+
const percent = (data.estimatedTotalTokens / data.contextWindow * 100).toFixed(1);
|
|
70715
|
+
return `est ${est} / ${formatReportTokens(data.contextWindow)} (${percent}%)`;
|
|
70716
|
+
}
|
|
70717
|
+
return `est ${est} / window unknown`;
|
|
70718
|
+
}
|
|
70719
|
+
function buildContextOverviewText(data, themeInput) {
|
|
70720
|
+
const theme2 = themeInput ?? identityTheme;
|
|
70721
|
+
const lines = [];
|
|
70722
|
+
const sections = data.sections;
|
|
70723
|
+
lines.push(theme2.bold("Context Report") + theme2.fg("dim", ` \xB7 ${formatReportHeadline(data)}`));
|
|
70724
|
+
const labelWidth = 20;
|
|
70725
|
+
const branch = (index) => index === sections.length ? "\u2514" : "\u251C";
|
|
70726
|
+
sections.forEach((section, index) => {
|
|
70727
|
+
const label = padEndVisible(` ${branch(index)} ${section.title}`, labelWidth);
|
|
70728
|
+
const tokens = `~${formatReportTokens(section.estTokens)}`;
|
|
70729
|
+
const note = section.note ? theme2.fg("dim", ` ${section.note}`) : "";
|
|
70730
|
+
lines.push(`${label}${theme2.fg("accent", tokens)}${note}`);
|
|
70731
|
+
if (section.id === "messages") {
|
|
70732
|
+
const counts = data.roleCounts.map((rc) => `${rc.role} ${rc.count}`).join(" \xB7 ");
|
|
70733
|
+
if (counts) {
|
|
70734
|
+
lines.push(`${" ".repeat(labelWidth + 1)}${theme2.fg("dim", counts)}`);
|
|
70735
|
+
}
|
|
70736
|
+
for (const top of data.topEntries.slice(0, 3)) {
|
|
70737
|
+
const preview = top.label.length > 60 ? `${top.label.slice(0, 59)}\u2026` : top.label;
|
|
70738
|
+
lines.push(
|
|
70739
|
+
`${" ".repeat(labelWidth + 1)}${theme2.fg("dim", `top: #${top.seq} ${preview} (~${formatReportTokens(top.estTokens)})`)}`
|
|
70740
|
+
);
|
|
70741
|
+
}
|
|
70742
|
+
if (data.latestCompaction) {
|
|
70743
|
+
const before = data.latestCompaction.tokensBefore !== void 0 ? ` \xB7 context was ~${formatReportTokens(data.latestCompaction.tokensBefore)} before` : "";
|
|
70744
|
+
lines.push(
|
|
70745
|
+
`${" ".repeat(labelWidth + 1)}${theme2.fg("dim", `\u2691 compact checkpoint @#${data.latestCompaction.seq}${before}`)}`
|
|
70746
|
+
);
|
|
70747
|
+
}
|
|
70748
|
+
}
|
|
70749
|
+
});
|
|
70750
|
+
const autoCompact = data.autoCompactLimitTokens ? `triggers > ~${formatReportTokens(data.autoCompactLimitTokens)} (reserve ${formatReportTokens(data.reserveTokens)})` : "disabled";
|
|
70751
|
+
lines.push(
|
|
70752
|
+
`${padEndVisible(` ${branch(sections.length)} auto-compact`, labelWidth)}${theme2.fg("dim", autoCompact)}`
|
|
70753
|
+
);
|
|
70754
|
+
const reconciliation = data.actualTokens !== null ? `actual ${formatReportTokens(data.actualTokens)} (last response) \xB7 est\u2212actual \u2248 ${formatReportTokens(
|
|
70755
|
+
Math.abs(data.estimatedTotalTokens - data.actualTokens)
|
|
70756
|
+
)}${data.estimatedTotalTokens >= data.actualTokens ? " overhead" : " undercount"}` : "actual unknown until the next model response";
|
|
70757
|
+
lines.push(` ${theme2.fg("dim", reconciliation)}`);
|
|
70758
|
+
lines.push(theme2.fg("dim", " /debugs/context \xB7 Enter to drill into a section, Esc to go back"));
|
|
70759
|
+
return lines.join("\n");
|
|
70760
|
+
}
|
|
70761
|
+
function buildWindowRows(data) {
|
|
70762
|
+
const rows = [
|
|
70763
|
+
{
|
|
70764
|
+
id: "window:window",
|
|
70765
|
+
label: "context window",
|
|
70766
|
+
estTokens: data.contextWindow,
|
|
70767
|
+
valueText: data.contextWindow > 0 ? formatReportTokens(data.contextWindow) : "?",
|
|
70768
|
+
note: data.contextWindow > 0 ? `${(data.estimatedTotalTokens / data.contextWindow * 100).toFixed(1)}% used (est)` : "unknown"
|
|
70769
|
+
},
|
|
70770
|
+
{
|
|
70771
|
+
id: "window:estimated",
|
|
70772
|
+
label: "estimated total (prompt + tools + messages)",
|
|
70773
|
+
estTokens: data.estimatedTotalTokens,
|
|
70774
|
+
note: `prompt ~${formatReportTokens(data.systemPromptTokens)} \xB7 tools ~${formatReportTokens(data.toolsTokens)} \xB7 messages ~${formatReportTokens(data.messagesTokens)}`
|
|
70775
|
+
}
|
|
70776
|
+
];
|
|
70777
|
+
if (data.actualTokens !== null) {
|
|
70778
|
+
rows.push({
|
|
70779
|
+
id: "window:actual",
|
|
70780
|
+
label: "actual (last model response)",
|
|
70781
|
+
estTokens: data.actualTokens,
|
|
70782
|
+
valueText: formatReportTokens(data.actualTokens),
|
|
70783
|
+
note: `gap \u2248 ${formatReportTokens(Math.abs(data.estimatedTotalTokens - data.actualTokens))}`
|
|
70784
|
+
});
|
|
70785
|
+
}
|
|
70786
|
+
rows.push({
|
|
70787
|
+
id: "window:auto-compact",
|
|
70788
|
+
label: "auto-compact threshold",
|
|
70789
|
+
estTokens: data.autoCompactLimitTokens ?? 0,
|
|
70790
|
+
valueText: data.autoCompactLimitTokens ? `>${formatReportTokens(data.autoCompactLimitTokens)}` : "off",
|
|
70791
|
+
note: data.autoCompactLimitTokens ? `reserve ${formatReportTokens(data.reserveTokens)}` : "disabled"
|
|
70792
|
+
});
|
|
70793
|
+
if (data.promptPrefixHash) {
|
|
70794
|
+
rows.push({
|
|
70795
|
+
id: "window:prefix-hash",
|
|
70796
|
+
label: "prompt+tools hash (cache prefix)",
|
|
70797
|
+
estTokens: 0,
|
|
70798
|
+
valueText: data.promptPrefixHash,
|
|
70799
|
+
note: data.promptPrefixChanged ? "changed since last turn \u2014 provider cache invalidated \u26A1" : "stable \u2014 cache-friendly"
|
|
70800
|
+
});
|
|
70801
|
+
}
|
|
70802
|
+
return rows;
|
|
70803
|
+
}
|
|
70804
|
+
|
|
70345
70805
|
// src/components/tree-selector.ts
|
|
70346
70806
|
var RESET = "\x1B[0m";
|
|
70347
70807
|
var INVERSE = "\x1B[7m";
|
|
@@ -70812,12 +71272,13 @@ var TreeSelectorComponent = class {
|
|
|
70812
71272
|
const activeIndicator = this.options.activePathSeqs.has(row.summary.seq) ? theme.fg("success", TREE_CHARS.active) : DIM + TREE_CHARS.inactive + RESET;
|
|
70813
71273
|
const expandIndicator = row.inWindowChildren ? theme.fg("dim", this.collapsed.has(row.summary.id) ? "\u25B6 " : "\u25BC ") : row.hasChildren ? theme.fg("dim", "\xB7\xB7") : " ";
|
|
70814
71274
|
const role = roleColor(roleName(row.summary));
|
|
71275
|
+
const tokenNote = row.summary.estTokens > 0 ? theme.fg("dim", ` ~${formatReportTokens(row.summary.estTokens)}`) : "";
|
|
70815
71276
|
const indicatorWidth = visibleWidth(activeIndicator) + visibleWidth(expandIndicator) + visibleWidth(role) + 2;
|
|
70816
|
-
const prefixBudget = Math.max(0, Math.min(Math.floor(width * 0.35), width - indicatorWidth - MIN_BODY_WIDTH));
|
|
71277
|
+
const prefixBudget = Math.max(0, Math.min(Math.floor(width * 0.35), width - indicatorWidth - MIN_BODY_WIDTH - visibleWidth(tokenNote)));
|
|
70817
71278
|
const displayPrefix = clampPrefixForDisplay(row.prefix, prefixBudget);
|
|
70818
|
-
const availableWidth = Math.max(0, width - visibleWidth(displayPrefix) - indicatorWidth);
|
|
71279
|
+
const availableWidth = Math.max(0, width - visibleWidth(displayPrefix) - indicatorWidth - visibleWidth(tokenNote) - 2);
|
|
70819
71280
|
const content = truncateToWidth(row.summary.preview ?? "", availableWidth);
|
|
70820
|
-
lines.push(createLine(`${displayPrefix}${activeIndicator}${expandIndicator}${role}: ${content}`, width, i === this.selectedIndex));
|
|
71281
|
+
lines.push(createLine(`${displayPrefix}${activeIndicator}${expandIndicator}${role}: ${content}${tokenNote}`, width, i === this.selectedIndex));
|
|
70821
71282
|
}
|
|
70822
71283
|
for (let i = endIndex - startIndex; i < this.maxVisibleLines; i++) {
|
|
70823
71284
|
lines.push(createLine("", width, false));
|
|
@@ -72156,6 +72617,29 @@ function deriveSessionTitle(options) {
|
|
|
72156
72617
|
}
|
|
72157
72618
|
return `S:${activeSession.id.slice(-6)}`;
|
|
72158
72619
|
}
|
|
72620
|
+
function calculateSessionUsageTotals(messages) {
|
|
72621
|
+
let input = 0;
|
|
72622
|
+
let output = 0;
|
|
72623
|
+
let cacheRead = 0;
|
|
72624
|
+
let cacheWrite = 0;
|
|
72625
|
+
let cost = 0;
|
|
72626
|
+
for (const message of messages) {
|
|
72627
|
+
if (message.role !== "assistant") continue;
|
|
72628
|
+
const usage = message.usage;
|
|
72629
|
+
if (!usage) continue;
|
|
72630
|
+
input += usage.input;
|
|
72631
|
+
output += usage.output;
|
|
72632
|
+
cacheRead += usage.cacheRead;
|
|
72633
|
+
cacheWrite += usage.cacheWrite;
|
|
72634
|
+
cost += usage.cost?.total ?? 0;
|
|
72635
|
+
}
|
|
72636
|
+
return { input, output, cacheRead, cacheWrite, cost };
|
|
72637
|
+
}
|
|
72638
|
+
function formatTokensCompact(count) {
|
|
72639
|
+
if (count < 1e3) return String(count);
|
|
72640
|
+
if (count < 1e6) return `${(count / 1e3).toFixed(1)}k`;
|
|
72641
|
+
return `${(count / 1e6).toFixed(2)}M`;
|
|
72642
|
+
}
|
|
72159
72643
|
function buildSessionInfoText(options) {
|
|
72160
72644
|
const displayCwd = options.homeDir && options.cwd.startsWith(options.homeDir) ? `~${options.cwd.slice(options.homeDir.length)}` : options.cwd;
|
|
72161
72645
|
let info = options.theme.bold("Session Info") + "\n\n";
|
|
@@ -72178,6 +72662,39 @@ function buildSessionInfoText(options) {
|
|
|
72178
72662
|
`;
|
|
72179
72663
|
info += `${options.theme.fg("dim", "Thinking Level:")} ${options.thinkingLevel}
|
|
72180
72664
|
`;
|
|
72665
|
+
if (options.messages && options.messages.length > 0) {
|
|
72666
|
+
const totals = calculateSessionUsageTotals(options.messages);
|
|
72667
|
+
const turnCount = options.messages.filter((m2) => m2.role === "assistant").length;
|
|
72668
|
+
if (turnCount > 0) {
|
|
72669
|
+
info += `
|
|
72670
|
+
${options.theme.bold("Usage (active context)")}
|
|
72671
|
+
`;
|
|
72672
|
+
info += `${options.theme.fg("dim", "Turns:")} ${turnCount}
|
|
72673
|
+
`;
|
|
72674
|
+
info += `${options.theme.fg("dim", "Input:")} ${totals.input.toLocaleString()}
|
|
72675
|
+
`;
|
|
72676
|
+
info += `${options.theme.fg("dim", "Output:")} ${totals.output.toLocaleString()}
|
|
72677
|
+
`;
|
|
72678
|
+
if (totals.cacheRead > 0) {
|
|
72679
|
+
info += `${options.theme.fg("dim", "Cache Read:")} ${totals.cacheRead.toLocaleString()}
|
|
72680
|
+
`;
|
|
72681
|
+
}
|
|
72682
|
+
if (totals.cacheWrite > 0) {
|
|
72683
|
+
info += `${options.theme.fg("dim", "Cache Write:")} ${totals.cacheWrite.toLocaleString()}
|
|
72684
|
+
`;
|
|
72685
|
+
}
|
|
72686
|
+
if (totals.cost > 0) {
|
|
72687
|
+
info += `${options.theme.fg("dim", "Cost:")} $${totals.cost.toFixed(4)}
|
|
72688
|
+
`;
|
|
72689
|
+
}
|
|
72690
|
+
const hitRateBase = totals.input + totals.cacheRead;
|
|
72691
|
+
if (hitRateBase > 0 && totals.cacheRead > 0) {
|
|
72692
|
+
const hitRate = (totals.cacheRead / hitRateBase * 100).toFixed(1);
|
|
72693
|
+
info += `${options.theme.fg("dim", "Cache Hit Rate:")} ${hitRate}% (~${formatTokensCompact(hitRateBase)} served)
|
|
72694
|
+
`;
|
|
72695
|
+
}
|
|
72696
|
+
}
|
|
72697
|
+
}
|
|
72181
72698
|
return info;
|
|
72182
72699
|
}
|
|
72183
72700
|
function extractUserText(msg) {
|
|
@@ -72309,6 +72826,7 @@ async function loadSession(host, sessionId) {
|
|
|
72309
72826
|
contextPercent,
|
|
72310
72827
|
contextWindow
|
|
72311
72828
|
});
|
|
72829
|
+
applyContextSignalsToFooter(host);
|
|
72312
72830
|
host.ui.requestRender();
|
|
72313
72831
|
setTimeout(() => host.ui.requestRender(), 100);
|
|
72314
72832
|
} catch (error) {
|
|
@@ -73086,8 +73604,9 @@ var BUILTIN_SLASH_COMMANDS = [
|
|
|
73086
73604
|
{ name: "settings/calm", description: "Toggle calm mode: show only questions and final answers" },
|
|
73087
73605
|
{ name: "settings/yolo", description: "Toggle or set YOLO mode" },
|
|
73088
73606
|
{ name: "debugs/cache-test", description: "Run provider cache diagnostics with a dedicated 2-request probe" },
|
|
73089
|
-
{ name: "debugs/context", description: "
|
|
73090
|
-
{ name: "debugs/
|
|
73607
|
+
{ name: "debugs/context", description: "Context composition report: sections, tokens, drill-down" },
|
|
73608
|
+
{ name: "debugs/trace", description: "Session trace: timeline, tool stats, runtime events" },
|
|
73609
|
+
{ name: "debugs/boot", description: "Boot composition pipeline: how the runtime was assembled" },
|
|
73091
73610
|
{ name: "settings/quit", description: "Exit Pie" },
|
|
73092
73611
|
{ name: "skills", description: "Manage skills: list, toggle enable/disable, invoke" },
|
|
73093
73612
|
{ name: "skills/list", description: "List available skills (plain text)" },
|
|
@@ -73345,6 +73864,7 @@ function bindInteractiveRuntimeEvents(host) {
|
|
|
73345
73864
|
contextPercent,
|
|
73346
73865
|
contextWindow
|
|
73347
73866
|
});
|
|
73867
|
+
applyContextSignalsToFooter(host);
|
|
73348
73868
|
host.safeRequestRender();
|
|
73349
73869
|
host.sessionManager.save().catch((err) => {
|
|
73350
73870
|
console.error("[Session] Auto-save failed:", err);
|
|
@@ -73793,7 +74313,7 @@ function assistantDisplayBlocks(content) {
|
|
|
73793
74313
|
}
|
|
73794
74314
|
|
|
73795
74315
|
// src/commands/interactive-debug-commands.ts
|
|
73796
|
-
import { createHash as
|
|
74316
|
+
import { createHash as createHash5 } from "crypto";
|
|
73797
74317
|
function errorMessage(error) {
|
|
73798
74318
|
return error instanceof Error ? error.message : String(error);
|
|
73799
74319
|
}
|
|
@@ -73831,7 +74351,7 @@ async function handleCacheTest(host) {
|
|
|
73831
74351
|
timestamp: fixedTimestamp
|
|
73832
74352
|
}
|
|
73833
74353
|
];
|
|
73834
|
-
const prefixHash =
|
|
74354
|
+
const prefixHash = createHash5("sha256").update(
|
|
73835
74355
|
JSON.stringify({
|
|
73836
74356
|
systemPrompt: stablePrefix,
|
|
73837
74357
|
tools: toolDefs.map((tool) => ({
|
|
@@ -73940,126 +74460,6 @@ async function handleCacheTest(host) {
|
|
|
73940
74460
|
host.chatContainer.addChild(new Spacer(1));
|
|
73941
74461
|
host.ui.requestRender();
|
|
73942
74462
|
}
|
|
73943
|
-
async function handleDebugContextCommand(host) {
|
|
73944
|
-
host.chatContainer.addChild(new Spacer(1));
|
|
73945
|
-
host.chatContainer.addChild(new Text(theme.bold("Debug Context"), 1, 0));
|
|
73946
|
-
host.ui.requestRender();
|
|
73947
|
-
try {
|
|
73948
|
-
const state = host.agent.state;
|
|
73949
|
-
const debugInfo = {
|
|
73950
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
73951
|
-
systemPrompt: state.systemPrompt,
|
|
73952
|
-
model: state.model,
|
|
73953
|
-
thinkingLevel: state.thinkingLevel,
|
|
73954
|
-
tools: state.tools.map((t) => ({
|
|
73955
|
-
name: t.name,
|
|
73956
|
-
description: t.description,
|
|
73957
|
-
label: t.label
|
|
73958
|
-
})),
|
|
73959
|
-
messageCount: state.messages.length,
|
|
73960
|
-
messages: state.messages,
|
|
73961
|
-
isStreaming: state.isStreaming,
|
|
73962
|
-
pendingToolCalls: Array.from(state.pendingToolCalls)
|
|
73963
|
-
};
|
|
73964
|
-
getLogger().child({ module: "context_dump" }).info("Agent context snapshot", {
|
|
73965
|
-
snapshot: {
|
|
73966
|
-
timestamp: debugInfo.timestamp,
|
|
73967
|
-
modelId: debugInfo.model?.id ?? "",
|
|
73968
|
-
provider: debugInfo.model?.provider ?? "",
|
|
73969
|
-
thinkingLevel: debugInfo.thinkingLevel,
|
|
73970
|
-
toolCount: debugInfo.tools.length,
|
|
73971
|
-
messageCount: debugInfo.messageCount,
|
|
73972
|
-
isStreaming: debugInfo.isStreaming,
|
|
73973
|
-
pendingToolCalls: debugInfo.pendingToolCalls.length
|
|
73974
|
-
}
|
|
73975
|
-
});
|
|
73976
|
-
host.chatContainer.addChild(new Text(
|
|
73977
|
-
theme.fg("success", "\u2713 Context summary appended to ~/.pie/logs/pie-cli.log"),
|
|
73978
|
-
1,
|
|
73979
|
-
0
|
|
73980
|
-
));
|
|
73981
|
-
host.chatContainer.addChild(new Text(
|
|
73982
|
-
theme.fg("dim", ` Messages: ${state.messages.length}, Tools: ${state.tools.length}`),
|
|
73983
|
-
1,
|
|
73984
|
-
0
|
|
73985
|
-
));
|
|
73986
|
-
} catch (err) {
|
|
73987
|
-
host.showError(`Failed to save context: ${errorMessage(err)}`);
|
|
73988
|
-
}
|
|
73989
|
-
host.chatContainer.addChild(new Spacer(1));
|
|
73990
|
-
host.ui.requestRender();
|
|
73991
|
-
}
|
|
73992
|
-
async function handleDebugPackageCommand(host) {
|
|
73993
|
-
host.chatContainer.addChild(new Spacer(1));
|
|
73994
|
-
host.chatContainer.addChild(new Text(theme.bold("Debug Package"), 1, 0));
|
|
73995
|
-
host.ui.requestRender();
|
|
73996
|
-
try {
|
|
73997
|
-
const messages = host.agent.state.messages;
|
|
73998
|
-
const packageInfo = {
|
|
73999
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
74000
|
-
totalMessages: messages.length,
|
|
74001
|
-
conversation: messages.map((msg, index) => {
|
|
74002
|
-
const baseInfo = {
|
|
74003
|
-
index,
|
|
74004
|
-
role: msg.role
|
|
74005
|
-
};
|
|
74006
|
-
if (msg.role === "user") {
|
|
74007
|
-
return {
|
|
74008
|
-
...baseInfo,
|
|
74009
|
-
direction: "\u2192 SEND",
|
|
74010
|
-
content: typeof msg.content === "string" ? msg.content : JSON.stringify(msg.content, null, 2)
|
|
74011
|
-
};
|
|
74012
|
-
} else if (msg.role === "assistant") {
|
|
74013
|
-
const assistantMsg = msg;
|
|
74014
|
-
const toolCalls = assistantMsg.content.filter((c) => c.type === "toolCall").map((c) => ({ name: c.name, arguments: c.arguments, id: c.id }));
|
|
74015
|
-
return {
|
|
74016
|
-
...baseInfo,
|
|
74017
|
-
direction: "\u2190 RECEIVE",
|
|
74018
|
-
content: assistantMsg.content,
|
|
74019
|
-
toolCalls,
|
|
74020
|
-
usage: assistantMsg.usage
|
|
74021
|
-
};
|
|
74022
|
-
} else if (msg.role === "toolResult") {
|
|
74023
|
-
const toolMsg = msg;
|
|
74024
|
-
return {
|
|
74025
|
-
...baseInfo,
|
|
74026
|
-
direction: "\u2192 TOOL RESULT",
|
|
74027
|
-
toolCallId: toolMsg.toolCallId,
|
|
74028
|
-
content: toolMsg.content
|
|
74029
|
-
};
|
|
74030
|
-
}
|
|
74031
|
-
return baseInfo;
|
|
74032
|
-
})
|
|
74033
|
-
};
|
|
74034
|
-
getLogger().child({ module: "package_dump" }).info("Agent package snapshot", {
|
|
74035
|
-
snapshot: {
|
|
74036
|
-
timestamp: packageInfo.timestamp,
|
|
74037
|
-
totalMessages: packageInfo.totalMessages,
|
|
74038
|
-
userMessages: packageInfo.conversation.filter((m2) => m2.role === "user").length,
|
|
74039
|
-
assistantMessages: packageInfo.conversation.filter((m2) => m2.role === "assistant").length,
|
|
74040
|
-
toolMessages: packageInfo.conversation.filter((m2) => m2.role === "toolResult").length,
|
|
74041
|
-
lastMessageRole: packageInfo.conversation.length > 0 ? packageInfo.conversation[packageInfo.conversation.length - 1].role : ""
|
|
74042
|
-
}
|
|
74043
|
-
});
|
|
74044
|
-
host.chatContainer.addChild(new Text(
|
|
74045
|
-
theme.fg("success", "\u2713 Package summary appended to ~/.pie/logs/pie-cli.log"),
|
|
74046
|
-
1,
|
|
74047
|
-
0
|
|
74048
|
-
));
|
|
74049
|
-
const userCount = messages.filter((m2) => m2.role === "user").length;
|
|
74050
|
-
const assistantCount = messages.filter((m2) => m2.role === "assistant").length;
|
|
74051
|
-
const toolCount = messages.filter((m2) => m2.role === "toolResult").length;
|
|
74052
|
-
host.chatContainer.addChild(new Text(
|
|
74053
|
-
theme.fg("dim", ` User: ${userCount}, Assistant: ${assistantCount}, Tool: ${toolCount}`),
|
|
74054
|
-
1,
|
|
74055
|
-
0
|
|
74056
|
-
));
|
|
74057
|
-
} catch (err) {
|
|
74058
|
-
host.showError(`Failed to save package log: ${errorMessage(err)}`);
|
|
74059
|
-
}
|
|
74060
|
-
host.chatContainer.addChild(new Spacer(1));
|
|
74061
|
-
host.ui.requestRender();
|
|
74062
|
-
}
|
|
74063
74463
|
|
|
74064
74464
|
// src/commands/interactive-skill-commands.ts
|
|
74065
74465
|
import * as fs24 from "fs";
|
|
@@ -74636,6 +75036,944 @@ function handleToolsCommand(host, args) {
|
|
|
74636
75036
|
showToolsManager(host);
|
|
74637
75037
|
}
|
|
74638
75038
|
|
|
75039
|
+
// src/components/context-report-selector.ts
|
|
75040
|
+
var RESET2 = "\x1B[0m";
|
|
75041
|
+
var INVERSE2 = "\x1B[7m";
|
|
75042
|
+
var ROLE_FILTER_CYCLE = ["all", "user", "assistant", "toolResult", "compaction"];
|
|
75043
|
+
function createLine2(content, width, isSelected) {
|
|
75044
|
+
const normalized = content.replace(/[\r\n]+/g, " ");
|
|
75045
|
+
const body = isSelected ? INVERSE2 + normalized : normalized;
|
|
75046
|
+
return truncateToWidth(body + RESET2, width, "...", true);
|
|
75047
|
+
}
|
|
75048
|
+
function buildRootRows(sections, windowSection) {
|
|
75049
|
+
const rows = sections.map((section) => ({
|
|
75050
|
+
id: `section:${section.id}`,
|
|
75051
|
+
label: section.title,
|
|
75052
|
+
estTokens: section.estTokens,
|
|
75053
|
+
note: section.note,
|
|
75054
|
+
detail: section.id === "messages" ? "active context entries (Enter to list)" : void 0,
|
|
75055
|
+
drill: {
|
|
75056
|
+
kind: "rows",
|
|
75057
|
+
title: `${section.title}`,
|
|
75058
|
+
rows: section.rows,
|
|
75059
|
+
rowKind: section.id === "messages" ? "messages" : "plain"
|
|
75060
|
+
}
|
|
75061
|
+
}));
|
|
75062
|
+
if (windowSection) {
|
|
75063
|
+
rows.push({
|
|
75064
|
+
id: "section:window",
|
|
75065
|
+
label: windowSection.label,
|
|
75066
|
+
estTokens: windowSection.estTokens,
|
|
75067
|
+
valueText: windowSection.valueText,
|
|
75068
|
+
detail: windowSection.detail,
|
|
75069
|
+
drill: {
|
|
75070
|
+
kind: "rows",
|
|
75071
|
+
title: windowSection.title ?? windowSection.label,
|
|
75072
|
+
rows: windowSection.rows,
|
|
75073
|
+
rowKind: "plain"
|
|
75074
|
+
}
|
|
75075
|
+
});
|
|
75076
|
+
}
|
|
75077
|
+
return rows;
|
|
75078
|
+
}
|
|
75079
|
+
var ContextReportSelectorComponent = class {
|
|
75080
|
+
options;
|
|
75081
|
+
maxVisibleLines;
|
|
75082
|
+
views = [];
|
|
75083
|
+
selectedIndex = 0;
|
|
75084
|
+
searchQuery = "";
|
|
75085
|
+
statusMessage = null;
|
|
75086
|
+
_focused = false;
|
|
75087
|
+
get focused() {
|
|
75088
|
+
return this._focused;
|
|
75089
|
+
}
|
|
75090
|
+
set focused(value) {
|
|
75091
|
+
this._focused = value;
|
|
75092
|
+
}
|
|
75093
|
+
constructor(options) {
|
|
75094
|
+
this.options = options;
|
|
75095
|
+
this.maxVisibleLines = Math.max(15, Math.floor(options.terminalHeight * 0.6));
|
|
75096
|
+
this.views = [
|
|
75097
|
+
{
|
|
75098
|
+
kind: "list",
|
|
75099
|
+
title: options.title,
|
|
75100
|
+
rows: buildRootRows(options.sections, options.windowSection),
|
|
75101
|
+
rowKind: "root",
|
|
75102
|
+
roleFilter: "all",
|
|
75103
|
+
sortBySize: false
|
|
75104
|
+
}
|
|
75105
|
+
];
|
|
75106
|
+
}
|
|
75107
|
+
// ---------------------------------------------------------------------------
|
|
75108
|
+
// Filtering / sorting
|
|
75109
|
+
// ---------------------------------------------------------------------------
|
|
75110
|
+
get currentView() {
|
|
75111
|
+
return this.views[this.views.length - 1];
|
|
75112
|
+
}
|
|
75113
|
+
visibleListRows(view) {
|
|
75114
|
+
let rows = view.rows;
|
|
75115
|
+
if (view.roleFilter !== "all") {
|
|
75116
|
+
rows = rows.filter((row) => row.roleTag === view.roleFilter);
|
|
75117
|
+
}
|
|
75118
|
+
if (view.rowKind === "messages" && view.sortBySize) {
|
|
75119
|
+
rows = [...rows].sort((a, b2) => b2.estTokens - a.estTokens);
|
|
75120
|
+
}
|
|
75121
|
+
if (this.searchQuery) {
|
|
75122
|
+
const query = this.searchQuery.toLowerCase();
|
|
75123
|
+
rows = rows.filter(
|
|
75124
|
+
(row) => `${row.label} ${row.detail ?? ""} ${row.note ?? ""} ${row.roleTag ?? ""}`.toLowerCase().includes(query)
|
|
75125
|
+
);
|
|
75126
|
+
}
|
|
75127
|
+
return rows;
|
|
75128
|
+
}
|
|
75129
|
+
applyFilterChange() {
|
|
75130
|
+
this.selectedIndex = 0;
|
|
75131
|
+
this.statusMessage = null;
|
|
75132
|
+
}
|
|
75133
|
+
// ---------------------------------------------------------------------------
|
|
75134
|
+
// Navigation
|
|
75135
|
+
// ---------------------------------------------------------------------------
|
|
75136
|
+
moveUp() {
|
|
75137
|
+
const view = this.currentView;
|
|
75138
|
+
if (view.kind === "list") {
|
|
75139
|
+
const rows = this.visibleListRows(view);
|
|
75140
|
+
if (rows.length > 0) {
|
|
75141
|
+
this.selectedIndex = (this.selectedIndex - 1 + rows.length) % rows.length;
|
|
75142
|
+
}
|
|
75143
|
+
} else {
|
|
75144
|
+
view.scroll = Math.max(0, view.scroll - 1);
|
|
75145
|
+
}
|
|
75146
|
+
}
|
|
75147
|
+
moveDown() {
|
|
75148
|
+
const view = this.currentView;
|
|
75149
|
+
if (view.kind === "list") {
|
|
75150
|
+
const rows = this.visibleListRows(view);
|
|
75151
|
+
if (rows.length > 0) {
|
|
75152
|
+
this.selectedIndex = (this.selectedIndex + 1) % rows.length;
|
|
75153
|
+
}
|
|
75154
|
+
} else {
|
|
75155
|
+
view.scroll = Math.min(Math.max(0, view.lines.length - 1), view.scroll + 1);
|
|
75156
|
+
}
|
|
75157
|
+
}
|
|
75158
|
+
pageUp() {
|
|
75159
|
+
const view = this.currentView;
|
|
75160
|
+
if (view.kind === "list") {
|
|
75161
|
+
this.selectedIndex = Math.max(0, this.selectedIndex - this.maxVisibleLines);
|
|
75162
|
+
} else {
|
|
75163
|
+
view.scroll = Math.max(0, view.scroll - this.maxVisibleLines);
|
|
75164
|
+
}
|
|
75165
|
+
}
|
|
75166
|
+
pageDown() {
|
|
75167
|
+
const view = this.currentView;
|
|
75168
|
+
if (view.kind === "list") {
|
|
75169
|
+
const rows = this.visibleListRows(view);
|
|
75170
|
+
this.selectedIndex = Math.min(Math.max(0, rows.length - 1), this.selectedIndex + this.maxVisibleLines);
|
|
75171
|
+
} else {
|
|
75172
|
+
view.scroll = Math.min(
|
|
75173
|
+
Math.max(0, view.lines.length - 1),
|
|
75174
|
+
view.scroll + this.maxVisibleLines
|
|
75175
|
+
);
|
|
75176
|
+
}
|
|
75177
|
+
}
|
|
75178
|
+
pushTextView(title, text) {
|
|
75179
|
+
this.searchQuery = "";
|
|
75180
|
+
this.views.push({
|
|
75181
|
+
kind: "text",
|
|
75182
|
+
title,
|
|
75183
|
+
lines: text.replace(/\r\n/g, "\n").split("\n"),
|
|
75184
|
+
scroll: 0
|
|
75185
|
+
});
|
|
75186
|
+
this.selectedIndex = 0;
|
|
75187
|
+
this.statusMessage = null;
|
|
75188
|
+
}
|
|
75189
|
+
drillIntoSelected() {
|
|
75190
|
+
const view = this.currentView;
|
|
75191
|
+
if (view.kind !== "list") return;
|
|
75192
|
+
const rows = this.visibleListRows(view);
|
|
75193
|
+
const row = rows[this.selectedIndex];
|
|
75194
|
+
if (!row) return;
|
|
75195
|
+
if (!row.drill) {
|
|
75196
|
+
this.statusMessage = "no further detail";
|
|
75197
|
+
return;
|
|
75198
|
+
}
|
|
75199
|
+
switch (row.drill.kind) {
|
|
75200
|
+
case "rows":
|
|
75201
|
+
this.searchQuery = "";
|
|
75202
|
+
this.views.push({
|
|
75203
|
+
kind: "list",
|
|
75204
|
+
title: row.drill.title,
|
|
75205
|
+
rows: row.drill.rows,
|
|
75206
|
+
rowKind: row.drill.rowKind,
|
|
75207
|
+
roleFilter: "all",
|
|
75208
|
+
sortBySize: false
|
|
75209
|
+
});
|
|
75210
|
+
this.selectedIndex = 0;
|
|
75211
|
+
this.statusMessage = null;
|
|
75212
|
+
break;
|
|
75213
|
+
case "text":
|
|
75214
|
+
this.pushTextView(row.drill.title, row.drill.text);
|
|
75215
|
+
break;
|
|
75216
|
+
case "entry": {
|
|
75217
|
+
const text = this.options.getEntryText?.(row.drill.entryId) ?? null;
|
|
75218
|
+
if (text === null) {
|
|
75219
|
+
this.statusMessage = "entry body unavailable";
|
|
75220
|
+
} else {
|
|
75221
|
+
this.pushTextView(`Entry \xB7 ${row.label}`, text);
|
|
75222
|
+
}
|
|
75223
|
+
break;
|
|
75224
|
+
}
|
|
75225
|
+
}
|
|
75226
|
+
}
|
|
75227
|
+
popView() {
|
|
75228
|
+
if (this.views.length > 1) {
|
|
75229
|
+
this.views.pop();
|
|
75230
|
+
this.selectedIndex = 0;
|
|
75231
|
+
this.statusMessage = null;
|
|
75232
|
+
} else {
|
|
75233
|
+
this.options.onDone();
|
|
75234
|
+
}
|
|
75235
|
+
}
|
|
75236
|
+
// ---------------------------------------------------------------------------
|
|
75237
|
+
// Input
|
|
75238
|
+
// ---------------------------------------------------------------------------
|
|
75239
|
+
handleInput(keyData) {
|
|
75240
|
+
const kb = getEditorKeybindings();
|
|
75241
|
+
if (kb.matches(keyData, "selectUp")) {
|
|
75242
|
+
this.moveUp();
|
|
75243
|
+
} else if (kb.matches(keyData, "selectDown")) {
|
|
75244
|
+
this.moveDown();
|
|
75245
|
+
} else if (kb.matches(keyData, "selectPageUp")) {
|
|
75246
|
+
this.pageUp();
|
|
75247
|
+
} else if (kb.matches(keyData, "selectPageDown")) {
|
|
75248
|
+
this.pageDown();
|
|
75249
|
+
} else if (kb.matches(keyData, "selectConfirm")) {
|
|
75250
|
+
this.drillIntoSelected();
|
|
75251
|
+
} else if (kb.matches(keyData, "selectCancel")) {
|
|
75252
|
+
if (this.searchQuery) {
|
|
75253
|
+
this.searchQuery = "";
|
|
75254
|
+
this.applyFilterChange();
|
|
75255
|
+
} else {
|
|
75256
|
+
this.popView();
|
|
75257
|
+
}
|
|
75258
|
+
} else if (matchesKey(keyData, "ctrl+u")) {
|
|
75259
|
+
const view = this.currentView;
|
|
75260
|
+
if (view.kind === "list" && view.rowKind === "messages") {
|
|
75261
|
+
const next = ROLE_FILTER_CYCLE[(ROLE_FILTER_CYCLE.indexOf(view.roleFilter) + 1) % ROLE_FILTER_CYCLE.length];
|
|
75262
|
+
view.roleFilter = next;
|
|
75263
|
+
this.applyFilterChange();
|
|
75264
|
+
}
|
|
75265
|
+
} else if ((keyData === "s" || keyData === "S") && this.searchQuery === "") {
|
|
75266
|
+
const view = this.currentView;
|
|
75267
|
+
if (view.kind === "list" && view.rowKind === "messages") {
|
|
75268
|
+
view.sortBySize = !view.sortBySize;
|
|
75269
|
+
this.applyFilterChange();
|
|
75270
|
+
}
|
|
75271
|
+
} else if (kb.matches(keyData, "deleteCharBackward")) {
|
|
75272
|
+
if (this.searchQuery.length > 0) {
|
|
75273
|
+
this.searchQuery = this.searchQuery.slice(0, -1);
|
|
75274
|
+
this.applyFilterChange();
|
|
75275
|
+
}
|
|
75276
|
+
} else {
|
|
75277
|
+
const hasControlChars = [...keyData].some((ch) => {
|
|
75278
|
+
const code = ch.charCodeAt(0);
|
|
75279
|
+
return code < 32 || code === 127 || code >= 128 && code <= 159;
|
|
75280
|
+
});
|
|
75281
|
+
if (!hasControlChars && keyData.length > 0 && this.searchQuery.length < 100) {
|
|
75282
|
+
this.searchQuery += keyData;
|
|
75283
|
+
this.applyFilterChange();
|
|
75284
|
+
}
|
|
75285
|
+
}
|
|
75286
|
+
}
|
|
75287
|
+
// ---------------------------------------------------------------------------
|
|
75288
|
+
// Rendering
|
|
75289
|
+
// ---------------------------------------------------------------------------
|
|
75290
|
+
invalidate() {
|
|
75291
|
+
}
|
|
75292
|
+
hintsLine(view) {
|
|
75293
|
+
if (view.kind === "text") {
|
|
75294
|
+
return " \u2191\u2193:scroll Esc:back";
|
|
75295
|
+
}
|
|
75296
|
+
const base = " \u2191\u2193:move Enter:drill Esc:back type:search PgUp/PgDn:page";
|
|
75297
|
+
if (view.rowKind === "messages") {
|
|
75298
|
+
return `${base} ctrl+u:role(${view.roleFilter}) s:sort(${view.sortBySize ? "size" : "seq"})`;
|
|
75299
|
+
}
|
|
75300
|
+
return base;
|
|
75301
|
+
}
|
|
75302
|
+
renderRowLine(row, width, selected) {
|
|
75303
|
+
const valueText = row.valueText ?? `~${formatReportTokens(row.estTokens)}`;
|
|
75304
|
+
const rightParts = [theme.fg("accent", valueText)];
|
|
75305
|
+
if (row.note) {
|
|
75306
|
+
rightParts.push(theme.fg("dim", row.note));
|
|
75307
|
+
}
|
|
75308
|
+
const right = rightParts.join(" ");
|
|
75309
|
+
const rightWidth = visibleWidth(right);
|
|
75310
|
+
const marker = row.marker ? theme.fg("warning", `${row.marker} `) : "";
|
|
75311
|
+
const detail = row.detail ? theme.fg("dim", ` \xB7 ${row.detail}`) : "";
|
|
75312
|
+
let left = ` ${marker}${row.label}${detail}`;
|
|
75313
|
+
const leftBudget = Math.max(12, width - rightWidth - 3);
|
|
75314
|
+
if (visibleWidth(left) > leftBudget) {
|
|
75315
|
+
left = truncateToWidth(left, leftBudget, "\u2026");
|
|
75316
|
+
}
|
|
75317
|
+
const gap = Math.max(1, width - visibleWidth(left) - rightWidth - 1);
|
|
75318
|
+
return createLine2(`${left}${" ".repeat(gap)}${right}`, width, selected);
|
|
75319
|
+
}
|
|
75320
|
+
render(width) {
|
|
75321
|
+
const lines = [];
|
|
75322
|
+
const totalLines = this.maxVisibleLines + 5;
|
|
75323
|
+
const view = this.currentView;
|
|
75324
|
+
const depthSuffix = this.views.length > 1 ? theme.fg("dim", ` (${this.views.length} levels)`) : "";
|
|
75325
|
+
lines.push(createLine2(` ${theme.bold(view.title)}${depthSuffix}`, width, false));
|
|
75326
|
+
lines.push(createLine2(this.hintsLine(view), width, false));
|
|
75327
|
+
const searchPart = this.searchQuery ? `Search: ${this.searchQuery}` : "";
|
|
75328
|
+
const statusPart = this.statusMessage ? theme.fg("warning", this.statusMessage) : "";
|
|
75329
|
+
const statusLine = [searchPart, statusPart].filter(Boolean).join(" \xB7 ");
|
|
75330
|
+
lines.push(createLine2(statusLine, width, false));
|
|
75331
|
+
lines.push(createLine2("", width, false));
|
|
75332
|
+
if (view.kind === "list") {
|
|
75333
|
+
const rows = this.visibleListRows(view);
|
|
75334
|
+
if (rows.length === 0) {
|
|
75335
|
+
const notice = this.searchQuery || view.roleFilter !== "all" ? " (no matching rows)" : " (empty)";
|
|
75336
|
+
lines.push(createLine2(notice, width, false));
|
|
75337
|
+
for (let i = 1; i < this.maxVisibleLines; i++) {
|
|
75338
|
+
lines.push(createLine2("", width, false));
|
|
75339
|
+
}
|
|
75340
|
+
} else {
|
|
75341
|
+
this.selectedIndex = Math.max(0, Math.min(this.selectedIndex, rows.length - 1));
|
|
75342
|
+
let startIndex = Math.max(
|
|
75343
|
+
0,
|
|
75344
|
+
Math.min(
|
|
75345
|
+
this.selectedIndex - Math.floor(this.maxVisibleLines / 2),
|
|
75346
|
+
rows.length - this.maxVisibleLines
|
|
75347
|
+
)
|
|
75348
|
+
);
|
|
75349
|
+
const endIndex = Math.min(startIndex + this.maxVisibleLines, rows.length);
|
|
75350
|
+
if (endIndex - startIndex < this.maxVisibleLines && startIndex > 0) {
|
|
75351
|
+
startIndex = Math.max(0, endIndex - this.maxVisibleLines);
|
|
75352
|
+
}
|
|
75353
|
+
for (let i = startIndex; i < endIndex; i++) {
|
|
75354
|
+
lines.push(this.renderRowLine(rows[i], width, i === this.selectedIndex));
|
|
75355
|
+
}
|
|
75356
|
+
for (let i = endIndex - startIndex; i < this.maxVisibleLines; i++) {
|
|
75357
|
+
lines.push(createLine2("", width, false));
|
|
75358
|
+
}
|
|
75359
|
+
}
|
|
75360
|
+
const filterSuffix = view.roleFilter !== "all" ? ` [${view.roleFilter}]` : "";
|
|
75361
|
+
const sortSuffix = view.rowKind === "messages" && view.sortBySize ? " [size]" : "";
|
|
75362
|
+
lines.push(
|
|
75363
|
+
createLine2(
|
|
75364
|
+
` (${this.selectedIndex + 1}/${this.visibleListRows(view).length})${filterSuffix}${sortSuffix}`,
|
|
75365
|
+
width,
|
|
75366
|
+
false
|
|
75367
|
+
)
|
|
75368
|
+
);
|
|
75369
|
+
} else {
|
|
75370
|
+
const total = view.lines.length;
|
|
75371
|
+
const start = Math.min(view.scroll, Math.max(0, total - 1));
|
|
75372
|
+
const end = Math.min(start + this.maxVisibleLines, total);
|
|
75373
|
+
for (let i = start; i < end; i++) {
|
|
75374
|
+
lines.push(createLine2(` ${view.lines[i]}`, width, false));
|
|
75375
|
+
}
|
|
75376
|
+
for (let i = end - start; i < this.maxVisibleLines; i++) {
|
|
75377
|
+
lines.push(createLine2("", width, false));
|
|
75378
|
+
}
|
|
75379
|
+
lines.push(
|
|
75380
|
+
createLine2(` (lines ${total > 0 ? start + 1 : 0}-${end} of ${total})`, width, false)
|
|
75381
|
+
);
|
|
75382
|
+
}
|
|
75383
|
+
while (lines.length < totalLines) {
|
|
75384
|
+
lines.push(createLine2("", width, false));
|
|
75385
|
+
}
|
|
75386
|
+
return lines.slice(0, totalLines);
|
|
75387
|
+
}
|
|
75388
|
+
};
|
|
75389
|
+
|
|
75390
|
+
// src/commands/interactive-context-command.ts
|
|
75391
|
+
var MAX_ENTRY_BODY_CHARS = 1e4;
|
|
75392
|
+
var MAX_ARCHIVED_ROWS = 200;
|
|
75393
|
+
function fetchArchivedSummaries(sessionManager, firstKeptSeq) {
|
|
75394
|
+
const result = [];
|
|
75395
|
+
let afterSeq;
|
|
75396
|
+
while (result.length < MAX_ARCHIVED_ROWS) {
|
|
75397
|
+
const page = sessionManager.getEntrySummariesPage({ limit: 100, afterSeq });
|
|
75398
|
+
if (page.summaries.length === 0) break;
|
|
75399
|
+
let crossedCutPoint = false;
|
|
75400
|
+
for (const summary of page.summaries) {
|
|
75401
|
+
if (summary.seq >= firstKeptSeq) {
|
|
75402
|
+
crossedCutPoint = true;
|
|
75403
|
+
break;
|
|
75404
|
+
}
|
|
75405
|
+
if (result.length >= MAX_ARCHIVED_ROWS) break;
|
|
75406
|
+
result.push(summary);
|
|
75407
|
+
}
|
|
75408
|
+
if (crossedCutPoint || !page.hasMore) break;
|
|
75409
|
+
afterSeq = page.summaries[page.summaries.length - 1].seq;
|
|
75410
|
+
}
|
|
75411
|
+
return result;
|
|
75412
|
+
}
|
|
75413
|
+
function enhanceCheckpointRowWithArchive(report, host, entries) {
|
|
75414
|
+
const messagesSection = report.sections.find((section) => section.id === "messages");
|
|
75415
|
+
const checkpoint = [...entries].reverse().find((entry) => entry.type === "compaction");
|
|
75416
|
+
if (!messagesSection || !checkpoint) return;
|
|
75417
|
+
const compactionEntry = host.sessionManager.getEntry(checkpoint.id);
|
|
75418
|
+
const firstKeptEntryId = compactionEntry?.compactionData?.firstKeptEntryId;
|
|
75419
|
+
if (!firstKeptEntryId) return;
|
|
75420
|
+
const firstKeptSeq = host.sessionManager.getEntrySummary(firstKeptEntryId)?.seq;
|
|
75421
|
+
if (firstKeptSeq === void 0) return;
|
|
75422
|
+
const archived = fetchArchivedSummaries(host.sessionManager, firstKeptSeq);
|
|
75423
|
+
if (archived.length === 0) return;
|
|
75424
|
+
const row = messagesSection.rows.find((candidate) => candidate.id === `entry:${checkpoint.id}`);
|
|
75425
|
+
if (!row) return;
|
|
75426
|
+
const truncated = archived.length >= MAX_ARCHIVED_ROWS;
|
|
75427
|
+
row.drill = {
|
|
75428
|
+
kind: "rows",
|
|
75429
|
+
title: `Archived @ checkpoint #${checkpoint.seq}`,
|
|
75430
|
+
rowKind: "plain",
|
|
75431
|
+
rows: [
|
|
75432
|
+
{
|
|
75433
|
+
id: "checkpoint-summary",
|
|
75434
|
+
label: "checkpoint summary",
|
|
75435
|
+
estTokens: checkpoint.estTokens,
|
|
75436
|
+
drill: {
|
|
75437
|
+
kind: "text",
|
|
75438
|
+
title: "Checkpoint Summary",
|
|
75439
|
+
text: compactionEntry?.compactionData?.summary ?? ""
|
|
75440
|
+
}
|
|
75441
|
+
},
|
|
75442
|
+
...archived.map((summary) => ({
|
|
75443
|
+
id: `archived:${summary.id}`,
|
|
75444
|
+
label: `#${summary.seq} ${summary.role ?? summary.type}`,
|
|
75445
|
+
estTokens: summary.estTokens,
|
|
75446
|
+
detail: summary.preview,
|
|
75447
|
+
drill: { kind: "entry", entryId: summary.id }
|
|
75448
|
+
})),
|
|
75449
|
+
...truncated ? [{
|
|
75450
|
+
id: "archived:truncated",
|
|
75451
|
+
label: `\u2026 archived list capped at ${MAX_ARCHIVED_ROWS} entries (oldest first)`,
|
|
75452
|
+
estTokens: 0
|
|
75453
|
+
}] : []
|
|
75454
|
+
]
|
|
75455
|
+
};
|
|
75456
|
+
}
|
|
75457
|
+
function formatEntryBodyText(entry) {
|
|
75458
|
+
if (!entry) return null;
|
|
75459
|
+
if (entry.type === "compaction") {
|
|
75460
|
+
const summary = entry.compactionData?.summary ?? "";
|
|
75461
|
+
const before = entry.compactionData?.tokensBefore;
|
|
75462
|
+
const header = before !== void 0 ? `# compaction checkpoint (context was ~${formatReportTokens(before)} before)
|
|
75463
|
+
` : "# compaction checkpoint\n";
|
|
75464
|
+
return `${header}
|
|
75465
|
+
${summary}`.slice(0, MAX_ENTRY_BODY_CHARS) || null;
|
|
75466
|
+
}
|
|
75467
|
+
const message = entry.message;
|
|
75468
|
+
if (!message) return null;
|
|
75469
|
+
if (message.role === "user") {
|
|
75470
|
+
const parts = ["# user message"];
|
|
75471
|
+
const content = message.content;
|
|
75472
|
+
if (typeof content === "string") {
|
|
75473
|
+
parts.push(content);
|
|
75474
|
+
} else if (Array.isArray(content)) {
|
|
75475
|
+
for (const block of content) {
|
|
75476
|
+
if (block && block.type === "text" && typeof block.text === "string") {
|
|
75477
|
+
parts.push(block.text);
|
|
75478
|
+
} else if (block && "type" in block) {
|
|
75479
|
+
parts.push(`[${block.type}]`);
|
|
75480
|
+
}
|
|
75481
|
+
}
|
|
75482
|
+
}
|
|
75483
|
+
return parts.join("\n").slice(0, MAX_ENTRY_BODY_CHARS) || null;
|
|
75484
|
+
}
|
|
75485
|
+
if (message.role === "assistant") {
|
|
75486
|
+
const parts = ["# assistant message"];
|
|
75487
|
+
const usage = message.usage;
|
|
75488
|
+
if (usage) {
|
|
75489
|
+
parts.push(
|
|
75490
|
+
`usage: input ${usage.input} \xB7 output ${usage.output} \xB7 cacheRead ${usage.cacheRead} \xB7 cacheWrite ${usage.cacheWrite}`
|
|
75491
|
+
);
|
|
75492
|
+
}
|
|
75493
|
+
if (Array.isArray(message.content)) {
|
|
75494
|
+
for (const block of message.content) {
|
|
75495
|
+
if (block.type === "text") {
|
|
75496
|
+
parts.push(block.text);
|
|
75497
|
+
} else if (block.type === "thinking") {
|
|
75498
|
+
parts.push("[thinking omitted from context on most providers]");
|
|
75499
|
+
} else if (block.type === "toolCall") {
|
|
75500
|
+
parts.push(`\u2192 ${block.name}(${JSON.stringify(block.arguments)})`);
|
|
75501
|
+
}
|
|
75502
|
+
}
|
|
75503
|
+
}
|
|
75504
|
+
return parts.join("\n").slice(0, MAX_ENTRY_BODY_CHARS) || null;
|
|
75505
|
+
}
|
|
75506
|
+
if (message.role === "toolResult") {
|
|
75507
|
+
const parts = [`# tool result (${message.toolCallId})`];
|
|
75508
|
+
if (Array.isArray(message.content)) {
|
|
75509
|
+
for (const block of message.content) {
|
|
75510
|
+
if (block.type === "text") {
|
|
75511
|
+
parts.push(block.text);
|
|
75512
|
+
} else if (block.type === "image") {
|
|
75513
|
+
parts.push("[image]");
|
|
75514
|
+
} else if (block.type === "audio") {
|
|
75515
|
+
parts.push("[audio]");
|
|
75516
|
+
} else if (block.type === "video") {
|
|
75517
|
+
parts.push("[video]");
|
|
75518
|
+
} else {
|
|
75519
|
+
parts.push(`[${block.type}]`);
|
|
75520
|
+
}
|
|
75521
|
+
}
|
|
75522
|
+
}
|
|
75523
|
+
return parts.join("\n").slice(0, MAX_ENTRY_BODY_CHARS) || null;
|
|
75524
|
+
}
|
|
75525
|
+
return JSON.stringify(message, null, 2).slice(0, MAX_ENTRY_BODY_CHARS) || null;
|
|
75526
|
+
}
|
|
75527
|
+
function handleContextReportCommand(host) {
|
|
75528
|
+
const systemPrompt = host.agent.state.systemPrompt ?? "";
|
|
75529
|
+
const knowledgeFiles = parseProjectContextSection(host.knowledgeSection);
|
|
75530
|
+
const entries = host.sessionManager.getActiveContextSummaries();
|
|
75531
|
+
const usage = host.calculateContextUsage();
|
|
75532
|
+
const contextWindow = host.options.model?.contextWindow ?? 0;
|
|
75533
|
+
const reserveTokens = host.options.settingsManager.getAutoCompactReserveTokens();
|
|
75534
|
+
const autoCompactLimit = contextWindow > 0 ? getAutoCompactTokenLimit(contextWindow, reserveTokens) ?? null : null;
|
|
75535
|
+
const prefixHash = computePromptPrefixHash(
|
|
75536
|
+
systemPrompt,
|
|
75537
|
+
host.agent.state.tools.map((tool) => ({
|
|
75538
|
+
name: tool.name,
|
|
75539
|
+
description: tool.description,
|
|
75540
|
+
parameters: tool.parameters
|
|
75541
|
+
}))
|
|
75542
|
+
);
|
|
75543
|
+
const lastSignals2 = getLastContextSignals(host);
|
|
75544
|
+
const promptPrefixChanged = lastSignals2 !== null && lastSignals2.prefixHash !== prefixHash;
|
|
75545
|
+
const report = buildContextReportData({
|
|
75546
|
+
systemPrompt,
|
|
75547
|
+
skillsSection: host.skillsSection,
|
|
75548
|
+
knowledgeFiles,
|
|
75549
|
+
skills: host.skills.map((skill) => ({
|
|
75550
|
+
name: skill.name,
|
|
75551
|
+
description: skill.description,
|
|
75552
|
+
filePath: skill.filePath,
|
|
75553
|
+
baseDir: skill.baseDir,
|
|
75554
|
+
source: skill.source
|
|
75555
|
+
})),
|
|
75556
|
+
tools: host.agent.state.tools.map((tool) => ({
|
|
75557
|
+
name: tool.name,
|
|
75558
|
+
label: tool.label,
|
|
75559
|
+
description: tool.description,
|
|
75560
|
+
parameters: tool.parameters
|
|
75561
|
+
})),
|
|
75562
|
+
entries,
|
|
75563
|
+
compactionTokensBefore: (entryId) => host.sessionManager.getEntry(entryId)?.compactionData?.tokensBefore,
|
|
75564
|
+
contextWindow,
|
|
75565
|
+
actualTokens: usage.tokens,
|
|
75566
|
+
autoCompactLimitTokens: autoCompactLimit,
|
|
75567
|
+
reserveTokens,
|
|
75568
|
+
promptPrefixHash: prefixHash,
|
|
75569
|
+
promptPrefixChanged
|
|
75570
|
+
});
|
|
75571
|
+
enhanceCheckpointRowWithArchive(report, host, entries);
|
|
75572
|
+
host.chatContainer.addChild(new Spacer(1));
|
|
75573
|
+
host.chatContainer.addChild(new Text(buildContextOverviewText(report, theme), 1, 0));
|
|
75574
|
+
host.ui.requestRender();
|
|
75575
|
+
host.showSelector((done) => {
|
|
75576
|
+
const selector = new ContextReportSelectorComponent({
|
|
75577
|
+
title: "Context Report",
|
|
75578
|
+
sections: report.sections,
|
|
75579
|
+
windowSection: {
|
|
75580
|
+
label: "window & thresholds",
|
|
75581
|
+
estTokens: report.contextWindow,
|
|
75582
|
+
valueText: report.contextWindow > 0 ? formatReportTokens(report.contextWindow) : "?",
|
|
75583
|
+
title: "Window & Thresholds",
|
|
75584
|
+
detail: "context window, estimate vs actual, auto-compact",
|
|
75585
|
+
rows: buildWindowRows(report)
|
|
75586
|
+
},
|
|
75587
|
+
terminalHeight: host.ui.terminal.rows,
|
|
75588
|
+
getEntryText: (entryId) => formatEntryBodyText(host.sessionManager.getEntry(entryId)),
|
|
75589
|
+
onDone: done
|
|
75590
|
+
});
|
|
75591
|
+
return { component: selector, focus: selector };
|
|
75592
|
+
});
|
|
75593
|
+
}
|
|
75594
|
+
|
|
75595
|
+
// src/core/trace-report.ts
|
|
75596
|
+
var MAX_DRILL_CHARS = 8e3;
|
|
75597
|
+
function formatTime(at) {
|
|
75598
|
+
return new Date(at).toLocaleTimeString([], { hour12: false });
|
|
75599
|
+
}
|
|
75600
|
+
function formatDurationMs(ms) {
|
|
75601
|
+
if (ms < 1e3) return `${Math.round(ms)}ms`;
|
|
75602
|
+
if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
|
|
75603
|
+
return `${Math.floor(ms / 6e4)}m${Math.round(ms % 6e4 / 1e3)}s`;
|
|
75604
|
+
}
|
|
75605
|
+
function detailsToText(event) {
|
|
75606
|
+
const header = [
|
|
75607
|
+
`# ${event.type}`,
|
|
75608
|
+
`at: ${new Date(event.at).toISOString()}`,
|
|
75609
|
+
event.summary ? `summary: ${event.summary}` : "",
|
|
75610
|
+
event.failure ? "failure: true" : ""
|
|
75611
|
+
].filter(Boolean).join("\n");
|
|
75612
|
+
const details = event.details === void 0 ? "" : `
|
|
75613
|
+
|
|
75614
|
+
# details
|
|
75615
|
+
${safeStringify(event.details).slice(0, MAX_DRILL_CHARS)}`;
|
|
75616
|
+
return `${header}${details}`;
|
|
75617
|
+
}
|
|
75618
|
+
function safeStringify(value) {
|
|
75619
|
+
try {
|
|
75620
|
+
return typeof value === "string" ? value : JSON.stringify(value, null, 2);
|
|
75621
|
+
} catch {
|
|
75622
|
+
return String(value);
|
|
75623
|
+
}
|
|
75624
|
+
}
|
|
75625
|
+
function buildTimelineRows(timeline) {
|
|
75626
|
+
if (timeline.length === 0) {
|
|
75627
|
+
return [{ id: "timeline:none", label: "no runtime events recorded yet", estTokens: 0 }];
|
|
75628
|
+
}
|
|
75629
|
+
return [...timeline].sort((a, b2) => b2.at - a.at).map((event, index) => ({
|
|
75630
|
+
id: `timeline:${event.at}:${index}`,
|
|
75631
|
+
label: `${formatTime(event.at)} ${event.type}`,
|
|
75632
|
+
estTokens: 0,
|
|
75633
|
+
detail: event.summary || void 0,
|
|
75634
|
+
marker: event.failure ? "\u2716" : void 0,
|
|
75635
|
+
drill: {
|
|
75636
|
+
kind: "text",
|
|
75637
|
+
title: `Event \xB7 ${event.type}`,
|
|
75638
|
+
text: detailsToText(event)
|
|
75639
|
+
}
|
|
75640
|
+
}));
|
|
75641
|
+
}
|
|
75642
|
+
function aggregateToolStats(turns) {
|
|
75643
|
+
const stats = /* @__PURE__ */ new Map();
|
|
75644
|
+
for (const turn of turns) {
|
|
75645
|
+
for (const call of turn.toolCalls) {
|
|
75646
|
+
const stat2 = stats.get(call.toolName) ?? {
|
|
75647
|
+
name: call.toolName,
|
|
75648
|
+
calls: 0,
|
|
75649
|
+
errors: 0,
|
|
75650
|
+
totalMs: 0
|
|
75651
|
+
};
|
|
75652
|
+
stat2.calls += 1;
|
|
75653
|
+
if (call.status === "failed") stat2.errors += 1;
|
|
75654
|
+
if (call.endedAt !== void 0 && call.endedAt >= call.startedAt) {
|
|
75655
|
+
stat2.totalMs += call.endedAt - call.startedAt;
|
|
75656
|
+
}
|
|
75657
|
+
stats.set(call.toolName, stat2);
|
|
75658
|
+
}
|
|
75659
|
+
}
|
|
75660
|
+
return [...stats.values()].sort((a, b2) => b2.totalMs - a.totalMs || b2.calls - a.calls);
|
|
75661
|
+
}
|
|
75662
|
+
function buildToolStatRows(turns) {
|
|
75663
|
+
const stats = aggregateToolStats(turns);
|
|
75664
|
+
if (stats.length === 0) {
|
|
75665
|
+
return [{ id: "tools:none", label: "no tool calls in recent turns", estTokens: 0 }];
|
|
75666
|
+
}
|
|
75667
|
+
return stats.map((stat2) => ({
|
|
75668
|
+
id: `toolstat:${stat2.name}`,
|
|
75669
|
+
label: stat2.name,
|
|
75670
|
+
estTokens: 0,
|
|
75671
|
+
valueText: formatDurationMs(stat2.totalMs),
|
|
75672
|
+
note: `${stat2.calls} calls${stat2.errors > 0 ? ` \xB7 ${stat2.errors} errors` : ""}`,
|
|
75673
|
+
drill: {
|
|
75674
|
+
kind: "rows",
|
|
75675
|
+
title: `Tool Calls \xB7 ${stat2.name}`,
|
|
75676
|
+
rowKind: "plain",
|
|
75677
|
+
rows: collectCalls(turns, stat2.name)
|
|
75678
|
+
}
|
|
75679
|
+
}));
|
|
75680
|
+
}
|
|
75681
|
+
function collectCalls(turns, toolName) {
|
|
75682
|
+
const rows = [];
|
|
75683
|
+
for (const turn of turns) {
|
|
75684
|
+
for (const call of turn.toolCalls) {
|
|
75685
|
+
if (call.toolName !== toolName) continue;
|
|
75686
|
+
const duration = call.endedAt !== void 0 && call.endedAt >= call.startedAt ? formatDurationMs(call.endedAt - call.startedAt) : "running";
|
|
75687
|
+
rows.push({
|
|
75688
|
+
id: `call:${call.toolCallId ?? `${call.startedAt}:${rows.length}`}`,
|
|
75689
|
+
label: `${formatTime(call.startedAt)} ${call.status}`,
|
|
75690
|
+
estTokens: 0,
|
|
75691
|
+
valueText: duration,
|
|
75692
|
+
detail: call.resultSummary || void 0,
|
|
75693
|
+
marker: call.status === "failed" ? "\u2716" : void 0,
|
|
75694
|
+
drill: {
|
|
75695
|
+
kind: "text",
|
|
75696
|
+
title: `Call \xB7 ${toolName}`,
|
|
75697
|
+
text: [
|
|
75698
|
+
`# ${toolName} (${call.status})`,
|
|
75699
|
+
`started: ${new Date(call.startedAt).toISOString()}`,
|
|
75700
|
+
call.endedAt !== void 0 ? `ended: ${new Date(call.endedAt).toISOString()}` : "",
|
|
75701
|
+
call.outcome !== void 0 ? `
|
|
75702
|
+
# outcome
|
|
75703
|
+
${safeStringify(call.outcome)}` : ""
|
|
75704
|
+
].filter(Boolean).join("\n").slice(0, MAX_DRILL_CHARS)
|
|
75705
|
+
}
|
|
75706
|
+
});
|
|
75707
|
+
}
|
|
75708
|
+
}
|
|
75709
|
+
return rows.sort((a, b2) => a.id.localeCompare(b2.id));
|
|
75710
|
+
}
|
|
75711
|
+
function buildTurnRows(turns) {
|
|
75712
|
+
if (turns.length === 0) {
|
|
75713
|
+
return [{ id: "turns:none", label: "no completed turns recorded yet", estTokens: 0 }];
|
|
75714
|
+
}
|
|
75715
|
+
return [...turns].sort((a, b2) => b2.turnIndex - a.turnIndex).map((turn) => {
|
|
75716
|
+
const duration = turn.completedAt !== void 0 && turn.startedAt !== void 0 && turn.completedAt >= turn.startedAt ? formatDurationMs(turn.completedAt - turn.startedAt) : "\u2014";
|
|
75717
|
+
return {
|
|
75718
|
+
id: `turn:${turn.turnIndex}`,
|
|
75719
|
+
label: `#${turn.turnIndex} ${turn.state}`,
|
|
75720
|
+
estTokens: 0,
|
|
75721
|
+
valueText: duration,
|
|
75722
|
+
note: `${turn.toolCalls.length} tool calls`,
|
|
75723
|
+
detail: turn.userText?.slice(0, 80) || void 0,
|
|
75724
|
+
marker: turn.state === "failed" ? "\u2716" : void 0,
|
|
75725
|
+
drill: {
|
|
75726
|
+
kind: "text",
|
|
75727
|
+
title: `Turn #${turn.turnIndex}`,
|
|
75728
|
+
text: turnToText(turn)
|
|
75729
|
+
}
|
|
75730
|
+
};
|
|
75731
|
+
});
|
|
75732
|
+
}
|
|
75733
|
+
function turnToText(turn) {
|
|
75734
|
+
const parts = [
|
|
75735
|
+
`# turn ${turn.turnIndex} (${turn.state})`,
|
|
75736
|
+
turn.startedAt !== void 0 ? `started: ${new Date(turn.startedAt).toISOString()}` : "",
|
|
75737
|
+
turn.completedAt !== void 0 ? `completed: ${new Date(turn.completedAt).toISOString()}` : ""
|
|
75738
|
+
];
|
|
75739
|
+
if (turn.userText) parts.push(`
|
|
75740
|
+
# user
|
|
75741
|
+
${turn.userText.slice(0, 2e3)}`);
|
|
75742
|
+
if (turn.assistantText) parts.push(`
|
|
75743
|
+
# assistant
|
|
75744
|
+
${turn.assistantText.slice(0, 2e3)}`);
|
|
75745
|
+
if (turn.errorMessage) parts.push(`
|
|
75746
|
+
# error
|
|
75747
|
+
${turn.errorMessage}`);
|
|
75748
|
+
if (turn.toolCalls.length > 0) {
|
|
75749
|
+
parts.push(
|
|
75750
|
+
`
|
|
75751
|
+
# tool calls
|
|
75752
|
+
${turn.toolCalls.map(
|
|
75753
|
+
(call) => `- ${call.toolName} (${call.status})${call.endedAt !== void 0 && call.endedAt >= call.startedAt ? ` ${formatDurationMs(call.endedAt - call.startedAt)}` : ""}${call.resultSummary ? ` \u2014 ${call.resultSummary.slice(0, 200)}` : ""}`
|
|
75754
|
+
).join("\n")}`
|
|
75755
|
+
);
|
|
75756
|
+
}
|
|
75757
|
+
return parts.filter(Boolean).join("\n").slice(0, MAX_DRILL_CHARS);
|
|
75758
|
+
}
|
|
75759
|
+
function buildRuntimeSummaryRows(snapshot) {
|
|
75760
|
+
const summary = snapshot.runtimeSummary;
|
|
75761
|
+
if (!summary) {
|
|
75762
|
+
return [{ id: "runtime:none", label: "no runtime summary recorded yet", estTokens: 0 }];
|
|
75763
|
+
}
|
|
75764
|
+
const entries = [
|
|
75765
|
+
["tool results", summary.toolResults, "completed tool calls (recent turns)"],
|
|
75766
|
+
["tool errors", summary.toolErrors, "failed tool calls (recent turns)"],
|
|
75767
|
+
["retries", summary.retryEvents, "provider/overflow retries"],
|
|
75768
|
+
["auto-compactions", summary.autoCompactionEvents, "context checkpoints this session"],
|
|
75769
|
+
["runtime guard events", summary.runtimeGuardEvents, "guard advisories triggered"],
|
|
75770
|
+
["queued turn events", summary.queuedTurnEvents, "steer/followUp queue dispatches"],
|
|
75771
|
+
["subagent events", summary.subagentEvents, "subagent lifecycle events"]
|
|
75772
|
+
];
|
|
75773
|
+
return entries.map(([label, count, detail]) => ({
|
|
75774
|
+
id: `runtime:${label}`,
|
|
75775
|
+
label,
|
|
75776
|
+
estTokens: count,
|
|
75777
|
+
valueText: String(count),
|
|
75778
|
+
note: count > 0 ? void 0 : "none",
|
|
75779
|
+
detail
|
|
75780
|
+
}));
|
|
75781
|
+
}
|
|
75782
|
+
function buildSubagentRows(snapshot) {
|
|
75783
|
+
const summaries = snapshot.subagentSummaries ?? [];
|
|
75784
|
+
if (summaries.length === 0) {
|
|
75785
|
+
return [{ id: "subagents:none", label: "no subagent tasks recorded yet", estTokens: 0 }];
|
|
75786
|
+
}
|
|
75787
|
+
return summaries.map((sub, index) => ({
|
|
75788
|
+
id: `subagent:${sub.toolCallId ?? index}`,
|
|
75789
|
+
label: sub.name,
|
|
75790
|
+
estTokens: 0,
|
|
75791
|
+
valueText: sub.status,
|
|
75792
|
+
note: sub.modelId ? `${sub.modelClass ? `${sub.modelClass}/` : ""}${sub.modelId}` : void 0,
|
|
75793
|
+
detail: [
|
|
75794
|
+
sub.evidenceCount > 0 ? `${sub.evidenceCount} evidence` : "",
|
|
75795
|
+
sub.failureReason ? `failed: ${sub.failureReason}` : "",
|
|
75796
|
+
sub.modelFallbackReason ? `fallback: ${sub.modelFallbackReason}` : ""
|
|
75797
|
+
].filter(Boolean).join(" \xB7 ") || void 0,
|
|
75798
|
+
marker: sub.status === "failed" || sub.failureReason ? "\u2716" : void 0,
|
|
75799
|
+
drill: {
|
|
75800
|
+
kind: "text",
|
|
75801
|
+
title: `Subagent \xB7 ${sub.name}`,
|
|
75802
|
+
text: safeStringify(sub).slice(0, MAX_DRILL_CHARS)
|
|
75803
|
+
}
|
|
75804
|
+
}));
|
|
75805
|
+
}
|
|
75806
|
+
function buildTraceSections(snapshot) {
|
|
75807
|
+
const turns = [...snapshot.recentTurns];
|
|
75808
|
+
if (snapshot.activeTurn) turns.push(snapshot.activeTurn);
|
|
75809
|
+
const timeline = snapshot.recentTimeline ?? [];
|
|
75810
|
+
return [
|
|
75811
|
+
{
|
|
75812
|
+
id: "trace-timeline",
|
|
75813
|
+
title: `Timeline (${timeline.length})`,
|
|
75814
|
+
estTokens: 0,
|
|
75815
|
+
rows: buildTimelineRows(timeline)
|
|
75816
|
+
},
|
|
75817
|
+
{
|
|
75818
|
+
id: "trace-tools",
|
|
75819
|
+
title: "Tool stats (recent turns)",
|
|
75820
|
+
estTokens: 0,
|
|
75821
|
+
note: aggregateToolStats(turns)[0] ? `slowest: ${aggregateToolStats(turns)[0].name} ${formatDurationMs(aggregateToolStats(turns)[0].totalMs)}` : void 0,
|
|
75822
|
+
rows: buildToolStatRows(turns)
|
|
75823
|
+
},
|
|
75824
|
+
{
|
|
75825
|
+
id: "trace-turns",
|
|
75826
|
+
title: `Recent turns (${snapshot.recentTurns.length}${snapshot.activeTurn ? " +1 active" : ""})`,
|
|
75827
|
+
estTokens: 0,
|
|
75828
|
+
rows: buildTurnRows(
|
|
75829
|
+
snapshot.activeTurn ? [...snapshot.recentTurns, snapshot.activeTurn] : snapshot.recentTurns
|
|
75830
|
+
)
|
|
75831
|
+
},
|
|
75832
|
+
{
|
|
75833
|
+
id: "trace-runtime",
|
|
75834
|
+
title: "Runtime summary",
|
|
75835
|
+
estTokens: 0,
|
|
75836
|
+
rows: buildRuntimeSummaryRows(snapshot)
|
|
75837
|
+
},
|
|
75838
|
+
{
|
|
75839
|
+
id: "trace-subagents",
|
|
75840
|
+
title: `Subagents (${(snapshot.subagentSummaries ?? []).length})`,
|
|
75841
|
+
estTokens: 0,
|
|
75842
|
+
rows: buildSubagentRows(snapshot)
|
|
75843
|
+
}
|
|
75844
|
+
];
|
|
75845
|
+
}
|
|
75846
|
+
function buildTraceOverviewText(snapshot, theme2) {
|
|
75847
|
+
const t = theme2 ?? { bold: (s) => s, fg: (_k, s) => s };
|
|
75848
|
+
const lines = [];
|
|
75849
|
+
const turns = snapshot.recentTurns.length + (snapshot.activeTurn ? 1 : 0);
|
|
75850
|
+
const timeline = snapshot.recentTimeline ?? [];
|
|
75851
|
+
lines.push(t.bold("Session Trace") + t.fg("dim", ` \xB7 ${turns} recent turns \xB7 ${timeline.length} events`));
|
|
75852
|
+
const summary = snapshot.runtimeSummary;
|
|
75853
|
+
if (summary) {
|
|
75854
|
+
const notable = [];
|
|
75855
|
+
if (summary.retryEvents > 0) notable.push(`retries ${summary.retryEvents}`);
|
|
75856
|
+
if (summary.autoCompactionEvents > 0) notable.push(`compactions ${summary.autoCompactionEvents}`);
|
|
75857
|
+
if (summary.runtimeGuardEvents > 0) notable.push(`guard ${summary.runtimeGuardEvents}`);
|
|
75858
|
+
if (summary.toolErrors > 0) notable.push(`tool errors ${summary.toolErrors}`);
|
|
75859
|
+
if (notable.length > 0) {
|
|
75860
|
+
lines.push(t.fg("dim", ` events: ${notable.join(" \xB7 ")}`));
|
|
75861
|
+
} else {
|
|
75862
|
+
lines.push(t.fg("dim", " no retries, compactions, or guard events"));
|
|
75863
|
+
}
|
|
75864
|
+
}
|
|
75865
|
+
const stats = aggregateToolStats([...snapshot.recentTurns, ...snapshot.activeTurn ? [snapshot.activeTurn] : []]);
|
|
75866
|
+
if (stats.length > 0) {
|
|
75867
|
+
const top = stats.slice(0, 3).map((s) => `${s.name} ${formatDurationMs(s.totalMs)} (${s.calls})`);
|
|
75868
|
+
lines.push(t.fg("dim", ` tools: ${top.join(" \xB7 ")}`));
|
|
75869
|
+
}
|
|
75870
|
+
lines.push(t.fg("dim", " /debugs/trace \xB7 Enter to drill, Esc to go back"));
|
|
75871
|
+
return lines.join("\n");
|
|
75872
|
+
}
|
|
75873
|
+
|
|
75874
|
+
// src/commands/interactive-trace-command.ts
|
|
75875
|
+
function handleTraceCommand(host, snapshot) {
|
|
75876
|
+
if (!snapshot) {
|
|
75877
|
+
host.showStatus("No session trace yet \u2014 it starts with the first turn");
|
|
75878
|
+
return;
|
|
75879
|
+
}
|
|
75880
|
+
const sections = buildTraceSections(snapshot);
|
|
75881
|
+
host.chatContainer.addChild(new Spacer(1));
|
|
75882
|
+
host.chatContainer.addChild(new Text(buildTraceOverviewText(snapshot, theme), 1, 0));
|
|
75883
|
+
host.ui.requestRender();
|
|
75884
|
+
host.showSelector((done) => {
|
|
75885
|
+
const selector = new ContextReportSelectorComponent({
|
|
75886
|
+
title: "Session Trace",
|
|
75887
|
+
sections,
|
|
75888
|
+
terminalHeight: host.ui.terminal.rows,
|
|
75889
|
+
onDone: done
|
|
75890
|
+
});
|
|
75891
|
+
return { component: selector, focus: selector };
|
|
75892
|
+
});
|
|
75893
|
+
}
|
|
75894
|
+
|
|
75895
|
+
// src/core/boot-report.ts
|
|
75896
|
+
function stepToText(step) {
|
|
75897
|
+
const lines = [
|
|
75898
|
+
`# ${step.id}`,
|
|
75899
|
+
`input: ${step.inputSummary}`,
|
|
75900
|
+
`output: ${step.outputSummary}`
|
|
75901
|
+
];
|
|
75902
|
+
if (step.toolCount !== void 0) lines.push(`tools: ${step.toolCount}`);
|
|
75903
|
+
if (step.policyDecisions?.length) {
|
|
75904
|
+
lines.push("", "# policy decisions", ...step.policyDecisions.map((decision) => `- ${decision}`));
|
|
75905
|
+
}
|
|
75906
|
+
if (step.extensionWrapping) {
|
|
75907
|
+
lines.push(
|
|
75908
|
+
"",
|
|
75909
|
+
"# extension wrapping",
|
|
75910
|
+
`extensions: ${step.extensionWrapping.extensionCount}`,
|
|
75911
|
+
`extension tools: ${step.extensionWrapping.extensionToolCount}`,
|
|
75912
|
+
`wrapped tools: ${step.extensionWrapping.wrappedToolCount}`
|
|
75913
|
+
);
|
|
75914
|
+
}
|
|
75915
|
+
return lines.join("\n");
|
|
75916
|
+
}
|
|
75917
|
+
function buildBootRows(trace) {
|
|
75918
|
+
if (trace.steps.length === 0) {
|
|
75919
|
+
return [{ id: "boot:none", label: "no composition steps recorded", estTokens: 0 }];
|
|
75920
|
+
}
|
|
75921
|
+
return trace.steps.map((step, index) => ({
|
|
75922
|
+
id: `boot:${step.id}`,
|
|
75923
|
+
label: `${index + 1}. ${step.id}`,
|
|
75924
|
+
estTokens: 0,
|
|
75925
|
+
note: step.toolCount !== void 0 ? `${step.toolCount} tools` : void 0,
|
|
75926
|
+
detail: step.outputSummary,
|
|
75927
|
+
drill: {
|
|
75928
|
+
kind: "text",
|
|
75929
|
+
title: `Step \xB7 ${step.id}`,
|
|
75930
|
+
text: stepToText(step)
|
|
75931
|
+
}
|
|
75932
|
+
}));
|
|
75933
|
+
}
|
|
75934
|
+
function buildBootSections(trace) {
|
|
75935
|
+
return [
|
|
75936
|
+
{
|
|
75937
|
+
id: "boot-pipeline",
|
|
75938
|
+
title: `Composition pipeline (${trace.steps.length} steps)`,
|
|
75939
|
+
estTokens: 0,
|
|
75940
|
+
rows: buildBootRows(trace)
|
|
75941
|
+
}
|
|
75942
|
+
];
|
|
75943
|
+
}
|
|
75944
|
+
function buildBootOverviewText(trace, theme2) {
|
|
75945
|
+
const t = theme2 ?? { bold: (s) => s, fg: (_k, s) => s };
|
|
75946
|
+
const lines = [];
|
|
75947
|
+
lines.push(t.bold("Boot Composition") + t.fg("dim", ` \xB7 ${trace.steps.length} steps`));
|
|
75948
|
+
for (const step of trace.steps) {
|
|
75949
|
+
lines.push(t.fg("dim", ` ${step.id} \u2014 ${step.outputSummary}`));
|
|
75950
|
+
}
|
|
75951
|
+
lines.push(t.fg("dim", " /debugs/boot \xB7 Enter to drill into a step"));
|
|
75952
|
+
return lines.join("\n");
|
|
75953
|
+
}
|
|
75954
|
+
|
|
75955
|
+
// src/commands/interactive-boot-command.ts
|
|
75956
|
+
function handleBootCommand(host) {
|
|
75957
|
+
const trace = host.options.compositionTrace;
|
|
75958
|
+
if (!trace || trace.steps.length === 0) {
|
|
75959
|
+
host.showStatus("No composition trace available for this runtime");
|
|
75960
|
+
return;
|
|
75961
|
+
}
|
|
75962
|
+
const sections = buildBootSections(trace);
|
|
75963
|
+
host.chatContainer.addChild(new Spacer(1));
|
|
75964
|
+
host.chatContainer.addChild(new Text(buildBootOverviewText(trace, theme), 1, 0));
|
|
75965
|
+
host.ui.requestRender();
|
|
75966
|
+
host.showSelector((done) => {
|
|
75967
|
+
const selector = new ContextReportSelectorComponent({
|
|
75968
|
+
title: "Boot Composition",
|
|
75969
|
+
sections,
|
|
75970
|
+
terminalHeight: host.ui.terminal.rows,
|
|
75971
|
+
onDone: done
|
|
75972
|
+
});
|
|
75973
|
+
return { component: selector, focus: selector };
|
|
75974
|
+
});
|
|
75975
|
+
}
|
|
75976
|
+
|
|
74639
75977
|
// src/commands/interactive-command-handlers.ts
|
|
74640
75978
|
function showSettingsSelector(host, focusItem) {
|
|
74641
75979
|
host.showSelector((done) => {
|
|
@@ -75060,6 +76398,7 @@ async function handleClearCommand(host) {
|
|
|
75060
76398
|
contextPercent: contextWindow > 0 && contextUsage.tokens !== null ? contextUsage.tokens / contextWindow * 100 : 0,
|
|
75061
76399
|
contextWindow
|
|
75062
76400
|
});
|
|
76401
|
+
applyContextSignalsToFooter(host);
|
|
75063
76402
|
host.updateTerminalTitle();
|
|
75064
76403
|
host.chatContainer.clear();
|
|
75065
76404
|
host.streamingComponent = void 0;
|
|
@@ -75106,6 +76445,7 @@ function handleSessionCommand(host) {
|
|
|
75106
76445
|
homeDir: process.env.HOME || process.env.USERPROFILE || "",
|
|
75107
76446
|
modelId: host.options.model?.id,
|
|
75108
76447
|
thinkingLevel: host.thinkingLevel,
|
|
76448
|
+
messages: host.sessionManager.getMessages(),
|
|
75109
76449
|
theme
|
|
75110
76450
|
});
|
|
75111
76451
|
host.chatContainer.addChild(new Spacer(1));
|
|
@@ -75339,12 +76679,16 @@ function registerBuiltinCommands(host) {
|
|
|
75339
76679
|
handler: () => host.handleCacheTest()
|
|
75340
76680
|
});
|
|
75341
76681
|
commandTree.register(["debugs", "context"], {
|
|
75342
|
-
description: "
|
|
75343
|
-
handler: () => host.
|
|
76682
|
+
description: "Context composition report: sections, tokens, drill-down",
|
|
76683
|
+
handler: () => host.handleDebugReportCommand("context")
|
|
75344
76684
|
});
|
|
75345
|
-
commandTree.register(["debugs", "
|
|
75346
|
-
description: "
|
|
75347
|
-
handler: () => host.
|
|
76685
|
+
commandTree.register(["debugs", "trace"], {
|
|
76686
|
+
description: "Session trace: timeline, tool stats, runtime events",
|
|
76687
|
+
handler: () => host.handleDebugReportCommand("trace")
|
|
76688
|
+
});
|
|
76689
|
+
commandTree.register(["debugs", "boot"], {
|
|
76690
|
+
description: "Boot composition pipeline: how the runtime was assembled",
|
|
76691
|
+
handler: () => host.handleDebugReportCommand("boot")
|
|
75348
76692
|
});
|
|
75349
76693
|
commandTree.register(["settings", "quit"], {
|
|
75350
76694
|
description: "Exit Pie",
|
|
@@ -75355,6 +76699,36 @@ function registerBuiltinCommands(host) {
|
|
|
75355
76699
|
});
|
|
75356
76700
|
}
|
|
75357
76701
|
|
|
76702
|
+
// src/runtime/compaction-diff.ts
|
|
76703
|
+
function summarizeActiveContext(summaries) {
|
|
76704
|
+
let tokens = 0;
|
|
76705
|
+
for (const summary of summaries) {
|
|
76706
|
+
tokens += summary.estTokens;
|
|
76707
|
+
}
|
|
76708
|
+
return { count: summaries.length, tokens };
|
|
76709
|
+
}
|
|
76710
|
+
function formatCompactionTokenLine(stats) {
|
|
76711
|
+
const saved = Math.max(0, stats.before.tokens - stats.after.tokens);
|
|
76712
|
+
const percent = stats.before.tokens > 0 ? Math.round(saved / stats.before.tokens * 100) : 0;
|
|
76713
|
+
return `~${formatReportTokens(stats.before.tokens)} \u2192 ~${formatReportTokens(stats.after.tokens)} tokens (saved ~${formatReportTokens(saved)}, \u2212${percent}%)`;
|
|
76714
|
+
}
|
|
76715
|
+
function renderCompactionDiffPanel(target, stats) {
|
|
76716
|
+
const archived = Math.max(0, stats.before.count - stats.after.count);
|
|
76717
|
+
target.chatContainer.addChild(new Spacer(1));
|
|
76718
|
+
target.chatContainer.addChild(new Text(theme.fg("accent", "\u2691 Context checkpoint"), 1, 0));
|
|
76719
|
+
target.chatContainer.addChild(
|
|
76720
|
+
new Text(
|
|
76721
|
+
theme.fg(
|
|
76722
|
+
"dim",
|
|
76723
|
+
` kept ${stats.after.count} entries \xB7 archived ${archived} entries \xB7 ${formatCompactionTokenLine(stats)}`
|
|
76724
|
+
),
|
|
76725
|
+
1,
|
|
76726
|
+
0
|
|
76727
|
+
)
|
|
76728
|
+
);
|
|
76729
|
+
target.safeRequestRender();
|
|
76730
|
+
}
|
|
76731
|
+
|
|
75358
76732
|
// src/commands/interactive-compact-command.ts
|
|
75359
76733
|
async function handleCompactCommand(host) {
|
|
75360
76734
|
if (host.submitLock || host.isProcessing || host.isCompacting) {
|
|
@@ -75373,6 +76747,7 @@ async function handleCompactCommand(host) {
|
|
|
75373
76747
|
host.chatContainer.addChild(new Spacer(1));
|
|
75374
76748
|
host.chatContainer.addChild(new Text(theme.fg("dim", "[/sessions/compact]"), 1, 0));
|
|
75375
76749
|
host.safeRequestRender();
|
|
76750
|
+
const beforeStats = summarizeActiveContext(host.sessionManager.getActiveContextSummaries());
|
|
75376
76751
|
try {
|
|
75377
76752
|
const activeEntryId = host.sessionManager.getActiveEntryId();
|
|
75378
76753
|
if (!activeEntryId) {
|
|
@@ -75415,8 +76790,10 @@ async function handleCompactCommand(host) {
|
|
|
75415
76790
|
host.lastStatusSpacer = void 0;
|
|
75416
76791
|
host.lastStatusText = void 0;
|
|
75417
76792
|
host.renderMessageHistory(compactedMessages);
|
|
75418
|
-
host
|
|
75419
|
-
|
|
76793
|
+
renderCompactionDiffPanel(host, {
|
|
76794
|
+
before: beforeStats,
|
|
76795
|
+
after: summarizeActiveContext(host.sessionManager.getActiveContextSummaries())
|
|
76796
|
+
});
|
|
75420
76797
|
const contextUsage = host.calculateContextUsage();
|
|
75421
76798
|
const contextWindow = host.options.model?.contextWindow ?? 0;
|
|
75422
76799
|
const contextPercent = contextWindow > 0 && contextUsage.tokens !== null ? contextUsage.tokens / contextWindow * 100 : 0;
|
|
@@ -75431,6 +76808,7 @@ async function handleCompactCommand(host) {
|
|
|
75431
76808
|
contextPercent,
|
|
75432
76809
|
contextWindow
|
|
75433
76810
|
});
|
|
76811
|
+
applyContextSignalsToFooter(host);
|
|
75434
76812
|
await host.sessionManager.save();
|
|
75435
76813
|
host.safeRequestRender();
|
|
75436
76814
|
} catch (error) {
|
|
@@ -77807,6 +79185,14 @@ var FooterComponent = class {
|
|
|
77807
79185
|
if (state.cacheRead) statsParts.push(`R${formatTokens(state.cacheRead)}`);
|
|
77808
79186
|
if (state.cacheWrite) statsParts.push(`W${formatTokens(state.cacheWrite)}`);
|
|
77809
79187
|
if (state.cost) statsParts.push(`$${state.cost.toFixed(3)}`);
|
|
79188
|
+
if (state.cacheHitRate != null) {
|
|
79189
|
+
statsParts.push(theme.fg("dim", `ca ${(state.cacheHitRate * 100).toFixed(0)}%`));
|
|
79190
|
+
}
|
|
79191
|
+
if (state.prefixHash) {
|
|
79192
|
+
statsParts.push(
|
|
79193
|
+
state.prefixHashChanged ? theme.fg("warning", `\u26A1${state.prefixHash}`) : theme.fg("dim", `\u2301${state.prefixHash}`)
|
|
79194
|
+
);
|
|
79195
|
+
}
|
|
77810
79196
|
if (state.contextWindow) {
|
|
77811
79197
|
const autoIndicator = this.autoCompactEnabled ? " (auto)" : "";
|
|
77812
79198
|
const percent = state.contextPercent ?? 0;
|
|
@@ -77879,27 +79265,13 @@ var FooterComponent = class {
|
|
|
77879
79265
|
// src/components/todo-widget.ts
|
|
77880
79266
|
var TodoWidgetComponent = class extends Container {
|
|
77881
79267
|
state;
|
|
77882
|
-
calmMode = false;
|
|
77883
79268
|
constructor(state) {
|
|
77884
79269
|
super();
|
|
77885
79270
|
this.state = state;
|
|
77886
79271
|
void this.refresh();
|
|
77887
79272
|
}
|
|
77888
|
-
/** Calm mode hides the progress widget (questions/answers only). */
|
|
77889
|
-
setCalmMode(calm) {
|
|
77890
|
-
if (this.calmMode === calm) return;
|
|
77891
|
-
this.calmMode = calm;
|
|
77892
|
-
if (calm) {
|
|
77893
|
-
this.clear();
|
|
77894
|
-
} else {
|
|
77895
|
-
void this.refresh();
|
|
77896
|
-
}
|
|
77897
|
-
}
|
|
77898
79273
|
async refresh() {
|
|
77899
79274
|
this.clear();
|
|
77900
|
-
if (this.calmMode) {
|
|
77901
|
-
return;
|
|
77902
|
-
}
|
|
77903
79275
|
const lines = renderExecutionWidgetLines(this.state.getWidgetSteps());
|
|
77904
79276
|
if (lines.length === 0) {
|
|
77905
79277
|
return;
|
|
@@ -78658,6 +80030,22 @@ function showStatus(host, message) {
|
|
|
78658
80030
|
host.lastStatusText = text;
|
|
78659
80031
|
host.ui.requestRender();
|
|
78660
80032
|
}
|
|
80033
|
+
function clearStatusLine(host) {
|
|
80034
|
+
const spacer = host.lastStatusSpacer;
|
|
80035
|
+
const text = host.lastStatusText;
|
|
80036
|
+
host.lastStatusSpacer = void 0;
|
|
80037
|
+
host.lastStatusText = void 0;
|
|
80038
|
+
let removed = false;
|
|
80039
|
+
if (spacer && host.chatContainer.children.includes(spacer)) {
|
|
80040
|
+
host.chatContainer.removeChild(spacer);
|
|
80041
|
+
removed = true;
|
|
80042
|
+
}
|
|
80043
|
+
if (text && host.chatContainer.children.includes(text)) {
|
|
80044
|
+
host.chatContainer.removeChild(text);
|
|
80045
|
+
removed = true;
|
|
80046
|
+
}
|
|
80047
|
+
if (removed) host.ui.requestRender();
|
|
80048
|
+
}
|
|
78661
80049
|
function showError(host, errorMessage4) {
|
|
78662
80050
|
host.chatContainer.addChild(new Spacer(1));
|
|
78663
80051
|
host.chatContainer.addChild(new Text(theme.fg("error", `Error: ${errorMessage4}`), 1, 0));
|
|
@@ -78874,6 +80262,7 @@ function createInteractiveAgentSessionController(host) {
|
|
|
78874
80262
|
}
|
|
78875
80263
|
let retryElapsedTicker;
|
|
78876
80264
|
let retryElapsedStartedAt = 0;
|
|
80265
|
+
let autoCompactBeforeStats = null;
|
|
78877
80266
|
const attention = cliAttention(host);
|
|
78878
80267
|
const stopRetryElapsedTicker = () => {
|
|
78879
80268
|
if (retryElapsedTicker !== void 0) {
|
|
@@ -78939,6 +80328,7 @@ function createInteractiveAgentSessionController(host) {
|
|
|
78939
80328
|
if (!firstKeptEntryId) return { aborted: true };
|
|
78940
80329
|
return { summary: beforeCompact.summary, firstKeptEntryId };
|
|
78941
80330
|
}
|
|
80331
|
+
autoCompactBeforeStats = summarizeActiveContext(context.sessionManager.getActiveContextSummaries());
|
|
78942
80332
|
return createCliAutoCompactionResult({
|
|
78943
80333
|
context,
|
|
78944
80334
|
model: host.options.model,
|
|
@@ -79107,6 +80497,7 @@ function createInteractiveAgentSessionController(host) {
|
|
|
79107
80497
|
host.showError(`${prefix}: ${event.errorMessage}`);
|
|
79108
80498
|
host.footer.setState({ status: "ready" });
|
|
79109
80499
|
host.setControllerBusy(false);
|
|
80500
|
+
autoCompactBeforeStats = null;
|
|
79110
80501
|
return;
|
|
79111
80502
|
}
|
|
79112
80503
|
host.resetFileObservationState();
|
|
@@ -79132,10 +80523,20 @@ function createInteractiveAgentSessionController(host) {
|
|
|
79132
80523
|
contextPercent,
|
|
79133
80524
|
contextWindow
|
|
79134
80525
|
});
|
|
80526
|
+
applyContextSignalsToFooter(host);
|
|
79135
80527
|
host.safeRequestRender();
|
|
79136
|
-
if (!event.
|
|
79137
|
-
|
|
80528
|
+
if (!event.result?.aborted) {
|
|
80529
|
+
if (autoCompactBeforeStats !== null) {
|
|
80530
|
+
renderCompactionDiffPanel(host, {
|
|
80531
|
+
before: autoCompactBeforeStats,
|
|
80532
|
+
after: summarizeActiveContext(host.sessionManager.getActiveContextSummaries())
|
|
80533
|
+
});
|
|
80534
|
+
}
|
|
80535
|
+
if (!event.willRetry) {
|
|
80536
|
+
host.showStatus("Context auto-compacted");
|
|
80537
|
+
}
|
|
79138
80538
|
}
|
|
80539
|
+
autoCompactBeforeStats = null;
|
|
79139
80540
|
} else if (event.type === "auto_continue_scheduled") {
|
|
79140
80541
|
host.setControllerBusy(true);
|
|
79141
80542
|
if (event.reason === "todo_closure") {
|
|
@@ -79382,6 +80783,7 @@ function sendDesktopNotification(reason, options = {}) {
|
|
|
79382
80783
|
lastNotificationAtMs = atMs;
|
|
79383
80784
|
const { title, body } = attentionMessage(reason);
|
|
79384
80785
|
terminal.notify(title, body);
|
|
80786
|
+
terminal.requestAttention?.();
|
|
79385
80787
|
return true;
|
|
79386
80788
|
}
|
|
79387
80789
|
|
|
@@ -79567,13 +80969,17 @@ function installInteractiveInteractionHandler(host) {
|
|
|
79567
80969
|
host.footer.setState({ lifecycleEvent: "\u25B6 resuming" });
|
|
79568
80970
|
host.safeRequestRender();
|
|
79569
80971
|
};
|
|
79570
|
-
const withTimeout2 = async (
|
|
80972
|
+
const withTimeout2 = async (createPromise) => {
|
|
80973
|
+
const controller = new AbortController();
|
|
79571
80974
|
if (!("timeoutMs" in request) || !request.timeoutMs || request.timeoutMs <= 0) {
|
|
79572
|
-
return { value: await
|
|
80975
|
+
return { value: await createPromise(controller.signal), timedOut: false };
|
|
79573
80976
|
}
|
|
79574
80977
|
return await new Promise((resolve7, reject) => {
|
|
79575
|
-
const timer = setTimeout(() =>
|
|
79576
|
-
|
|
80978
|
+
const timer = setTimeout(() => {
|
|
80979
|
+
controller.abort();
|
|
80980
|
+
resolve7({ timedOut: true });
|
|
80981
|
+
}, request.timeoutMs);
|
|
80982
|
+
createPromise(controller.signal).then((value) => {
|
|
79577
80983
|
clearTimeout(timer);
|
|
79578
80984
|
resolve7({ value, timedOut: false });
|
|
79579
80985
|
}).catch((error) => {
|
|
@@ -79586,7 +80992,7 @@ function installInteractiveInteractionHandler(host) {
|
|
|
79586
80992
|
beginWaitingForUser();
|
|
79587
80993
|
let resolution = "cancelled";
|
|
79588
80994
|
try {
|
|
79589
|
-
const result = await withTimeout2(createPromise
|
|
80995
|
+
const result = await withTimeout2(createPromise);
|
|
79590
80996
|
resolution = interactionAttentionResolution(result);
|
|
79591
80997
|
return result;
|
|
79592
80998
|
} finally {
|
|
@@ -79609,7 +81015,8 @@ function installInteractiveInteractionHandler(host) {
|
|
|
79609
81015
|
optionCount: request.options.length
|
|
79610
81016
|
});
|
|
79611
81017
|
const { value: selection, timedOut } = await waitForUser(
|
|
79612
|
-
() => showExtensionSelector2(host, request.prompt, request.options, {
|
|
81018
|
+
(signal) => showExtensionSelector2(host, request.prompt, request.options, {
|
|
81019
|
+
signal,
|
|
79613
81020
|
shortcuts: { left: request.leftShortcut, right: request.rightShortcut }
|
|
79614
81021
|
})
|
|
79615
81022
|
);
|
|
@@ -79628,7 +81035,7 @@ function installInteractiveInteractionHandler(host) {
|
|
|
79628
81035
|
detail: request.detail
|
|
79629
81036
|
});
|
|
79630
81037
|
const { value: confirmed, timedOut } = await waitForUser(
|
|
79631
|
-
() => showExtensionConfirm(host, request.prompt, request.detail ?? "")
|
|
81038
|
+
(signal) => showExtensionConfirm(host, request.prompt, request.detail ?? "", { signal })
|
|
79632
81039
|
);
|
|
79633
81040
|
host.logDebug("interaction:confirm:end", {
|
|
79634
81041
|
id: request.id,
|
|
@@ -79644,7 +81051,7 @@ function installInteractiveInteractionHandler(host) {
|
|
|
79644
81051
|
placeholder: request.placeholder
|
|
79645
81052
|
});
|
|
79646
81053
|
const { value, timedOut } = await waitForUser(
|
|
79647
|
-
() => showExtensionInput(host, request.prompt, request.placeholder)
|
|
81054
|
+
(signal) => showExtensionInput(host, request.prompt, request.placeholder, { signal })
|
|
79648
81055
|
);
|
|
79649
81056
|
host.logDebug("interaction:text_input:end", {
|
|
79650
81057
|
id: request.id,
|
|
@@ -79661,7 +81068,7 @@ function installInteractiveInteractionHandler(host) {
|
|
|
79661
81068
|
prefillLength: request.prefill?.length ?? 0
|
|
79662
81069
|
});
|
|
79663
81070
|
const { value, timedOut } = await waitForUser(
|
|
79664
|
-
() => showExtensionEditor(host, request.prompt, request.prefill)
|
|
81071
|
+
(signal) => showExtensionEditor(host, request.prompt, request.prefill, { signal })
|
|
79665
81072
|
);
|
|
79666
81073
|
host.logDebug("interaction:multiline_input:end", {
|
|
79667
81074
|
id: request.id,
|
|
@@ -79682,12 +81089,24 @@ function showExtensionNotification(host, message, type = "info") {
|
|
|
79682
81089
|
}
|
|
79683
81090
|
function showExtensionSelector2(host, title, options, opts) {
|
|
79684
81091
|
return new Promise((resolve7) => {
|
|
79685
|
-
|
|
81092
|
+
const promptLine = title.split("\n")[0].trim() || title.trim();
|
|
81093
|
+
host.showStatus(`Waiting for selection: ${promptLine}`);
|
|
79686
81094
|
if (opts?.signal?.aborted) {
|
|
81095
|
+
host.clearStatusLine?.();
|
|
79687
81096
|
resolve7(void 0);
|
|
79688
81097
|
return;
|
|
79689
81098
|
}
|
|
81099
|
+
const settle = (option) => {
|
|
81100
|
+
if (option === void 0) {
|
|
81101
|
+
host.clearStatusLine?.();
|
|
81102
|
+
} else {
|
|
81103
|
+
host.showStatus(`${promptLine} \u2192 ${option}`);
|
|
81104
|
+
}
|
|
81105
|
+
host.restoreEditor();
|
|
81106
|
+
resolve7(option);
|
|
81107
|
+
};
|
|
79690
81108
|
const onAbort = () => {
|
|
81109
|
+
host.clearStatusLine?.();
|
|
79691
81110
|
host.restoreEditor();
|
|
79692
81111
|
resolve7(void 0);
|
|
79693
81112
|
};
|
|
@@ -79697,13 +81116,11 @@ function showExtensionSelector2(host, title, options, opts) {
|
|
|
79697
81116
|
options,
|
|
79698
81117
|
(option) => {
|
|
79699
81118
|
opts?.signal?.removeEventListener("abort", onAbort);
|
|
79700
|
-
|
|
79701
|
-
resolve7(option);
|
|
81119
|
+
settle(option);
|
|
79702
81120
|
},
|
|
79703
81121
|
() => {
|
|
79704
81122
|
opts?.signal?.removeEventListener("abort", onAbort);
|
|
79705
|
-
|
|
79706
|
-
resolve7(void 0);
|
|
81123
|
+
settle(void 0);
|
|
79707
81124
|
},
|
|
79708
81125
|
opts?.shortcuts
|
|
79709
81126
|
);
|
|
@@ -79723,26 +81140,27 @@ function showExtensionInput(host, title, placeholder, opts) {
|
|
|
79723
81140
|
return new Promise((resolve7) => {
|
|
79724
81141
|
host.showStatus(`Waiting for input: ${title}`);
|
|
79725
81142
|
if (opts?.signal?.aborted) {
|
|
81143
|
+
host.clearStatusLine?.();
|
|
79726
81144
|
resolve7(void 0);
|
|
79727
81145
|
return;
|
|
79728
81146
|
}
|
|
79729
|
-
const
|
|
81147
|
+
const settle = (value) => {
|
|
81148
|
+
host.clearStatusLine?.();
|
|
79730
81149
|
host.restoreEditor();
|
|
79731
|
-
resolve7(
|
|
81150
|
+
resolve7(value);
|
|
79732
81151
|
};
|
|
81152
|
+
const onAbort = () => settle(void 0);
|
|
79733
81153
|
opts?.signal?.addEventListener("abort", onAbort, { once: true });
|
|
79734
81154
|
const input = new ExtensionInputComponent(
|
|
79735
81155
|
title,
|
|
79736
81156
|
placeholder,
|
|
79737
81157
|
(value) => {
|
|
79738
81158
|
opts?.signal?.removeEventListener("abort", onAbort);
|
|
79739
|
-
|
|
79740
|
-
resolve7(value);
|
|
81159
|
+
settle(value);
|
|
79741
81160
|
},
|
|
79742
81161
|
() => {
|
|
79743
81162
|
opts?.signal?.removeEventListener("abort", onAbort);
|
|
79744
|
-
|
|
79745
|
-
resolve7(void 0);
|
|
81163
|
+
settle(void 0);
|
|
79746
81164
|
}
|
|
79747
81165
|
);
|
|
79748
81166
|
host.editorContainer.clear();
|
|
@@ -79752,9 +81170,20 @@ function showExtensionInput(host, title, placeholder, opts) {
|
|
|
79752
81170
|
host.ui.requestRender();
|
|
79753
81171
|
});
|
|
79754
81172
|
}
|
|
79755
|
-
function showExtensionEditor(host, title, prefill) {
|
|
81173
|
+
function showExtensionEditor(host, title, prefill, opts) {
|
|
79756
81174
|
return new Promise((resolve7) => {
|
|
79757
81175
|
host.showStatus(`Waiting for input: ${title}`);
|
|
81176
|
+
const settle = (value) => {
|
|
81177
|
+
host.clearStatusLine?.();
|
|
81178
|
+
host.restoreEditor();
|
|
81179
|
+
resolve7(value);
|
|
81180
|
+
};
|
|
81181
|
+
const onAbort = () => settle(void 0);
|
|
81182
|
+
opts?.signal?.addEventListener("abort", onAbort, { once: true });
|
|
81183
|
+
if (opts?.signal?.aborted) {
|
|
81184
|
+
onAbort();
|
|
81185
|
+
return;
|
|
81186
|
+
}
|
|
79758
81187
|
const container = new Container();
|
|
79759
81188
|
container.addChild(new Text(theme.bold(theme.fg("accent", title)), 0, 0));
|
|
79760
81189
|
container.addChild(new Spacer(1));
|
|
@@ -79774,13 +81203,13 @@ function showExtensionEditor(host, title, prefill) {
|
|
|
79774
81203
|
valueLength: value.length,
|
|
79775
81204
|
preview: value.slice(0, 120)
|
|
79776
81205
|
});
|
|
79777
|
-
|
|
79778
|
-
|
|
81206
|
+
opts?.signal?.removeEventListener("abort", onAbort);
|
|
81207
|
+
settle(value);
|
|
79779
81208
|
};
|
|
79780
81209
|
editor.onEscape = () => {
|
|
79781
81210
|
host.logDebug("extension:editor:cancel", { title });
|
|
79782
|
-
|
|
79783
|
-
|
|
81211
|
+
opts?.signal?.removeEventListener("abort", onAbort);
|
|
81212
|
+
settle(void 0);
|
|
79784
81213
|
};
|
|
79785
81214
|
container.addChild(editor);
|
|
79786
81215
|
container.addChild(new Spacer(1));
|
|
@@ -80545,7 +81974,7 @@ var InteractiveMode = class {
|
|
|
80545
81974
|
async init() {
|
|
80546
81975
|
const activeSession = this.sessionManager.getActiveSession();
|
|
80547
81976
|
this.thinkingLevel = resolveInitialThinkingLevel({ session: activeSession, settingsManager: this.options.settingsManager });
|
|
80548
|
-
const { Agent } = await import("./chunks/src-
|
|
81977
|
+
const { Agent } = await import("./chunks/src-OWQI5M6W.js");
|
|
80549
81978
|
this.agent = new Agent({
|
|
80550
81979
|
initialState: {
|
|
80551
81980
|
systemPrompt: this.buildSystemPrompt(),
|
|
@@ -80771,7 +82200,6 @@ var InteractiveMode = class {
|
|
|
80771
82200
|
this.options.settingsManager.setCalmModeEnabled(enabled);
|
|
80772
82201
|
this.footer.setState({ calmMode: enabled });
|
|
80773
82202
|
applyCalmMode(this, enabled);
|
|
80774
|
-
this.todoWidget.setCalmMode(enabled);
|
|
80775
82203
|
this.extensionWidgets.setCalmMode(enabled);
|
|
80776
82204
|
this.showStatus(`Calm mode ${enabled ? "on \u2014 showing questions and final answers only" : "off"}`);
|
|
80777
82205
|
this.safeRequestRender(true);
|
|
@@ -80809,11 +82237,11 @@ var InteractiveMode = class {
|
|
|
80809
82237
|
async handleCacheTest() {
|
|
80810
82238
|
return handleCacheTest(this);
|
|
80811
82239
|
}
|
|
80812
|
-
async
|
|
80813
|
-
return
|
|
82240
|
+
async handleTreeCommand() {
|
|
82241
|
+
return handleTreeCommand(this);
|
|
80814
82242
|
}
|
|
80815
|
-
|
|
80816
|
-
return
|
|
82243
|
+
handleDebugReportCommand(kind) {
|
|
82244
|
+
return kind === "context" ? handleContextReportCommand(this) : kind === "trace" ? handleTraceCommand(this, this.sessionTrace.getLiveSnapshot()) : handleBootCommand(this);
|
|
80817
82245
|
}
|
|
80818
82246
|
async handleResumeCommand() {
|
|
80819
82247
|
return handleResumeCommand(this);
|
|
@@ -80833,9 +82261,6 @@ var InteractiveMode = class {
|
|
|
80833
82261
|
setWaitingForUser(waiting) {
|
|
80834
82262
|
return setWaitingForUser(this, waiting);
|
|
80835
82263
|
}
|
|
80836
|
-
async handleTreeCommand() {
|
|
80837
|
-
return handleTreeCommand(this);
|
|
80838
|
-
}
|
|
80839
82264
|
async forkAtEntry(entryId) {
|
|
80840
82265
|
return forkAtEntry(this, entryId);
|
|
80841
82266
|
}
|
|
@@ -80909,6 +82334,9 @@ var InteractiveMode = class {
|
|
|
80909
82334
|
showStatus(message) {
|
|
80910
82335
|
return showStatus(this.uiHelperHost, message);
|
|
80911
82336
|
}
|
|
82337
|
+
clearStatusLine() {
|
|
82338
|
+
return clearStatusLine(this.uiHelperHost);
|
|
82339
|
+
}
|
|
80912
82340
|
showError(errorMessage4) {
|
|
80913
82341
|
return showError(this.uiHelperHost, errorMessage4);
|
|
80914
82342
|
}
|
|
@@ -81377,7 +82805,7 @@ async function runPrintMode(params) {
|
|
|
81377
82805
|
`);
|
|
81378
82806
|
console.log("Assistant: ");
|
|
81379
82807
|
}
|
|
81380
|
-
const { Agent: AgentClass } = await import("./chunks/src-
|
|
82808
|
+
const { Agent: AgentClass } = await import("./chunks/src-OWQI5M6W.js");
|
|
81381
82809
|
let agent;
|
|
81382
82810
|
const printModeExtensions = await loadPrintModeExtensions({
|
|
81383
82811
|
cwd: runtime.cwd,
|
|
@@ -82238,7 +83666,7 @@ async function runJsonEventsMode(params) {
|
|
|
82238
83666
|
return;
|
|
82239
83667
|
}
|
|
82240
83668
|
const parent = agent;
|
|
82241
|
-
const { Agent: AgentClass } = await import("./chunks/src-
|
|
83669
|
+
const { Agent: AgentClass } = await import("./chunks/src-OWQI5M6W.js");
|
|
82242
83670
|
const sideAgent = new AgentClass({
|
|
82243
83671
|
initialState: {
|
|
82244
83672
|
systemPrompt: parent.state.systemPrompt,
|
|
@@ -82582,7 +84010,7 @@ async function runJsonEventsMode(params) {
|
|
|
82582
84010
|
if (runtime.initialModel.unconfigured || controller) {
|
|
82583
84011
|
return;
|
|
82584
84012
|
}
|
|
82585
|
-
const { Agent: AgentClass } = await import("./chunks/src-
|
|
84013
|
+
const { Agent: AgentClass } = await import("./chunks/src-OWQI5M6W.js");
|
|
82586
84014
|
const jsonModeExtensions = await loadJsonModeExtensions({ runtime, getAgent: () => agent });
|
|
82587
84015
|
extensionRunner = jsonModeExtensions.runner;
|
|
82588
84016
|
const tools = [...runtime.tools, ...jsonModeExtensions.extensionTools];
|