@caupulican/pi-adaptative 0.81.23 → 0.81.24

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.
Files changed (44) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/dist/core/agent-session.d.ts +2 -0
  3. package/dist/core/agent-session.d.ts.map +1 -1
  4. package/dist/core/agent-session.js +4 -3
  5. package/dist/core/agent-session.js.map +1 -1
  6. package/dist/core/autonomy/status.d.ts +2 -3
  7. package/dist/core/autonomy/status.d.ts.map +1 -1
  8. package/dist/core/autonomy/status.js +3 -12
  9. package/dist/core/autonomy/status.js.map +1 -1
  10. package/dist/core/autonomy-telemetry.d.ts +3 -8
  11. package/dist/core/autonomy-telemetry.d.ts.map +1 -1
  12. package/dist/core/autonomy-telemetry.js +15 -20
  13. package/dist/core/autonomy-telemetry.js.map +1 -1
  14. package/dist/core/cost/cost-summary.d.ts +26 -0
  15. package/dist/core/cost/cost-summary.d.ts.map +1 -0
  16. package/dist/core/cost/cost-summary.js +85 -0
  17. package/dist/core/cost/cost-summary.js.map +1 -0
  18. package/dist/core/cost/session-usage.d.ts.map +1 -1
  19. package/dist/core/cost/session-usage.js +8 -2
  20. package/dist/core/cost/session-usage.js.map +1 -1
  21. package/dist/core/session-analytics.d.ts +3 -1
  22. package/dist/core/session-analytics.d.ts.map +1 -1
  23. package/dist/core/session-analytics.js +33 -18
  24. package/dist/core/session-analytics.js.map +1 -1
  25. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  26. package/dist/modes/interactive/components/footer.js +4 -20
  27. package/dist/modes/interactive/components/footer.js.map +1 -1
  28. package/dist/modes/interactive/report-commands.d.ts.map +1 -1
  29. package/dist/modes/interactive/report-commands.js +7 -8
  30. package/dist/modes/interactive/report-commands.js.map +1 -1
  31. package/dist/modes/interactive/session-flow-commands.d.ts +1 -2
  32. package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
  33. package/dist/modes/interactive/session-flow-commands.js +8 -4
  34. package/dist/modes/interactive/session-flow-commands.js.map +1 -1
  35. package/docs/usage.md +6 -0
  36. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  37. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  38. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  39. package/examples/extensions/sandbox/package-lock.json +2 -2
  40. package/examples/extensions/sandbox/package.json +1 -1
  41. package/examples/extensions/with-deps/package-lock.json +2 -2
  42. package/examples/extensions/with-deps/package.json +1 -1
  43. package/npm-shrinkwrap.json +12 -12
  44. package/package.json +4 -4
@@ -1,5 +1,6 @@
1
1
  import { isAbsolute, relative, resolve, sep } from "node:path";
2
2
  import { truncateToWidth, visibleWidth } from "@caupulican/pi-tui";
3
+ import { formatFooterCostParts } from "../../../core/cost/cost-summary.js";
3
4
  import { theme } from "../theme/theme.js";
4
5
  /**
5
6
  * Sanitize text for display in a single-line status.
@@ -140,7 +141,6 @@ export class FooterComponent {
140
141
  let totalOutput = 0;
141
142
  let totalCacheRead = 0;
142
143
  let totalCacheWrite = 0;
143
- let totalCost = 0;
144
144
  const entries = this.session.sessionManager.getEntries();
145
145
  for (let i = 0; i < entries.length; i++) {
146
146
  const entry = entries[i];
@@ -153,12 +153,7 @@ export class FooterComponent {
153
153
  totalOutput += usage.output;
154
154
  totalCacheRead += usage.cacheRead;
155
155
  totalCacheWrite += usage.cacheWrite;
156
- totalCost += usage.cost.total;
157
156
  }
158
- // Roll up spawned/subagent cost (Cost Aggregation, Model A). Derived from the same
159
- // session entries, so the {entryCount} cache key above busts when new reports land.
160
- const totalSpawnedCost = this.session.getSpawnedUsage().cost;
161
- const dailyTotalCost = this.session.getDailyUsageTotals?.().totalCost ?? 0;
162
157
  const snapshot = {
163
158
  entryCount,
164
159
  messageCount,
@@ -166,9 +161,6 @@ export class FooterComponent {
166
161
  totalOutput,
167
162
  totalCacheRead,
168
163
  totalCacheWrite,
169
- totalCost,
170
- totalSpawnedCost,
171
- dailyTotalCost,
172
164
  // Calculate context usage from session (handles compaction correctly).
173
165
  // After compaction, tokens are unknown until the next LLM response.
174
166
  contextUsage: this.session.getContextUsage(),
@@ -179,7 +171,8 @@ export class FooterComponent {
179
171
  render(width) {
180
172
  const state = this.session.state;
181
173
  const usageSnapshot = this.getUsageSnapshot(state.messages?.length ?? 0);
182
- const { totalInput, totalOutput, totalCacheRead, totalCacheWrite, totalCost, totalSpawnedCost, dailyTotalCost, contextUsage, } = usageSnapshot;
174
+ const { totalInput, totalOutput, totalCacheRead, totalCacheWrite, contextUsage } = usageSnapshot;
175
+ const costSummary = this.session.getCostSummary();
183
176
  const contextWindow = contextUsage?.contextWindow ?? state.model?.contextWindow ?? 0;
184
177
  const contextPercentValue = contextUsage?.percent ?? 0;
185
178
  const contextPercent = contextUsage?.percent !== null ? contextPercentValue.toFixed(1) : "?";
@@ -205,16 +198,7 @@ export class FooterComponent {
205
198
  statsParts.push(`R${formatTokens(totalCacheRead)}`);
206
199
  if (totalCacheWrite)
207
200
  statsParts.push(`W${formatTokens(totalCacheWrite)}`);
208
- // Show cost with "(sub)" indicator if using OAuth subscription
209
- const usingSubscription = state.model ? this.session.modelRegistry.isUsingOAuth(state.model) : false;
210
- const grandTotalCost = totalCost + totalSpawnedCost;
211
- if (grandTotalCost || usingSubscription) {
212
- const costStr = `$${grandTotalCost.toFixed(3)}${usingSubscription ? " (sub)" : ""}`;
213
- statsParts.push(costStr);
214
- }
215
- if (dailyTotalCost) {
216
- statsParts.push(`day:$${dailyTotalCost.toFixed(3)}`);
217
- }
201
+ statsParts.push(...formatFooterCostParts(costSummary));
218
202
  // Colorize context percentage based on usage
219
203
  let contextPercentStr;
220
204
  const autoIndicator = this.autoCompactEnabled ? " (auto)" : "";
@@ -1 +1 @@
1
- {"version":3,"file":"footer.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/footer.ts"],"names":[],"mappings":"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","sourcesContent":["import { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport { type Component, truncateToWidth, visibleWidth } from \"@caupulican/pi-tui\";\nimport type { AgentSession } from \"../../../core/agent-session.ts\";\nimport type { ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.ts\";\nimport { theme } from \"../theme/theme.ts\";\n\n/**\n * Sanitize text for display in a single-line status.\n * Removes newlines, tabs, carriage returns, and other control characters.\n */\nfunction sanitizeStatusText(text: string): string {\n\t// Replace newlines, tabs, carriage returns with space, then collapse multiple spaces\n\treturn text\n\t\t.replace(/[\\r\\n\\t]/g, \" \")\n\t\t.replace(/ +/g, \" \")\n\t\t.trim();\n}\n\nfunction stripAnsi(text: string): string {\n\treturn text.replace(/\\u001b\\[[0-?]*[ -/]*[@-~]/g, \"\");\n}\n\nfunction normalizeLearningPhase(phase: string): string {\n\tconst normalized = phase\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9_-]+/g, \"\")\n\t\t.trim();\n\tif (!normalized) return \"active\";\n\tif (normalized === \"starting\") return \"start\";\n\tif (normalized === \"mapping\") return \"map\";\n\tif (normalized === \"scanning\") return \"scan\";\n\tif (normalized === \"auditing\") return \"audit\";\n\tif (normalized === \"learning\") return \"run\";\n\tif (normalized === \"pruning\") return \"prune\";\n\treturn normalized.slice(0, 16);\n}\n\nfunction formatExtensionStatuses(statuses: ReadonlyMap<string, string>): string[] {\n\tconst regularStatuses: string[] = [];\n\tconst learningPhases = new Set<string>();\n\tlet sawLearningStatus = false;\n\n\tfor (const [key, rawText] of Array.from(statuses.entries()).sort(([a], [b]) => a.localeCompare(b))) {\n\t\tconst text = sanitizeStatusText(rawText);\n\t\tconst plain = stripAnsi(text).trim();\n\t\tconst plainLower = plain.toLowerCase();\n\t\tlet phase: string | undefined;\n\n\t\tif (plainLower.startsWith(\"(learning)\")) {\n\t\t\tphase = plain.slice(\"(learning)\".length).trim();\n\t\t} else if (plainLower === \"learning\") {\n\t\t\tphase = \"active\";\n\t\t} else if (/^learn(?:ing)?\\s*[: ]/.test(plainLower)) {\n\t\t\tphase = plain.replace(/^learn(?:ing)?\\s*[: ]/i, \"\").trim();\n\t\t}\n\n\t\tif (phase !== undefined) {\n\t\t\tsawLearningStatus = true;\n\t\t\tlearningPhases.add(normalizeLearningPhase(phase));\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (key === \"auto-learn\" || key === \"continuous-learning\") {\n\t\t\tsawLearningStatus = true;\n\t\t\tlearningPhases.add(\"active\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tregularStatuses.push(text);\n\t}\n\n\tif (!sawLearningStatus) return regularStatuses;\n\tconst phases = Array.from(learningPhases).filter((phase) => phase !== \"active\");\n\tconst phaseText = phases.length > 0 ? phases.join(\"/\") : \"active\";\n\treturn [theme.fg(\"warning\", \"learn\") + theme.fg(\"dim\", `:${phaseText}`), ...regularStatuses];\n}\n\n/**\n * Format token counts for compact footer display.\n */\nfunction formatTokens(count: number): string {\n\tif (count < 1000) return count.toString();\n\tif (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n\tif (count < 1000000) return `${Math.round(count / 1000)}k`;\n\tif (count < 10000000) return `${(count / 1000000).toFixed(1)}M`;\n\treturn `${Math.round(count / 1000000)}M`;\n}\n\nexport function formatCwdForFooter(cwd: string, home: string | undefined): string {\n\tif (!home) return cwd;\n\n\tconst resolvedCwd = resolve(cwd);\n\tconst resolvedHome = resolve(home);\n\tconst relativeToHome = relative(resolvedHome, resolvedCwd);\n\tconst isInsideHome =\n\t\trelativeToHome === \"\" ||\n\t\t(relativeToHome !== \"..\" && !relativeToHome.startsWith(`..${sep}`) && !isAbsolute(relativeToHome));\n\n\tif (!isInsideHome) return cwd;\n\treturn relativeToHome === \"\" ? \"~\" : `~${sep}${relativeToHome}`;\n}\n\n/**\n * Footer component that shows pwd, token stats, and context usage.\n * Computes token/context stats from session, gets git branch and extension statuses from provider.\n */\ntype FooterUsageSnapshot = {\n\tentryCount: number;\n\tmessageCount: number;\n\ttotalInput: number;\n\ttotalOutput: number;\n\ttotalCacheRead: number;\n\ttotalCacheWrite: number;\n\ttotalCost: number;\n\t/** Rolled-up cost of spawned/subagent sessions (Cost Aggregation). 0 when none. */\n\ttotalSpawnedCost: number;\n\tdailyTotalCost: number;\n\tcontextUsage: ReturnType<AgentSession[\"getContextUsage\"]>;\n};\n\nexport class FooterComponent implements Component {\n\tprivate autoCompactEnabled = true;\n\tprivate session: AgentSession;\n\tprivate footerData: ReadonlyFooterDataProvider;\n\tprivate usageSnapshot?: FooterUsageSnapshot;\n\n\tconstructor(session: AgentSession, footerData: ReadonlyFooterDataProvider) {\n\t\tthis.session = session;\n\t\tthis.footerData = footerData;\n\t}\n\n\tsetSession(session: AgentSession): void {\n\t\tthis.session = session;\n\t\tthis.usageSnapshot = undefined;\n\t}\n\n\tsetAutoCompactEnabled(enabled: boolean): void {\n\t\tthis.autoCompactEnabled = enabled;\n\t}\n\n\t/**\n\t * Invalidate cached footer stats when session state changes.\n\t */\n\tinvalidate(): void {\n\t\tthis.usageSnapshot = undefined;\n\t}\n\n\t/**\n\t * Clean up resources.\n\t * Git watcher cleanup now handled by provider.\n\t */\n\tdispose(): void {\n\t\t// Git watcher cleanup handled by provider\n\t}\n\n\tprivate getUsageSnapshot(messageCount: number): FooterUsageSnapshot {\n\t\tconst sessionManager = this.session.sessionManager as AgentSession[\"sessionManager\"] & {\n\t\t\tgetEntryCount?: () => number;\n\t\t};\n\t\tconst entryCount = sessionManager.getEntryCount?.() ?? sessionManager.getEntries().length;\n\t\tconst cached = this.usageSnapshot;\n\t\tif (cached && cached.entryCount === entryCount && cached.messageCount === messageCount) {\n\t\t\treturn cached;\n\t\t}\n\n\t\t// Calculate cumulative usage from ALL session entries in one batched pass.\n\t\t// This avoids per-frame defensive array allocation when only the TUI redraws.\n\t\tlet totalInput = 0;\n\t\tlet totalOutput = 0;\n\t\tlet totalCacheRead = 0;\n\t\tlet totalCacheWrite = 0;\n\t\tlet totalCost = 0;\n\n\t\tconst entries = this.session.sessionManager.getEntries();\n\t\tfor (let i = 0; i < entries.length; i++) {\n\t\t\tconst entry = entries[i];\n\t\t\tif (entry.type !== \"message\" || entry.message.role !== \"assistant\") continue;\n\t\t\tconst usage = entry.message.usage;\n\t\t\tif (!usage) continue;\n\t\t\ttotalInput += usage.input;\n\t\t\ttotalOutput += usage.output;\n\t\t\ttotalCacheRead += usage.cacheRead;\n\t\t\ttotalCacheWrite += usage.cacheWrite;\n\t\t\ttotalCost += usage.cost.total;\n\t\t}\n\n\t\t// Roll up spawned/subagent cost (Cost Aggregation, Model A). Derived from the same\n\t\t// session entries, so the {entryCount} cache key above busts when new reports land.\n\t\tconst totalSpawnedCost = this.session.getSpawnedUsage().cost;\n\t\tconst dailyTotalCost = this.session.getDailyUsageTotals?.().totalCost ?? 0;\n\n\t\tconst snapshot: FooterUsageSnapshot = {\n\t\t\tentryCount,\n\t\t\tmessageCount,\n\t\t\ttotalInput,\n\t\t\ttotalOutput,\n\t\t\ttotalCacheRead,\n\t\t\ttotalCacheWrite,\n\t\t\ttotalCost,\n\t\t\ttotalSpawnedCost,\n\t\t\tdailyTotalCost,\n\t\t\t// Calculate context usage from session (handles compaction correctly).\n\t\t\t// After compaction, tokens are unknown until the next LLM response.\n\t\t\tcontextUsage: this.session.getContextUsage(),\n\t\t};\n\t\tthis.usageSnapshot = snapshot;\n\t\treturn snapshot;\n\t}\n\n\trender(width: number): string[] {\n\t\tconst state = this.session.state;\n\t\tconst usageSnapshot = this.getUsageSnapshot(state.messages?.length ?? 0);\n\t\tconst {\n\t\t\ttotalInput,\n\t\t\ttotalOutput,\n\t\t\ttotalCacheRead,\n\t\t\ttotalCacheWrite,\n\t\t\ttotalCost,\n\t\t\ttotalSpawnedCost,\n\t\t\tdailyTotalCost,\n\t\t\tcontextUsage,\n\t\t} = usageSnapshot;\n\t\tconst contextWindow = contextUsage?.contextWindow ?? state.model?.contextWindow ?? 0;\n\t\tconst contextPercentValue = contextUsage?.percent ?? 0;\n\t\tconst contextPercent = contextUsage?.percent !== null ? contextPercentValue.toFixed(1) : \"?\";\n\n\t\t// Replace home directory with ~\n\t\tlet pwd = formatCwdForFooter(this.session.sessionManager.getCwd(), process.env.HOME || process.env.USERPROFILE);\n\n\t\t// Add git branch if available\n\t\tconst branch = this.footerData.getGitBranch();\n\t\tif (branch) {\n\t\t\tpwd = `${pwd} (${branch})`;\n\t\t}\n\n\t\t// Add session name if set\n\t\tconst sessionName = this.session.sessionManager.getSessionName();\n\t\tif (sessionName) {\n\t\t\tpwd = `${pwd} • ${sessionName}`;\n\t\t}\n\n\t\t// Build stats line\n\t\tconst statsParts = [];\n\t\tif (totalInput) statsParts.push(`↑${formatTokens(totalInput)}`);\n\t\tif (totalOutput) statsParts.push(`↓${formatTokens(totalOutput)}`);\n\t\tif (totalCacheRead) statsParts.push(`R${formatTokens(totalCacheRead)}`);\n\t\tif (totalCacheWrite) statsParts.push(`W${formatTokens(totalCacheWrite)}`);\n\n\t\t// Show cost with \"(sub)\" indicator if using OAuth subscription\n\t\tconst usingSubscription = state.model ? this.session.modelRegistry.isUsingOAuth(state.model) : false;\n\t\tconst grandTotalCost = totalCost + totalSpawnedCost;\n\t\tif (grandTotalCost || usingSubscription) {\n\t\t\tconst costStr = `$${grandTotalCost.toFixed(3)}${usingSubscription ? \" (sub)\" : \"\"}`;\n\t\t\tstatsParts.push(costStr);\n\t\t}\n\t\tif (dailyTotalCost) {\n\t\t\tstatsParts.push(`day:$${dailyTotalCost.toFixed(3)}`);\n\t\t}\n\n\t\t// Colorize context percentage based on usage\n\t\tlet contextPercentStr: string;\n\t\tconst autoIndicator = this.autoCompactEnabled ? \" (auto)\" : \"\";\n\t\tconst contextPercentDisplay =\n\t\t\tcontextPercent === \"?\"\n\t\t\t\t? `?/${formatTokens(contextWindow)}${autoIndicator}`\n\t\t\t\t: `${contextPercent}%/${formatTokens(contextWindow)}${autoIndicator}`;\n\t\tif (contextPercentValue > 90) {\n\t\t\tcontextPercentStr = theme.fg(\"error\", contextPercentDisplay);\n\t\t} else if (contextPercentValue > 70) {\n\t\t\tcontextPercentStr = theme.fg(\"warning\", contextPercentDisplay);\n\t\t} else {\n\t\t\tcontextPercentStr = contextPercentDisplay;\n\t\t}\n\t\tstatsParts.push(contextPercentStr);\n\n\t\tlet statsLeft = statsParts.join(\" \");\n\n\t\t// Add model display name on the right side, plus thinking level if model supports it\n\t\tconst modelName = state.model?.name || state.model?.id || \"no-model\";\n\n\t\tlet statsLeftWidth = visibleWidth(statsLeft);\n\n\t\t// If statsLeft is too wide, truncate it\n\t\tif (statsLeftWidth > width) {\n\t\t\tstatsLeft = truncateToWidth(statsLeft, width, \"...\");\n\t\t\tstatsLeftWidth = visibleWidth(statsLeft);\n\t\t}\n\n\t\t// Calculate available space for padding (minimum 2 spaces between stats and model)\n\t\tconst minPadding = 2;\n\n\t\t// Add thinking level indicator if model supports reasoning\n\t\tlet rightSideWithoutProvider = modelName;\n\t\tif (state.model?.reasoning) {\n\t\t\tconst thinkingLevel = state.thinkingLevel || \"off\";\n\t\t\trightSideWithoutProvider =\n\t\t\t\tthinkingLevel === \"off\" ? `${modelName} • thinking off` : `${modelName} • ${thinkingLevel}`;\n\t\t}\n\n\t\t// Prepend the provider in parentheses if there are multiple providers and there's enough room\n\t\tlet rightSide = rightSideWithoutProvider;\n\t\tif (this.footerData.getAvailableProviderCount() > 1 && state.model) {\n\t\t\trightSide = `(${state.model!.provider}) ${rightSideWithoutProvider}`;\n\t\t\tif (statsLeftWidth + minPadding + visibleWidth(rightSide) > width) {\n\t\t\t\t// Too wide, fall back\n\t\t\t\trightSide = rightSideWithoutProvider;\n\t\t\t}\n\t\t}\n\n\t\tconst rightSideWidth = visibleWidth(rightSide);\n\t\tconst totalNeeded = statsLeftWidth + minPadding + rightSideWidth;\n\n\t\tlet statsLine: string;\n\t\tif (totalNeeded <= width) {\n\t\t\t// Both fit - add padding to right-align model\n\t\t\tconst padding = \" \".repeat(width - statsLeftWidth - rightSideWidth);\n\t\t\tstatsLine = statsLeft + padding + rightSide;\n\t\t} else {\n\t\t\t// Need to truncate right side\n\t\t\tconst availableForRight = width - statsLeftWidth - minPadding;\n\t\t\tif (availableForRight > 0) {\n\t\t\t\tconst truncatedRight = truncateToWidth(rightSide, availableForRight, \"\");\n\t\t\t\tconst truncatedRightWidth = visibleWidth(truncatedRight);\n\t\t\t\tconst padding = \" \".repeat(Math.max(0, width - statsLeftWidth - truncatedRightWidth));\n\t\t\t\tstatsLine = statsLeft + padding + truncatedRight;\n\t\t\t} else {\n\t\t\t\t// Not enough space for right side at all\n\t\t\t\tstatsLine = statsLeft;\n\t\t\t}\n\t\t}\n\n\t\t// Apply dim to each part separately. statsLeft may contain color codes (for context %)\n\t\t// that end with a reset, which would clear an outer dim wrapper. So we dim the parts\n\t\t// before and after the colored section independently.\n\t\tconst dimStatsLeft = theme.fg(\"dim\", statsLeft);\n\t\tconst remainder = statsLine.slice(statsLeft.length); // padding + rightSide\n\t\tconst dimRemainder = theme.fg(\"dim\", remainder);\n\n\t\tconst pwdLine = truncateToWidth(theme.fg(\"dim\", pwd), width, theme.fg(\"dim\", \"...\"));\n\t\tconst lines = [pwdLine, dimStatsLeft + dimRemainder];\n\n\t\t// Add extension statuses on a single line. Learning-related statuses are\n\t\t// folded into one compact chip so independent learning systems do not render\n\t\t// brittle duplicates like \"(learning) (learning) auto\".\n\t\tconst extensionStatuses = this.footerData.getExtensionStatuses();\n\t\tconst autonomyStatus = this.footerData.getAutonomyStatus();\n\n\t\tconst statusParts: string[] = [];\n\t\tif (autonomyStatus) {\n\t\t\tconst sanitizedAutonomyStatus = sanitizeStatusText(autonomyStatus);\n\t\t\tif (sanitizedAutonomyStatus) {\n\t\t\t\tstatusParts.push(sanitizedAutonomyStatus);\n\t\t\t}\n\t\t}\n\t\tif (extensionStatuses.size > 0) {\n\t\t\tconst extLine = formatExtensionStatuses(extensionStatuses).join(\" \");\n\t\t\tif (extLine) {\n\t\t\t\tstatusParts.push(extLine);\n\t\t\t}\n\t\t}\n\n\t\tif (statusParts.length > 0) {\n\t\t\tconst statusLine = statusParts.join(\" \");\n\t\t\tlines.push(truncateToWidth(statusLine, width, theme.fg(\"dim\", \"...\")));\n\t\t}\n\n\t\treturn lines;\n\t}\n}\n"]}
1
+ {"version":3,"file":"footer.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/footer.ts"],"names":[],"mappings":"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","sourcesContent":["import { isAbsolute, relative, resolve, sep } from \"node:path\";\nimport { type Component, truncateToWidth, visibleWidth } from \"@caupulican/pi-tui\";\nimport type { AgentSession } from \"../../../core/agent-session.ts\";\nimport { formatFooterCostParts } from \"../../../core/cost/cost-summary.ts\";\nimport type { ReadonlyFooterDataProvider } from \"../../../core/footer-data-provider.ts\";\nimport { theme } from \"../theme/theme.ts\";\n\n/**\n * Sanitize text for display in a single-line status.\n * Removes newlines, tabs, carriage returns, and other control characters.\n */\nfunction sanitizeStatusText(text: string): string {\n\t// Replace newlines, tabs, carriage returns with space, then collapse multiple spaces\n\treturn text\n\t\t.replace(/[\\r\\n\\t]/g, \" \")\n\t\t.replace(/ +/g, \" \")\n\t\t.trim();\n}\n\nfunction stripAnsi(text: string): string {\n\treturn text.replace(/\\u001b\\[[0-?]*[ -/]*[@-~]/g, \"\");\n}\n\nfunction normalizeLearningPhase(phase: string): string {\n\tconst normalized = phase\n\t\t.toLowerCase()\n\t\t.replace(/[^a-z0-9_-]+/g, \"\")\n\t\t.trim();\n\tif (!normalized) return \"active\";\n\tif (normalized === \"starting\") return \"start\";\n\tif (normalized === \"mapping\") return \"map\";\n\tif (normalized === \"scanning\") return \"scan\";\n\tif (normalized === \"auditing\") return \"audit\";\n\tif (normalized === \"learning\") return \"run\";\n\tif (normalized === \"pruning\") return \"prune\";\n\treturn normalized.slice(0, 16);\n}\n\nfunction formatExtensionStatuses(statuses: ReadonlyMap<string, string>): string[] {\n\tconst regularStatuses: string[] = [];\n\tconst learningPhases = new Set<string>();\n\tlet sawLearningStatus = false;\n\n\tfor (const [key, rawText] of Array.from(statuses.entries()).sort(([a], [b]) => a.localeCompare(b))) {\n\t\tconst text = sanitizeStatusText(rawText);\n\t\tconst plain = stripAnsi(text).trim();\n\t\tconst plainLower = plain.toLowerCase();\n\t\tlet phase: string | undefined;\n\n\t\tif (plainLower.startsWith(\"(learning)\")) {\n\t\t\tphase = plain.slice(\"(learning)\".length).trim();\n\t\t} else if (plainLower === \"learning\") {\n\t\t\tphase = \"active\";\n\t\t} else if (/^learn(?:ing)?\\s*[: ]/.test(plainLower)) {\n\t\t\tphase = plain.replace(/^learn(?:ing)?\\s*[: ]/i, \"\").trim();\n\t\t}\n\n\t\tif (phase !== undefined) {\n\t\t\tsawLearningStatus = true;\n\t\t\tlearningPhases.add(normalizeLearningPhase(phase));\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (key === \"auto-learn\" || key === \"continuous-learning\") {\n\t\t\tsawLearningStatus = true;\n\t\t\tlearningPhases.add(\"active\");\n\t\t\tcontinue;\n\t\t}\n\n\t\tregularStatuses.push(text);\n\t}\n\n\tif (!sawLearningStatus) return regularStatuses;\n\tconst phases = Array.from(learningPhases).filter((phase) => phase !== \"active\");\n\tconst phaseText = phases.length > 0 ? phases.join(\"/\") : \"active\";\n\treturn [theme.fg(\"warning\", \"learn\") + theme.fg(\"dim\", `:${phaseText}`), ...regularStatuses];\n}\n\n/**\n * Format token counts for compact footer display.\n */\nfunction formatTokens(count: number): string {\n\tif (count < 1000) return count.toString();\n\tif (count < 10000) return `${(count / 1000).toFixed(1)}k`;\n\tif (count < 1000000) return `${Math.round(count / 1000)}k`;\n\tif (count < 10000000) return `${(count / 1000000).toFixed(1)}M`;\n\treturn `${Math.round(count / 1000000)}M`;\n}\n\nexport function formatCwdForFooter(cwd: string, home: string | undefined): string {\n\tif (!home) return cwd;\n\n\tconst resolvedCwd = resolve(cwd);\n\tconst resolvedHome = resolve(home);\n\tconst relativeToHome = relative(resolvedHome, resolvedCwd);\n\tconst isInsideHome =\n\t\trelativeToHome === \"\" ||\n\t\t(relativeToHome !== \"..\" && !relativeToHome.startsWith(`..${sep}`) && !isAbsolute(relativeToHome));\n\n\tif (!isInsideHome) return cwd;\n\treturn relativeToHome === \"\" ? \"~\" : `~${sep}${relativeToHome}`;\n}\n\n/**\n * Footer component that shows pwd, token stats, and context usage.\n * Computes token/context stats from session, gets git branch and extension statuses from provider.\n */\ntype FooterUsageSnapshot = {\n\tentryCount: number;\n\tmessageCount: number;\n\ttotalInput: number;\n\ttotalOutput: number;\n\ttotalCacheRead: number;\n\ttotalCacheWrite: number;\n\tcontextUsage: ReturnType<AgentSession[\"getContextUsage\"]>;\n};\n\nexport class FooterComponent implements Component {\n\tprivate autoCompactEnabled = true;\n\tprivate session: AgentSession;\n\tprivate footerData: ReadonlyFooterDataProvider;\n\tprivate usageSnapshot?: FooterUsageSnapshot;\n\n\tconstructor(session: AgentSession, footerData: ReadonlyFooterDataProvider) {\n\t\tthis.session = session;\n\t\tthis.footerData = footerData;\n\t}\n\n\tsetSession(session: AgentSession): void {\n\t\tthis.session = session;\n\t\tthis.usageSnapshot = undefined;\n\t}\n\n\tsetAutoCompactEnabled(enabled: boolean): void {\n\t\tthis.autoCompactEnabled = enabled;\n\t}\n\n\t/**\n\t * Invalidate cached footer stats when session state changes.\n\t */\n\tinvalidate(): void {\n\t\tthis.usageSnapshot = undefined;\n\t}\n\n\t/**\n\t * Clean up resources.\n\t * Git watcher cleanup now handled by provider.\n\t */\n\tdispose(): void {\n\t\t// Git watcher cleanup handled by provider\n\t}\n\n\tprivate getUsageSnapshot(messageCount: number): FooterUsageSnapshot {\n\t\tconst sessionManager = this.session.sessionManager as AgentSession[\"sessionManager\"] & {\n\t\t\tgetEntryCount?: () => number;\n\t\t};\n\t\tconst entryCount = sessionManager.getEntryCount?.() ?? sessionManager.getEntries().length;\n\t\tconst cached = this.usageSnapshot;\n\t\tif (cached && cached.entryCount === entryCount && cached.messageCount === messageCount) {\n\t\t\treturn cached;\n\t\t}\n\n\t\t// Calculate cumulative usage from ALL session entries in one batched pass.\n\t\t// This avoids per-frame defensive array allocation when only the TUI redraws.\n\t\tlet totalInput = 0;\n\t\tlet totalOutput = 0;\n\t\tlet totalCacheRead = 0;\n\t\tlet totalCacheWrite = 0;\n\n\t\tconst entries = this.session.sessionManager.getEntries();\n\t\tfor (let i = 0; i < entries.length; i++) {\n\t\t\tconst entry = entries[i];\n\t\t\tif (entry.type !== \"message\" || entry.message.role !== \"assistant\") continue;\n\t\t\tconst usage = entry.message.usage;\n\t\t\tif (!usage) continue;\n\t\t\ttotalInput += usage.input;\n\t\t\ttotalOutput += usage.output;\n\t\t\ttotalCacheRead += usage.cacheRead;\n\t\t\ttotalCacheWrite += usage.cacheWrite;\n\t\t}\n\n\t\tconst snapshot: FooterUsageSnapshot = {\n\t\t\tentryCount,\n\t\t\tmessageCount,\n\t\t\ttotalInput,\n\t\t\ttotalOutput,\n\t\t\ttotalCacheRead,\n\t\t\ttotalCacheWrite,\n\t\t\t// Calculate context usage from session (handles compaction correctly).\n\t\t\t// After compaction, tokens are unknown until the next LLM response.\n\t\t\tcontextUsage: this.session.getContextUsage(),\n\t\t};\n\t\tthis.usageSnapshot = snapshot;\n\t\treturn snapshot;\n\t}\n\n\trender(width: number): string[] {\n\t\tconst state = this.session.state;\n\t\tconst usageSnapshot = this.getUsageSnapshot(state.messages?.length ?? 0);\n\t\tconst { totalInput, totalOutput, totalCacheRead, totalCacheWrite, contextUsage } = usageSnapshot;\n\t\tconst costSummary = this.session.getCostSummary();\n\t\tconst contextWindow = contextUsage?.contextWindow ?? state.model?.contextWindow ?? 0;\n\t\tconst contextPercentValue = contextUsage?.percent ?? 0;\n\t\tconst contextPercent = contextUsage?.percent !== null ? contextPercentValue.toFixed(1) : \"?\";\n\n\t\t// Replace home directory with ~\n\t\tlet pwd = formatCwdForFooter(this.session.sessionManager.getCwd(), process.env.HOME || process.env.USERPROFILE);\n\n\t\t// Add git branch if available\n\t\tconst branch = this.footerData.getGitBranch();\n\t\tif (branch) {\n\t\t\tpwd = `${pwd} (${branch})`;\n\t\t}\n\n\t\t// Add session name if set\n\t\tconst sessionName = this.session.sessionManager.getSessionName();\n\t\tif (sessionName) {\n\t\t\tpwd = `${pwd} • ${sessionName}`;\n\t\t}\n\n\t\t// Build stats line\n\t\tconst statsParts = [];\n\t\tif (totalInput) statsParts.push(`↑${formatTokens(totalInput)}`);\n\t\tif (totalOutput) statsParts.push(`↓${formatTokens(totalOutput)}`);\n\t\tif (totalCacheRead) statsParts.push(`R${formatTokens(totalCacheRead)}`);\n\t\tif (totalCacheWrite) statsParts.push(`W${formatTokens(totalCacheWrite)}`);\n\n\t\tstatsParts.push(...formatFooterCostParts(costSummary));\n\n\t\t// Colorize context percentage based on usage\n\t\tlet contextPercentStr: string;\n\t\tconst autoIndicator = this.autoCompactEnabled ? \" (auto)\" : \"\";\n\t\tconst contextPercentDisplay =\n\t\t\tcontextPercent === \"?\"\n\t\t\t\t? `?/${formatTokens(contextWindow)}${autoIndicator}`\n\t\t\t\t: `${contextPercent}%/${formatTokens(contextWindow)}${autoIndicator}`;\n\t\tif (contextPercentValue > 90) {\n\t\t\tcontextPercentStr = theme.fg(\"error\", contextPercentDisplay);\n\t\t} else if (contextPercentValue > 70) {\n\t\t\tcontextPercentStr = theme.fg(\"warning\", contextPercentDisplay);\n\t\t} else {\n\t\t\tcontextPercentStr = contextPercentDisplay;\n\t\t}\n\t\tstatsParts.push(contextPercentStr);\n\n\t\tlet statsLeft = statsParts.join(\" \");\n\n\t\t// Add model display name on the right side, plus thinking level if model supports it\n\t\tconst modelName = state.model?.name || state.model?.id || \"no-model\";\n\n\t\tlet statsLeftWidth = visibleWidth(statsLeft);\n\n\t\t// If statsLeft is too wide, truncate it\n\t\tif (statsLeftWidth > width) {\n\t\t\tstatsLeft = truncateToWidth(statsLeft, width, \"...\");\n\t\t\tstatsLeftWidth = visibleWidth(statsLeft);\n\t\t}\n\n\t\t// Calculate available space for padding (minimum 2 spaces between stats and model)\n\t\tconst minPadding = 2;\n\n\t\t// Add thinking level indicator if model supports reasoning\n\t\tlet rightSideWithoutProvider = modelName;\n\t\tif (state.model?.reasoning) {\n\t\t\tconst thinkingLevel = state.thinkingLevel || \"off\";\n\t\t\trightSideWithoutProvider =\n\t\t\t\tthinkingLevel === \"off\" ? `${modelName} • thinking off` : `${modelName} • ${thinkingLevel}`;\n\t\t}\n\n\t\t// Prepend the provider in parentheses if there are multiple providers and there's enough room\n\t\tlet rightSide = rightSideWithoutProvider;\n\t\tif (this.footerData.getAvailableProviderCount() > 1 && state.model) {\n\t\t\trightSide = `(${state.model!.provider}) ${rightSideWithoutProvider}`;\n\t\t\tif (statsLeftWidth + minPadding + visibleWidth(rightSide) > width) {\n\t\t\t\t// Too wide, fall back\n\t\t\t\trightSide = rightSideWithoutProvider;\n\t\t\t}\n\t\t}\n\n\t\tconst rightSideWidth = visibleWidth(rightSide);\n\t\tconst totalNeeded = statsLeftWidth + minPadding + rightSideWidth;\n\n\t\tlet statsLine: string;\n\t\tif (totalNeeded <= width) {\n\t\t\t// Both fit - add padding to right-align model\n\t\t\tconst padding = \" \".repeat(width - statsLeftWidth - rightSideWidth);\n\t\t\tstatsLine = statsLeft + padding + rightSide;\n\t\t} else {\n\t\t\t// Need to truncate right side\n\t\t\tconst availableForRight = width - statsLeftWidth - minPadding;\n\t\t\tif (availableForRight > 0) {\n\t\t\t\tconst truncatedRight = truncateToWidth(rightSide, availableForRight, \"\");\n\t\t\t\tconst truncatedRightWidth = visibleWidth(truncatedRight);\n\t\t\t\tconst padding = \" \".repeat(Math.max(0, width - statsLeftWidth - truncatedRightWidth));\n\t\t\t\tstatsLine = statsLeft + padding + truncatedRight;\n\t\t\t} else {\n\t\t\t\t// Not enough space for right side at all\n\t\t\t\tstatsLine = statsLeft;\n\t\t\t}\n\t\t}\n\n\t\t// Apply dim to each part separately. statsLeft may contain color codes (for context %)\n\t\t// that end with a reset, which would clear an outer dim wrapper. So we dim the parts\n\t\t// before and after the colored section independently.\n\t\tconst dimStatsLeft = theme.fg(\"dim\", statsLeft);\n\t\tconst remainder = statsLine.slice(statsLeft.length); // padding + rightSide\n\t\tconst dimRemainder = theme.fg(\"dim\", remainder);\n\n\t\tconst pwdLine = truncateToWidth(theme.fg(\"dim\", pwd), width, theme.fg(\"dim\", \"...\"));\n\t\tconst lines = [pwdLine, dimStatsLeft + dimRemainder];\n\n\t\t// Add extension statuses on a single line. Learning-related statuses are\n\t\t// folded into one compact chip so independent learning systems do not render\n\t\t// brittle duplicates like \"(learning) (learning) auto\".\n\t\tconst extensionStatuses = this.footerData.getExtensionStatuses();\n\t\tconst autonomyStatus = this.footerData.getAutonomyStatus();\n\n\t\tconst statusParts: string[] = [];\n\t\tif (autonomyStatus) {\n\t\t\tconst sanitizedAutonomyStatus = sanitizeStatusText(autonomyStatus);\n\t\t\tif (sanitizedAutonomyStatus) {\n\t\t\t\tstatusParts.push(sanitizedAutonomyStatus);\n\t\t\t}\n\t\t}\n\t\tif (extensionStatuses.size > 0) {\n\t\t\tconst extLine = formatExtensionStatuses(extensionStatuses).join(\" \");\n\t\t\tif (extLine) {\n\t\t\t\tstatusParts.push(extLine);\n\t\t\t}\n\t\t}\n\n\t\tif (statusParts.length > 0) {\n\t\t\tconst statusLine = statusParts.join(\" \");\n\t\t\tlines.push(truncateToWidth(statusLine, width, theme.fg(\"dim\", \"...\")));\n\t\t}\n\n\t\treturn lines;\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"report-commands.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/report-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAGpF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACnF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAUxE,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC;IAClC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC;CACjB;AAED,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACxD,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,2BAA2B,IAAI,QAAQ,CAAC,iBAAiB,CAAC,CAAC;CAC3D;AAED,MAAM,WAAW,mBAAoB,SAAQ,gBAAgB;IAC5D,4BAA4B,IAAI,aAAa,CAAC;CAC9C;AAED,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IAC1D,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,kBAAkB,CAAC;IACzC,4BAA4B,IAAI,aAAa,CAAC;IAC9C,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAAC;IAChD,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC;CAChD;AAED,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACxD,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;CAC/B;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAkE9D;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAmBtE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAiHlE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CA+B9D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAI9D;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAIjE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAI1D;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAI3G","sourcesContent":["/**\n * Read-only report and easter-egg commands extracted from interactive-mode.\n *\n * These build informational output (usage/cost summary, changelog, hotkeys\n * table, render debug dump) or render an easter-egg component, appending to the\n * chat container and requesting a render. None mutate agent/session state, so\n * they operate through narrow `host` seams (chat container, TUI, and a few\n * read accessors) while interactive-mode keeps thin delegating wrappers.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { Container, Keybinding, MarkdownTheme, TUI } from \"@caupulican/pi-tui\";\nimport { Markdown, Spacer, Text, visibleWidth } from \"@caupulican/pi-tui\";\nimport { getDebugLogPath } from \"../../config.ts\";\nimport type { AgentSession } from \"../../core/agent-session.ts\";\nimport type { AppKeybinding, KeybindingsManager } from \"../../core/keybindings.ts\";\nimport type { AutoLearnSettings } from \"../../core/settings-manager.ts\";\nimport { getChangelogPath, parseChangelog } from \"../../utils/changelog.ts\";\nimport { getProcessMemoryMb } from \"../../utils/process-memory.ts\";\nimport { ArminComponent } from \"./components/armin.ts\";\nimport { DaxnutsComponent } from \"./components/daxnuts.ts\";\nimport { DynamicBorder } from \"./components/dynamic-border.ts\";\nimport { EarendilAnnouncementComponent } from \"./components/earendil-announcement.ts\";\nimport { formatKeyText } from \"./components/keybinding-hints.ts\";\nimport { theme } from \"./theme/theme.ts\";\n\nexport interface ReportRenderHost {\n\treadonly chatContainer: Container;\n\treadonly ui: TUI;\n}\n\nexport interface UsageReportHost extends ReportRenderHost {\n\treadonly session: AgentSession;\n\tgetCurrentAutoLearnSettings(): Required<AutoLearnSettings>;\n}\n\nexport interface ChangelogReportHost extends ReportRenderHost {\n\tgetMarkdownThemeWithSettings(): MarkdownTheme;\n}\n\nexport interface HotkeysReportHost extends ReportRenderHost {\n\treadonly session: AgentSession;\n\treadonly keybindings: KeybindingsManager;\n\tgetMarkdownThemeWithSettings(): MarkdownTheme;\n\tgetAppKeyDisplay(action: AppKeybinding): string;\n\tgetEditorKeyDisplay(action: Keybinding): string;\n}\n\nexport interface DebugReportHost extends ReportRenderHost {\n\treadonly session: AgentSession;\n}\n\nexport function handleUsageCommand(host: UsageReportHost): void {\n\tconst stats = host.session.getSessionStats();\n\tconst spawned = host.session.getSpawnedUsage();\n\tconst daily = host.session.getDailyUsageTotals();\n\tconst context = host.session.getContextUsage();\n\tconst autoLearn = host.getCurrentAutoLearnSettings();\n\tconst costGuard = host.session.getLastCostGuardDecision();\n\n\tlet info = `${theme.bold(\"Usage & Optimization\")}\\n\\n`;\n\tinfo += `${theme.bold(\"Session tokens\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Input:\")} ${stats.tokens.input.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Output:\")} ${stats.tokens.output.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Cache read:\")} ${stats.tokens.cacheRead.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Cache write:\")} ${stats.tokens.cacheWrite.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Total:\")} ${stats.tokens.total.toLocaleString()}\\n\\n`;\n\n\tinfo += `${theme.bold(\"Cost\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Session:\")} $${stats.cost.toFixed(4)}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Spawned/background:\")} $${spawned.cost.toFixed(4)} (${spawned.reports} reports)\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Today:\")} $${daily.totalCost.toFixed(4)}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Today own:\")} $${daily.ownCost.toFixed(4)}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Today spawned/background:\")} $${daily.spawnedCost.toFixed(4)}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Today tokens:\")} ${daily.totalTokens.toLocaleString()}\\n\\n`;\n\n\tconst processMemory = getProcessMemoryMb();\n\tinfo += `${theme.bold(\"Process\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Memory:\")} rss ${processMemory.rssMb}MB, heap ${processMemory.heapUsedMb}MB, external ${processMemory.externalMb}MB\\n\\n`;\n\n\tinfo += `${theme.bold(\"Optimization state\")}\\n`;\n\tconst contextPercent = context?.percent;\n\tconst contextTokens = context?.tokens;\n\tif (\n\t\tcontext &&\n\t\tcontextPercent !== undefined &&\n\t\tcontextPercent !== null &&\n\t\tcontextTokens !== undefined &&\n\t\tcontextTokens !== null\n\t) {\n\t\tinfo += `${theme.fg(\"dim\", \"Context:\")} ${contextPercent.toFixed(1)}% (${contextTokens.toLocaleString()}/${context.contextWindow.toLocaleString()})\\n`;\n\t} else {\n\t\tinfo += `${theme.fg(\"dim\", \"Context:\")} unknown until next provider usage sample\\n`;\n\t}\n\tinfo += `${theme.fg(\"dim\", \"Auto-compaction:\")} ${host.session.autoCompactionEnabled ? \"enabled\" : \"disabled\"}\\n`;\n\tif (costGuard) {\n\t\tconst status = costGuard.over ? \"over\" : \"ok\";\n\t\tinfo += `${theme.fg(\"dim\", \"Cost guard:\")} ${status} $${costGuard.estUsd.toFixed(4)}/$${costGuard.thresholdUsd.toFixed(4)} (${costGuard.action})\\n`;\n\t} else {\n\t\tinfo += `${theme.fg(\"dim\", \"Cost guard:\")} disabled\\n`;\n\t}\n\tinfo += `${theme.fg(\"dim\", \"Auto Learn:\")} ${autoLearn.enabled ? \"enabled\" : \"disabled\"}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Scavenger model:\")} ${autoLearn.model || \"active\"}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Reflection review:\")} ${autoLearn.reflectionReview ? \"enabled\" : \"disabled\"} (${autoLearn.reflectionMinToolCalls} tool-call trigger)\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Auto Learn concurrency:\")} ${autoLearn.maxConcurrentLearners} learner(s), ${autoLearn.cooldownMinutes}m cooldown\\n\\n`;\n\n\tinfo += `${theme.bold(\"Model Router\")}\\n`;\n\tinfo += `${host.session.getModelRouterStatus((label) => theme.fg(\"dim\", label))}\\n\\n`;\n\n\tinfo += `${theme.bold(\"Manual controls\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"/compact\")}: compact the active context now\\n`;\n\tinfo += `${theme.fg(\"dim\", \"/settings\")}: adjust Auto Learn, cost guard, compaction, and model-router config\\n`;\n\tinfo += `${theme.fg(\"dim\", \"/auto-learn status|run\")}: inspect or launch background learning\\n`;\n\tinfo += `${theme.fg(\"dim\", \"context_audit\")}: ask the agent to inspect provider-visible context contributors\\n`;\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new Text(info, 1, 0));\n\thost.ui.requestRender();\n}\n\nexport function handleChangelogCommand(host: ChangelogReportHost): void {\n\tconst changelogPath = getChangelogPath();\n\tconst allEntries = parseChangelog(changelogPath);\n\n\tconst changelogMarkdown =\n\t\tallEntries.length > 0\n\t\t\t? allEntries\n\t\t\t\t\t.reverse()\n\t\t\t\t\t.map((e) => e.content)\n\t\t\t\t\t.join(\"\\n\\n\")\n\t\t\t: \"No changelog entries found.\";\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new DynamicBorder());\n\thost.chatContainer.addChild(new Text(theme.bold(theme.fg(\"accent\", \"What's New\")), 1, 0));\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new Markdown(changelogMarkdown, 1, 1, host.getMarkdownThemeWithSettings()));\n\thost.chatContainer.addChild(new DynamicBorder());\n\thost.ui.requestRender();\n}\n\nexport function handleHotkeysCommand(host: HotkeysReportHost): void {\n\t// Navigation keybindings\n\tconst cursorUp = host.getEditorKeyDisplay(\"tui.editor.cursorUp\");\n\tconst cursorDown = host.getEditorKeyDisplay(\"tui.editor.cursorDown\");\n\tconst cursorLeft = host.getEditorKeyDisplay(\"tui.editor.cursorLeft\");\n\tconst cursorRight = host.getEditorKeyDisplay(\"tui.editor.cursorRight\");\n\tconst cursorWordLeft = host.getEditorKeyDisplay(\"tui.editor.cursorWordLeft\");\n\tconst cursorWordRight = host.getEditorKeyDisplay(\"tui.editor.cursorWordRight\");\n\tconst cursorLineStart = host.getEditorKeyDisplay(\"tui.editor.cursorLineStart\");\n\tconst cursorLineEnd = host.getEditorKeyDisplay(\"tui.editor.cursorLineEnd\");\n\tconst jumpForward = host.getEditorKeyDisplay(\"tui.editor.jumpForward\");\n\tconst jumpBackward = host.getEditorKeyDisplay(\"tui.editor.jumpBackward\");\n\tconst pageUp = host.getEditorKeyDisplay(\"tui.editor.pageUp\");\n\tconst pageDown = host.getEditorKeyDisplay(\"tui.editor.pageDown\");\n\n\t// Editing keybindings\n\tconst submit = host.getEditorKeyDisplay(\"tui.input.submit\");\n\tconst newLine = host.getEditorKeyDisplay(\"tui.input.newLine\");\n\tconst deleteWordBackward = host.getEditorKeyDisplay(\"tui.editor.deleteWordBackward\");\n\tconst deleteWordForward = host.getEditorKeyDisplay(\"tui.editor.deleteWordForward\");\n\tconst deleteToLineStart = host.getEditorKeyDisplay(\"tui.editor.deleteToLineStart\");\n\tconst deleteToLineEnd = host.getEditorKeyDisplay(\"tui.editor.deleteToLineEnd\");\n\tconst yank = host.getEditorKeyDisplay(\"tui.editor.yank\");\n\tconst yankPop = host.getEditorKeyDisplay(\"tui.editor.yankPop\");\n\tconst undo = host.getEditorKeyDisplay(\"tui.editor.undo\");\n\tconst tab = host.getEditorKeyDisplay(\"tui.input.tab\");\n\n\t// App keybindings\n\tconst interrupt = host.getAppKeyDisplay(\"app.interrupt\");\n\tconst clear = host.getAppKeyDisplay(\"app.clear\");\n\tconst exit = host.getAppKeyDisplay(\"app.exit\");\n\tconst suspend = host.getAppKeyDisplay(\"app.suspend\");\n\tconst cycleThinkingLevel = host.getAppKeyDisplay(\"app.thinking.cycle\");\n\tconst cycleModelForward = host.getAppKeyDisplay(\"app.model.cycleForward\");\n\tconst selectModel = host.getAppKeyDisplay(\"app.model.select\");\n\tconst expandTools = host.getAppKeyDisplay(\"app.tools.expand\");\n\tconst toggleThinking = host.getAppKeyDisplay(\"app.thinking.toggle\");\n\tconst externalEditor = host.getAppKeyDisplay(\"app.editor.external\");\n\tconst cycleModelBackward = host.getAppKeyDisplay(\"app.model.cycleBackward\");\n\tconst followUp = host.getAppKeyDisplay(\"app.message.followUp\");\n\tconst dequeue = host.getAppKeyDisplay(\"app.message.dequeue\");\n\tconst pasteImage = host.getAppKeyDisplay(\"app.clipboard.pasteImage\");\n\n\tlet hotkeys = `\n**Navigation**\n| Key | Action |\n|-----|--------|\n| \\`${cursorUp}\\` / \\`${cursorDown}\\` / \\`${cursorLeft}\\` / \\`${cursorRight}\\` | Move cursor / browse history (Up when empty) |\n| \\`${cursorWordLeft}\\` / \\`${cursorWordRight}\\` | Move by word |\n| \\`${cursorLineStart}\\` | Start of line |\n| \\`${cursorLineEnd}\\` | End of line |\n| \\`${jumpForward}\\` | Jump forward to character |\n| \\`${jumpBackward}\\` | Jump backward to character |\n| \\`${pageUp}\\` / \\`${pageDown}\\` | Scroll by page |\n\n**Editing**\n| Key | Action |\n|-----|--------|\n| \\`${submit}\\` | Send message |\n| \\`${newLine}\\` | New line${process.platform === \"win32\" ? \" (Ctrl+Enter on Windows Terminal)\" : \"\"} |\n| \\`${deleteWordBackward}\\` | Delete word backwards |\n| \\`${deleteWordForward}\\` | Delete word forwards |\n| \\`${deleteToLineStart}\\` | Delete to start of line |\n| \\`${deleteToLineEnd}\\` | Delete to end of line |\n| \\`${yank}\\` | Paste the most-recently-deleted text |\n| \\`${yankPop}\\` | Cycle through the deleted text after pasting |\n| \\`${undo}\\` | Undo |\n\n**Other**\n| Key | Action |\n|-----|--------|\n| \\`${tab}\\` | Path completion / accept autocomplete |\n| \\`${interrupt}\\` | Cancel autocomplete / abort streaming |\n| \\`${clear}\\` | Clear editor (first) / exit (second) |\n| \\`${exit}\\` | Exit (when editor is empty) |\n| \\`${suspend}\\` | Suspend to background |\n| \\`${cycleThinkingLevel}\\` | Cycle thinking level |\n| \\`${cycleModelForward}\\` / \\`${cycleModelBackward}\\` | Cycle models |\n| \\`${selectModel}\\` | Open model selector |\n| \\`${expandTools}\\` | Toggle tool output expansion |\n| \\`${toggleThinking}\\` | Toggle thinking block visibility |\n| \\`${externalEditor}\\` | Edit message in external editor |\n| \\`${followUp}\\` | Queue follow-up message |\n| \\`${dequeue}\\` | Restore queued messages |\n| \\`${pasteImage}\\` | Paste image from clipboard |\n| \\`/\\` | Slash commands |\n| \\`!\\` | Run bash command |\n| \\`!!\\` | Run bash command (excluded from context) |\n`;\n\n\t// Add extension-registered shortcuts\n\tconst extensionRunner = host.session.extensionRunner;\n\tconst shortcuts = extensionRunner.getShortcuts(host.keybindings.getEffectiveConfig());\n\tif (shortcuts.size > 0) {\n\t\thotkeys += `\n**Extensions**\n| Key | Action |\n|-----|--------|\n`;\n\t\tfor (const [key, shortcut] of shortcuts) {\n\t\t\tconst description = shortcut.description ?? shortcut.extensionPath;\n\t\t\tconst keyDisplay = formatKeyText(key, { capitalize: true });\n\t\t\thotkeys += `| \\`${keyDisplay}\\` | ${description} |\\n`;\n\t\t}\n\t}\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new DynamicBorder());\n\thost.chatContainer.addChild(new Text(theme.bold(theme.fg(\"accent\", \"Keyboard Shortcuts\")), 1, 0));\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new Markdown(hotkeys.trim(), 1, 1, host.getMarkdownThemeWithSettings()));\n\thost.chatContainer.addChild(new DynamicBorder());\n\thost.ui.requestRender();\n}\n\nexport function handleDebugCommand(host: DebugReportHost): void {\n\tconst width = host.ui.terminal.columns;\n\tconst height = host.ui.terminal.rows;\n\tconst allLines = host.ui.render(width);\n\n\tconst debugLogPath = getDebugLogPath();\n\tconst debugData = [\n\t\t`Debug output at ${new Date().toISOString()}`,\n\t\t`Terminal: ${width}x${height}`,\n\t\t`Total lines: ${allLines.length}`,\n\t\t\"\",\n\t\t\"=== All rendered lines with visible widths ===\",\n\t\t...allLines.map((line, idx) => {\n\t\t\tconst vw = visibleWidth(line);\n\t\t\tconst escaped = JSON.stringify(line);\n\t\t\treturn `[${idx}] (w=${vw}) ${escaped}`;\n\t\t}),\n\t\t\"\",\n\t\t\"=== Agent messages (JSONL) ===\",\n\t\t...host.session.messages.map((msg) => JSON.stringify(msg)),\n\t\t\"\",\n\t].join(\"\\n\");\n\n\tfs.mkdirSync(path.dirname(debugLogPath), { recursive: true });\n\tfs.writeFileSync(debugLogPath, debugData);\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(\n\t\tnew Text(`${theme.fg(\"accent\", \"✓ Debug log written\")}\\n${theme.fg(\"muted\", debugLogPath)}`, 1, 1),\n\t);\n\thost.ui.requestRender();\n}\n\nexport function handleArminSaysHi(host: ReportRenderHost): void {\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new ArminComponent(host.ui));\n\thost.ui.requestRender();\n}\n\nexport function handleDementedDelves(host: ReportRenderHost): void {\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new EarendilAnnouncementComponent());\n\thost.ui.requestRender();\n}\n\nexport function handleDaxnuts(host: ReportRenderHost): void {\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new DaxnutsComponent(host.ui));\n\thost.ui.requestRender();\n}\n\nexport function checkDaxnutsEasterEgg(host: ReportRenderHost, model: { provider: string; id: string }): void {\n\tif (model.provider === \"opencode\" && model.id.toLowerCase().includes(\"kimi-k2.5\")) {\n\t\thandleDaxnuts(host);\n\t}\n}\n"]}
1
+ {"version":3,"file":"report-commands.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/report-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAGpF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACnF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gCAAgC,CAAC;AAUxE,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC;IAClC,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC;CACjB;AAED,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACxD,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,2BAA2B,IAAI,QAAQ,CAAC,iBAAiB,CAAC,CAAC;CAC3D;AAED,MAAM,WAAW,mBAAoB,SAAQ,gBAAgB;IAC5D,4BAA4B,IAAI,aAAa,CAAC;CAC9C;AAED,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IAC1D,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,WAAW,EAAE,kBAAkB,CAAC;IACzC,4BAA4B,IAAI,aAAa,CAAC;IAC9C,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,MAAM,CAAC;IAChD,mBAAmB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC;CAChD;AAED,MAAM,WAAW,eAAgB,SAAQ,gBAAgB;IACxD,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;CAC/B;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAiE9D;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAmBtE;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAiHlE;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CA+B9D;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAI9D;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAIjE;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,gBAAgB,GAAG,IAAI,CAI1D;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,gBAAgB,EAAE,KAAK,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAI3G","sourcesContent":["/**\n * Read-only report and easter-egg commands extracted from interactive-mode.\n *\n * These build informational output (usage/cost summary, changelog, hotkeys\n * table, render debug dump) or render an easter-egg component, appending to the\n * chat container and requesting a render. None mutate agent/session state, so\n * they operate through narrow `host` seams (chat container, TUI, and a few\n * read accessors) while interactive-mode keeps thin delegating wrappers.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { Container, Keybinding, MarkdownTheme, TUI } from \"@caupulican/pi-tui\";\nimport { Markdown, Spacer, Text, visibleWidth } from \"@caupulican/pi-tui\";\nimport { getDebugLogPath } from \"../../config.ts\";\nimport type { AgentSession } from \"../../core/agent-session.ts\";\nimport type { AppKeybinding, KeybindingsManager } from \"../../core/keybindings.ts\";\nimport type { AutoLearnSettings } from \"../../core/settings-manager.ts\";\nimport { getChangelogPath, parseChangelog } from \"../../utils/changelog.ts\";\nimport { getProcessMemoryMb } from \"../../utils/process-memory.ts\";\nimport { ArminComponent } from \"./components/armin.ts\";\nimport { DaxnutsComponent } from \"./components/daxnuts.ts\";\nimport { DynamicBorder } from \"./components/dynamic-border.ts\";\nimport { EarendilAnnouncementComponent } from \"./components/earendil-announcement.ts\";\nimport { formatKeyText } from \"./components/keybinding-hints.ts\";\nimport { theme } from \"./theme/theme.ts\";\n\nexport interface ReportRenderHost {\n\treadonly chatContainer: Container;\n\treadonly ui: TUI;\n}\n\nexport interface UsageReportHost extends ReportRenderHost {\n\treadonly session: AgentSession;\n\tgetCurrentAutoLearnSettings(): Required<AutoLearnSettings>;\n}\n\nexport interface ChangelogReportHost extends ReportRenderHost {\n\tgetMarkdownThemeWithSettings(): MarkdownTheme;\n}\n\nexport interface HotkeysReportHost extends ReportRenderHost {\n\treadonly session: AgentSession;\n\treadonly keybindings: KeybindingsManager;\n\tgetMarkdownThemeWithSettings(): MarkdownTheme;\n\tgetAppKeyDisplay(action: AppKeybinding): string;\n\tgetEditorKeyDisplay(action: Keybinding): string;\n}\n\nexport interface DebugReportHost extends ReportRenderHost {\n\treadonly session: AgentSession;\n}\n\nexport function handleUsageCommand(host: UsageReportHost): void {\n\tconst stats = host.session.getSessionStats();\n\tconst costs = host.session.getCostSummary();\n\tconst context = host.session.getContextUsage();\n\tconst autoLearn = host.getCurrentAutoLearnSettings();\n\tconst costGuard = host.session.getLastCostGuardDecision();\n\n\tlet info = `${theme.bold(\"Usage & Optimization\")}\\n\\n`;\n\tinfo += `${theme.bold(\"Session tokens\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Input:\")} ${stats.tokens.input.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Output:\")} ${stats.tokens.output.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Cache read:\")} ${stats.tokens.cacheRead.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Cache write:\")} ${stats.tokens.cacheWrite.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Total:\")} ${stats.tokens.total.toLocaleString()}\\n\\n`;\n\n\tinfo += `${theme.bold(\"Cost\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"CURRENT (session):\")} $${costs.currentCost.toFixed(4)}\\n`;\n\tif (costs.subagentReports > 0 || costs.subagentCost > 0) {\n\t\tinfo += `${theme.fg(\"dim\", \"SUBAGENTS (included in CURRENT):\")} $${costs.subagentCost.toFixed(4)} (${costs.subagentReports} reports)\\n`;\n\t}\n\tinfo += `${theme.fg(\"dim\", \"TODAY (host local day):\")} $${costs.todayCost.toFixed(4)}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Today rollover:\")} local midnight\\n\\n`;\n\n\tconst processMemory = getProcessMemoryMb();\n\tinfo += `${theme.bold(\"Process\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Memory:\")} rss ${processMemory.rssMb}MB, heap ${processMemory.heapUsedMb}MB, external ${processMemory.externalMb}MB\\n\\n`;\n\n\tinfo += `${theme.bold(\"Optimization state\")}\\n`;\n\tconst contextPercent = context?.percent;\n\tconst contextTokens = context?.tokens;\n\tif (\n\t\tcontext &&\n\t\tcontextPercent !== undefined &&\n\t\tcontextPercent !== null &&\n\t\tcontextTokens !== undefined &&\n\t\tcontextTokens !== null\n\t) {\n\t\tinfo += `${theme.fg(\"dim\", \"Context:\")} ${contextPercent.toFixed(1)}% (${contextTokens.toLocaleString()}/${context.contextWindow.toLocaleString()})\\n`;\n\t} else {\n\t\tinfo += `${theme.fg(\"dim\", \"Context:\")} unknown until next provider usage sample\\n`;\n\t}\n\tinfo += `${theme.fg(\"dim\", \"Auto-compaction:\")} ${host.session.autoCompactionEnabled ? \"enabled\" : \"disabled\"}\\n`;\n\tif (costGuard) {\n\t\tconst status = costGuard.over ? \"over\" : \"ok\";\n\t\tinfo += `${theme.fg(\"dim\", \"Cost guard:\")} ${status} $${costGuard.estUsd.toFixed(4)}/$${costGuard.thresholdUsd.toFixed(4)} (${costGuard.action})\\n`;\n\t} else {\n\t\tinfo += `${theme.fg(\"dim\", \"Cost guard:\")} disabled\\n`;\n\t}\n\tinfo += `${theme.fg(\"dim\", \"Auto Learn:\")} ${autoLearn.enabled ? \"enabled\" : \"disabled\"}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Scavenger model:\")} ${autoLearn.model || \"active\"}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Reflection review:\")} ${autoLearn.reflectionReview ? \"enabled\" : \"disabled\"} (${autoLearn.reflectionMinToolCalls} tool-call trigger)\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Auto Learn concurrency:\")} ${autoLearn.maxConcurrentLearners} learner(s), ${autoLearn.cooldownMinutes}m cooldown\\n\\n`;\n\n\tinfo += `${theme.bold(\"Model Router\")}\\n`;\n\tinfo += `${host.session.getModelRouterStatus((label) => theme.fg(\"dim\", label))}\\n\\n`;\n\n\tinfo += `${theme.bold(\"Manual controls\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"/compact\")}: compact the active context now\\n`;\n\tinfo += `${theme.fg(\"dim\", \"/settings\")}: adjust Auto Learn, cost guard, compaction, and model-router config\\n`;\n\tinfo += `${theme.fg(\"dim\", \"/auto-learn status|run\")}: inspect or launch background learning\\n`;\n\tinfo += `${theme.fg(\"dim\", \"context_audit\")}: ask the agent to inspect provider-visible context contributors\\n`;\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new Text(info, 1, 0));\n\thost.ui.requestRender();\n}\n\nexport function handleChangelogCommand(host: ChangelogReportHost): void {\n\tconst changelogPath = getChangelogPath();\n\tconst allEntries = parseChangelog(changelogPath);\n\n\tconst changelogMarkdown =\n\t\tallEntries.length > 0\n\t\t\t? allEntries\n\t\t\t\t\t.reverse()\n\t\t\t\t\t.map((e) => e.content)\n\t\t\t\t\t.join(\"\\n\\n\")\n\t\t\t: \"No changelog entries found.\";\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new DynamicBorder());\n\thost.chatContainer.addChild(new Text(theme.bold(theme.fg(\"accent\", \"What's New\")), 1, 0));\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new Markdown(changelogMarkdown, 1, 1, host.getMarkdownThemeWithSettings()));\n\thost.chatContainer.addChild(new DynamicBorder());\n\thost.ui.requestRender();\n}\n\nexport function handleHotkeysCommand(host: HotkeysReportHost): void {\n\t// Navigation keybindings\n\tconst cursorUp = host.getEditorKeyDisplay(\"tui.editor.cursorUp\");\n\tconst cursorDown = host.getEditorKeyDisplay(\"tui.editor.cursorDown\");\n\tconst cursorLeft = host.getEditorKeyDisplay(\"tui.editor.cursorLeft\");\n\tconst cursorRight = host.getEditorKeyDisplay(\"tui.editor.cursorRight\");\n\tconst cursorWordLeft = host.getEditorKeyDisplay(\"tui.editor.cursorWordLeft\");\n\tconst cursorWordRight = host.getEditorKeyDisplay(\"tui.editor.cursorWordRight\");\n\tconst cursorLineStart = host.getEditorKeyDisplay(\"tui.editor.cursorLineStart\");\n\tconst cursorLineEnd = host.getEditorKeyDisplay(\"tui.editor.cursorLineEnd\");\n\tconst jumpForward = host.getEditorKeyDisplay(\"tui.editor.jumpForward\");\n\tconst jumpBackward = host.getEditorKeyDisplay(\"tui.editor.jumpBackward\");\n\tconst pageUp = host.getEditorKeyDisplay(\"tui.editor.pageUp\");\n\tconst pageDown = host.getEditorKeyDisplay(\"tui.editor.pageDown\");\n\n\t// Editing keybindings\n\tconst submit = host.getEditorKeyDisplay(\"tui.input.submit\");\n\tconst newLine = host.getEditorKeyDisplay(\"tui.input.newLine\");\n\tconst deleteWordBackward = host.getEditorKeyDisplay(\"tui.editor.deleteWordBackward\");\n\tconst deleteWordForward = host.getEditorKeyDisplay(\"tui.editor.deleteWordForward\");\n\tconst deleteToLineStart = host.getEditorKeyDisplay(\"tui.editor.deleteToLineStart\");\n\tconst deleteToLineEnd = host.getEditorKeyDisplay(\"tui.editor.deleteToLineEnd\");\n\tconst yank = host.getEditorKeyDisplay(\"tui.editor.yank\");\n\tconst yankPop = host.getEditorKeyDisplay(\"tui.editor.yankPop\");\n\tconst undo = host.getEditorKeyDisplay(\"tui.editor.undo\");\n\tconst tab = host.getEditorKeyDisplay(\"tui.input.tab\");\n\n\t// App keybindings\n\tconst interrupt = host.getAppKeyDisplay(\"app.interrupt\");\n\tconst clear = host.getAppKeyDisplay(\"app.clear\");\n\tconst exit = host.getAppKeyDisplay(\"app.exit\");\n\tconst suspend = host.getAppKeyDisplay(\"app.suspend\");\n\tconst cycleThinkingLevel = host.getAppKeyDisplay(\"app.thinking.cycle\");\n\tconst cycleModelForward = host.getAppKeyDisplay(\"app.model.cycleForward\");\n\tconst selectModel = host.getAppKeyDisplay(\"app.model.select\");\n\tconst expandTools = host.getAppKeyDisplay(\"app.tools.expand\");\n\tconst toggleThinking = host.getAppKeyDisplay(\"app.thinking.toggle\");\n\tconst externalEditor = host.getAppKeyDisplay(\"app.editor.external\");\n\tconst cycleModelBackward = host.getAppKeyDisplay(\"app.model.cycleBackward\");\n\tconst followUp = host.getAppKeyDisplay(\"app.message.followUp\");\n\tconst dequeue = host.getAppKeyDisplay(\"app.message.dequeue\");\n\tconst pasteImage = host.getAppKeyDisplay(\"app.clipboard.pasteImage\");\n\n\tlet hotkeys = `\n**Navigation**\n| Key | Action |\n|-----|--------|\n| \\`${cursorUp}\\` / \\`${cursorDown}\\` / \\`${cursorLeft}\\` / \\`${cursorRight}\\` | Move cursor / browse history (Up when empty) |\n| \\`${cursorWordLeft}\\` / \\`${cursorWordRight}\\` | Move by word |\n| \\`${cursorLineStart}\\` | Start of line |\n| \\`${cursorLineEnd}\\` | End of line |\n| \\`${jumpForward}\\` | Jump forward to character |\n| \\`${jumpBackward}\\` | Jump backward to character |\n| \\`${pageUp}\\` / \\`${pageDown}\\` | Scroll by page |\n\n**Editing**\n| Key | Action |\n|-----|--------|\n| \\`${submit}\\` | Send message |\n| \\`${newLine}\\` | New line${process.platform === \"win32\" ? \" (Ctrl+Enter on Windows Terminal)\" : \"\"} |\n| \\`${deleteWordBackward}\\` | Delete word backwards |\n| \\`${deleteWordForward}\\` | Delete word forwards |\n| \\`${deleteToLineStart}\\` | Delete to start of line |\n| \\`${deleteToLineEnd}\\` | Delete to end of line |\n| \\`${yank}\\` | Paste the most-recently-deleted text |\n| \\`${yankPop}\\` | Cycle through the deleted text after pasting |\n| \\`${undo}\\` | Undo |\n\n**Other**\n| Key | Action |\n|-----|--------|\n| \\`${tab}\\` | Path completion / accept autocomplete |\n| \\`${interrupt}\\` | Cancel autocomplete / abort streaming |\n| \\`${clear}\\` | Clear editor (first) / exit (second) |\n| \\`${exit}\\` | Exit (when editor is empty) |\n| \\`${suspend}\\` | Suspend to background |\n| \\`${cycleThinkingLevel}\\` | Cycle thinking level |\n| \\`${cycleModelForward}\\` / \\`${cycleModelBackward}\\` | Cycle models |\n| \\`${selectModel}\\` | Open model selector |\n| \\`${expandTools}\\` | Toggle tool output expansion |\n| \\`${toggleThinking}\\` | Toggle thinking block visibility |\n| \\`${externalEditor}\\` | Edit message in external editor |\n| \\`${followUp}\\` | Queue follow-up message |\n| \\`${dequeue}\\` | Restore queued messages |\n| \\`${pasteImage}\\` | Paste image from clipboard |\n| \\`/\\` | Slash commands |\n| \\`!\\` | Run bash command |\n| \\`!!\\` | Run bash command (excluded from context) |\n`;\n\n\t// Add extension-registered shortcuts\n\tconst extensionRunner = host.session.extensionRunner;\n\tconst shortcuts = extensionRunner.getShortcuts(host.keybindings.getEffectiveConfig());\n\tif (shortcuts.size > 0) {\n\t\thotkeys += `\n**Extensions**\n| Key | Action |\n|-----|--------|\n`;\n\t\tfor (const [key, shortcut] of shortcuts) {\n\t\t\tconst description = shortcut.description ?? shortcut.extensionPath;\n\t\t\tconst keyDisplay = formatKeyText(key, { capitalize: true });\n\t\t\thotkeys += `| \\`${keyDisplay}\\` | ${description} |\\n`;\n\t\t}\n\t}\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new DynamicBorder());\n\thost.chatContainer.addChild(new Text(theme.bold(theme.fg(\"accent\", \"Keyboard Shortcuts\")), 1, 0));\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new Markdown(hotkeys.trim(), 1, 1, host.getMarkdownThemeWithSettings()));\n\thost.chatContainer.addChild(new DynamicBorder());\n\thost.ui.requestRender();\n}\n\nexport function handleDebugCommand(host: DebugReportHost): void {\n\tconst width = host.ui.terminal.columns;\n\tconst height = host.ui.terminal.rows;\n\tconst allLines = host.ui.render(width);\n\n\tconst debugLogPath = getDebugLogPath();\n\tconst debugData = [\n\t\t`Debug output at ${new Date().toISOString()}`,\n\t\t`Terminal: ${width}x${height}`,\n\t\t`Total lines: ${allLines.length}`,\n\t\t\"\",\n\t\t\"=== All rendered lines with visible widths ===\",\n\t\t...allLines.map((line, idx) => {\n\t\t\tconst vw = visibleWidth(line);\n\t\t\tconst escaped = JSON.stringify(line);\n\t\t\treturn `[${idx}] (w=${vw}) ${escaped}`;\n\t\t}),\n\t\t\"\",\n\t\t\"=== Agent messages (JSONL) ===\",\n\t\t...host.session.messages.map((msg) => JSON.stringify(msg)),\n\t\t\"\",\n\t].join(\"\\n\");\n\n\tfs.mkdirSync(path.dirname(debugLogPath), { recursive: true });\n\tfs.writeFileSync(debugLogPath, debugData);\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(\n\t\tnew Text(`${theme.fg(\"accent\", \"✓ Debug log written\")}\\n${theme.fg(\"muted\", debugLogPath)}`, 1, 1),\n\t);\n\thost.ui.requestRender();\n}\n\nexport function handleArminSaysHi(host: ReportRenderHost): void {\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new ArminComponent(host.ui));\n\thost.ui.requestRender();\n}\n\nexport function handleDementedDelves(host: ReportRenderHost): void {\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new EarendilAnnouncementComponent());\n\thost.ui.requestRender();\n}\n\nexport function handleDaxnuts(host: ReportRenderHost): void {\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new DaxnutsComponent(host.ui));\n\thost.ui.requestRender();\n}\n\nexport function checkDaxnutsEasterEgg(host: ReportRenderHost, model: { provider: string; id: string }): void {\n\tif (model.provider === \"opencode\" && model.id.toLowerCase().includes(\"kimi-k2.5\")) {\n\t\thandleDaxnuts(host);\n\t}\n}\n"]}
@@ -21,8 +21,7 @@ import { formatKeyText } from "./components/keybinding-hints.js";
21
21
  import { theme } from "./theme/theme.js";
22
22
  export function handleUsageCommand(host) {
23
23
  const stats = host.session.getSessionStats();
24
- const spawned = host.session.getSpawnedUsage();
25
- const daily = host.session.getDailyUsageTotals();
24
+ const costs = host.session.getCostSummary();
26
25
  const context = host.session.getContextUsage();
27
26
  const autoLearn = host.getCurrentAutoLearnSettings();
28
27
  const costGuard = host.session.getLastCostGuardDecision();
@@ -34,12 +33,12 @@ export function handleUsageCommand(host) {
34
33
  info += `${theme.fg("dim", "Cache write:")} ${stats.tokens.cacheWrite.toLocaleString()}\n`;
35
34
  info += `${theme.fg("dim", "Total:")} ${stats.tokens.total.toLocaleString()}\n\n`;
36
35
  info += `${theme.bold("Cost")}\n`;
37
- info += `${theme.fg("dim", "Session:")} $${stats.cost.toFixed(4)}\n`;
38
- info += `${theme.fg("dim", "Spawned/background:")} $${spawned.cost.toFixed(4)} (${spawned.reports} reports)\n`;
39
- info += `${theme.fg("dim", "Today:")} $${daily.totalCost.toFixed(4)}\n`;
40
- info += `${theme.fg("dim", "Today own:")} $${daily.ownCost.toFixed(4)}\n`;
41
- info += `${theme.fg("dim", "Today spawned/background:")} $${daily.spawnedCost.toFixed(4)}\n`;
42
- info += `${theme.fg("dim", "Today tokens:")} ${daily.totalTokens.toLocaleString()}\n\n`;
36
+ info += `${theme.fg("dim", "CURRENT (session):")} $${costs.currentCost.toFixed(4)}\n`;
37
+ if (costs.subagentReports > 0 || costs.subagentCost > 0) {
38
+ info += `${theme.fg("dim", "SUBAGENTS (included in CURRENT):")} $${costs.subagentCost.toFixed(4)} (${costs.subagentReports} reports)\n`;
39
+ }
40
+ info += `${theme.fg("dim", "TODAY (host local day):")} $${costs.todayCost.toFixed(4)}\n`;
41
+ info += `${theme.fg("dim", "Today rollover:")} local midnight\n\n`;
43
42
  const processMemory = getProcessMemoryMb();
44
43
  info += `${theme.bold("Process")}\n`;
45
44
  info += `${theme.fg("dim", "Memory:")} rss ${processMemory.rssMb}MB, heap ${processMemory.heapUsedMb}MB, external ${processMemory.externalMb}MB\n\n`;
@@ -1 +1 @@
1
- {"version":3,"file":"report-commands.js","sourceRoot":"","sources":["../../../src/modes/interactive/report-commands.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Read-only report and easter-egg commands extracted from interactive-mode.\n *\n * These build informational output (usage/cost summary, changelog, hotkeys\n * table, render debug dump) or render an easter-egg component, appending to the\n * chat container and requesting a render. None mutate agent/session state, so\n * they operate through narrow `host` seams (chat container, TUI, and a few\n * read accessors) while interactive-mode keeps thin delegating wrappers.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { Container, Keybinding, MarkdownTheme, TUI } from \"@caupulican/pi-tui\";\nimport { Markdown, Spacer, Text, visibleWidth } from \"@caupulican/pi-tui\";\nimport { getDebugLogPath } from \"../../config.ts\";\nimport type { AgentSession } from \"../../core/agent-session.ts\";\nimport type { AppKeybinding, KeybindingsManager } from \"../../core/keybindings.ts\";\nimport type { AutoLearnSettings } from \"../../core/settings-manager.ts\";\nimport { getChangelogPath, parseChangelog } from \"../../utils/changelog.ts\";\nimport { getProcessMemoryMb } from \"../../utils/process-memory.ts\";\nimport { ArminComponent } from \"./components/armin.ts\";\nimport { DaxnutsComponent } from \"./components/daxnuts.ts\";\nimport { DynamicBorder } from \"./components/dynamic-border.ts\";\nimport { EarendilAnnouncementComponent } from \"./components/earendil-announcement.ts\";\nimport { formatKeyText } from \"./components/keybinding-hints.ts\";\nimport { theme } from \"./theme/theme.ts\";\n\nexport interface ReportRenderHost {\n\treadonly chatContainer: Container;\n\treadonly ui: TUI;\n}\n\nexport interface UsageReportHost extends ReportRenderHost {\n\treadonly session: AgentSession;\n\tgetCurrentAutoLearnSettings(): Required<AutoLearnSettings>;\n}\n\nexport interface ChangelogReportHost extends ReportRenderHost {\n\tgetMarkdownThemeWithSettings(): MarkdownTheme;\n}\n\nexport interface HotkeysReportHost extends ReportRenderHost {\n\treadonly session: AgentSession;\n\treadonly keybindings: KeybindingsManager;\n\tgetMarkdownThemeWithSettings(): MarkdownTheme;\n\tgetAppKeyDisplay(action: AppKeybinding): string;\n\tgetEditorKeyDisplay(action: Keybinding): string;\n}\n\nexport interface DebugReportHost extends ReportRenderHost {\n\treadonly session: AgentSession;\n}\n\nexport function handleUsageCommand(host: UsageReportHost): void {\n\tconst stats = host.session.getSessionStats();\n\tconst spawned = host.session.getSpawnedUsage();\n\tconst daily = host.session.getDailyUsageTotals();\n\tconst context = host.session.getContextUsage();\n\tconst autoLearn = host.getCurrentAutoLearnSettings();\n\tconst costGuard = host.session.getLastCostGuardDecision();\n\n\tlet info = `${theme.bold(\"Usage & Optimization\")}\\n\\n`;\n\tinfo += `${theme.bold(\"Session tokens\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Input:\")} ${stats.tokens.input.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Output:\")} ${stats.tokens.output.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Cache read:\")} ${stats.tokens.cacheRead.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Cache write:\")} ${stats.tokens.cacheWrite.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Total:\")} ${stats.tokens.total.toLocaleString()}\\n\\n`;\n\n\tinfo += `${theme.bold(\"Cost\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Session:\")} $${stats.cost.toFixed(4)}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Spawned/background:\")} $${spawned.cost.toFixed(4)} (${spawned.reports} reports)\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Today:\")} $${daily.totalCost.toFixed(4)}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Today own:\")} $${daily.ownCost.toFixed(4)}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Today spawned/background:\")} $${daily.spawnedCost.toFixed(4)}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Today tokens:\")} ${daily.totalTokens.toLocaleString()}\\n\\n`;\n\n\tconst processMemory = getProcessMemoryMb();\n\tinfo += `${theme.bold(\"Process\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Memory:\")} rss ${processMemory.rssMb}MB, heap ${processMemory.heapUsedMb}MB, external ${processMemory.externalMb}MB\\n\\n`;\n\n\tinfo += `${theme.bold(\"Optimization state\")}\\n`;\n\tconst contextPercent = context?.percent;\n\tconst contextTokens = context?.tokens;\n\tif (\n\t\tcontext &&\n\t\tcontextPercent !== undefined &&\n\t\tcontextPercent !== null &&\n\t\tcontextTokens !== undefined &&\n\t\tcontextTokens !== null\n\t) {\n\t\tinfo += `${theme.fg(\"dim\", \"Context:\")} ${contextPercent.toFixed(1)}% (${contextTokens.toLocaleString()}/${context.contextWindow.toLocaleString()})\\n`;\n\t} else {\n\t\tinfo += `${theme.fg(\"dim\", \"Context:\")} unknown until next provider usage sample\\n`;\n\t}\n\tinfo += `${theme.fg(\"dim\", \"Auto-compaction:\")} ${host.session.autoCompactionEnabled ? \"enabled\" : \"disabled\"}\\n`;\n\tif (costGuard) {\n\t\tconst status = costGuard.over ? \"over\" : \"ok\";\n\t\tinfo += `${theme.fg(\"dim\", \"Cost guard:\")} ${status} $${costGuard.estUsd.toFixed(4)}/$${costGuard.thresholdUsd.toFixed(4)} (${costGuard.action})\\n`;\n\t} else {\n\t\tinfo += `${theme.fg(\"dim\", \"Cost guard:\")} disabled\\n`;\n\t}\n\tinfo += `${theme.fg(\"dim\", \"Auto Learn:\")} ${autoLearn.enabled ? \"enabled\" : \"disabled\"}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Scavenger model:\")} ${autoLearn.model || \"active\"}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Reflection review:\")} ${autoLearn.reflectionReview ? \"enabled\" : \"disabled\"} (${autoLearn.reflectionMinToolCalls} tool-call trigger)\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Auto Learn concurrency:\")} ${autoLearn.maxConcurrentLearners} learner(s), ${autoLearn.cooldownMinutes}m cooldown\\n\\n`;\n\n\tinfo += `${theme.bold(\"Model Router\")}\\n`;\n\tinfo += `${host.session.getModelRouterStatus((label) => theme.fg(\"dim\", label))}\\n\\n`;\n\n\tinfo += `${theme.bold(\"Manual controls\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"/compact\")}: compact the active context now\\n`;\n\tinfo += `${theme.fg(\"dim\", \"/settings\")}: adjust Auto Learn, cost guard, compaction, and model-router config\\n`;\n\tinfo += `${theme.fg(\"dim\", \"/auto-learn status|run\")}: inspect or launch background learning\\n`;\n\tinfo += `${theme.fg(\"dim\", \"context_audit\")}: ask the agent to inspect provider-visible context contributors\\n`;\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new Text(info, 1, 0));\n\thost.ui.requestRender();\n}\n\nexport function handleChangelogCommand(host: ChangelogReportHost): void {\n\tconst changelogPath = getChangelogPath();\n\tconst allEntries = parseChangelog(changelogPath);\n\n\tconst changelogMarkdown =\n\t\tallEntries.length > 0\n\t\t\t? allEntries\n\t\t\t\t\t.reverse()\n\t\t\t\t\t.map((e) => e.content)\n\t\t\t\t\t.join(\"\\n\\n\")\n\t\t\t: \"No changelog entries found.\";\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new DynamicBorder());\n\thost.chatContainer.addChild(new Text(theme.bold(theme.fg(\"accent\", \"What's New\")), 1, 0));\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new Markdown(changelogMarkdown, 1, 1, host.getMarkdownThemeWithSettings()));\n\thost.chatContainer.addChild(new DynamicBorder());\n\thost.ui.requestRender();\n}\n\nexport function handleHotkeysCommand(host: HotkeysReportHost): void {\n\t// Navigation keybindings\n\tconst cursorUp = host.getEditorKeyDisplay(\"tui.editor.cursorUp\");\n\tconst cursorDown = host.getEditorKeyDisplay(\"tui.editor.cursorDown\");\n\tconst cursorLeft = host.getEditorKeyDisplay(\"tui.editor.cursorLeft\");\n\tconst cursorRight = host.getEditorKeyDisplay(\"tui.editor.cursorRight\");\n\tconst cursorWordLeft = host.getEditorKeyDisplay(\"tui.editor.cursorWordLeft\");\n\tconst cursorWordRight = host.getEditorKeyDisplay(\"tui.editor.cursorWordRight\");\n\tconst cursorLineStart = host.getEditorKeyDisplay(\"tui.editor.cursorLineStart\");\n\tconst cursorLineEnd = host.getEditorKeyDisplay(\"tui.editor.cursorLineEnd\");\n\tconst jumpForward = host.getEditorKeyDisplay(\"tui.editor.jumpForward\");\n\tconst jumpBackward = host.getEditorKeyDisplay(\"tui.editor.jumpBackward\");\n\tconst pageUp = host.getEditorKeyDisplay(\"tui.editor.pageUp\");\n\tconst pageDown = host.getEditorKeyDisplay(\"tui.editor.pageDown\");\n\n\t// Editing keybindings\n\tconst submit = host.getEditorKeyDisplay(\"tui.input.submit\");\n\tconst newLine = host.getEditorKeyDisplay(\"tui.input.newLine\");\n\tconst deleteWordBackward = host.getEditorKeyDisplay(\"tui.editor.deleteWordBackward\");\n\tconst deleteWordForward = host.getEditorKeyDisplay(\"tui.editor.deleteWordForward\");\n\tconst deleteToLineStart = host.getEditorKeyDisplay(\"tui.editor.deleteToLineStart\");\n\tconst deleteToLineEnd = host.getEditorKeyDisplay(\"tui.editor.deleteToLineEnd\");\n\tconst yank = host.getEditorKeyDisplay(\"tui.editor.yank\");\n\tconst yankPop = host.getEditorKeyDisplay(\"tui.editor.yankPop\");\n\tconst undo = host.getEditorKeyDisplay(\"tui.editor.undo\");\n\tconst tab = host.getEditorKeyDisplay(\"tui.input.tab\");\n\n\t// App keybindings\n\tconst interrupt = host.getAppKeyDisplay(\"app.interrupt\");\n\tconst clear = host.getAppKeyDisplay(\"app.clear\");\n\tconst exit = host.getAppKeyDisplay(\"app.exit\");\n\tconst suspend = host.getAppKeyDisplay(\"app.suspend\");\n\tconst cycleThinkingLevel = host.getAppKeyDisplay(\"app.thinking.cycle\");\n\tconst cycleModelForward = host.getAppKeyDisplay(\"app.model.cycleForward\");\n\tconst selectModel = host.getAppKeyDisplay(\"app.model.select\");\n\tconst expandTools = host.getAppKeyDisplay(\"app.tools.expand\");\n\tconst toggleThinking = host.getAppKeyDisplay(\"app.thinking.toggle\");\n\tconst externalEditor = host.getAppKeyDisplay(\"app.editor.external\");\n\tconst cycleModelBackward = host.getAppKeyDisplay(\"app.model.cycleBackward\");\n\tconst followUp = host.getAppKeyDisplay(\"app.message.followUp\");\n\tconst dequeue = host.getAppKeyDisplay(\"app.message.dequeue\");\n\tconst pasteImage = host.getAppKeyDisplay(\"app.clipboard.pasteImage\");\n\n\tlet hotkeys = `\n**Navigation**\n| Key | Action |\n|-----|--------|\n| \\`${cursorUp}\\` / \\`${cursorDown}\\` / \\`${cursorLeft}\\` / \\`${cursorRight}\\` | Move cursor / browse history (Up when empty) |\n| \\`${cursorWordLeft}\\` / \\`${cursorWordRight}\\` | Move by word |\n| \\`${cursorLineStart}\\` | Start of line |\n| \\`${cursorLineEnd}\\` | End of line |\n| \\`${jumpForward}\\` | Jump forward to character |\n| \\`${jumpBackward}\\` | Jump backward to character |\n| \\`${pageUp}\\` / \\`${pageDown}\\` | Scroll by page |\n\n**Editing**\n| Key | Action |\n|-----|--------|\n| \\`${submit}\\` | Send message |\n| \\`${newLine}\\` | New line${process.platform === \"win32\" ? \" (Ctrl+Enter on Windows Terminal)\" : \"\"} |\n| \\`${deleteWordBackward}\\` | Delete word backwards |\n| \\`${deleteWordForward}\\` | Delete word forwards |\n| \\`${deleteToLineStart}\\` | Delete to start of line |\n| \\`${deleteToLineEnd}\\` | Delete to end of line |\n| \\`${yank}\\` | Paste the most-recently-deleted text |\n| \\`${yankPop}\\` | Cycle through the deleted text after pasting |\n| \\`${undo}\\` | Undo |\n\n**Other**\n| Key | Action |\n|-----|--------|\n| \\`${tab}\\` | Path completion / accept autocomplete |\n| \\`${interrupt}\\` | Cancel autocomplete / abort streaming |\n| \\`${clear}\\` | Clear editor (first) / exit (second) |\n| \\`${exit}\\` | Exit (when editor is empty) |\n| \\`${suspend}\\` | Suspend to background |\n| \\`${cycleThinkingLevel}\\` | Cycle thinking level |\n| \\`${cycleModelForward}\\` / \\`${cycleModelBackward}\\` | Cycle models |\n| \\`${selectModel}\\` | Open model selector |\n| \\`${expandTools}\\` | Toggle tool output expansion |\n| \\`${toggleThinking}\\` | Toggle thinking block visibility |\n| \\`${externalEditor}\\` | Edit message in external editor |\n| \\`${followUp}\\` | Queue follow-up message |\n| \\`${dequeue}\\` | Restore queued messages |\n| \\`${pasteImage}\\` | Paste image from clipboard |\n| \\`/\\` | Slash commands |\n| \\`!\\` | Run bash command |\n| \\`!!\\` | Run bash command (excluded from context) |\n`;\n\n\t// Add extension-registered shortcuts\n\tconst extensionRunner = host.session.extensionRunner;\n\tconst shortcuts = extensionRunner.getShortcuts(host.keybindings.getEffectiveConfig());\n\tif (shortcuts.size > 0) {\n\t\thotkeys += `\n**Extensions**\n| Key | Action |\n|-----|--------|\n`;\n\t\tfor (const [key, shortcut] of shortcuts) {\n\t\t\tconst description = shortcut.description ?? shortcut.extensionPath;\n\t\t\tconst keyDisplay = formatKeyText(key, { capitalize: true });\n\t\t\thotkeys += `| \\`${keyDisplay}\\` | ${description} |\\n`;\n\t\t}\n\t}\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new DynamicBorder());\n\thost.chatContainer.addChild(new Text(theme.bold(theme.fg(\"accent\", \"Keyboard Shortcuts\")), 1, 0));\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new Markdown(hotkeys.trim(), 1, 1, host.getMarkdownThemeWithSettings()));\n\thost.chatContainer.addChild(new DynamicBorder());\n\thost.ui.requestRender();\n}\n\nexport function handleDebugCommand(host: DebugReportHost): void {\n\tconst width = host.ui.terminal.columns;\n\tconst height = host.ui.terminal.rows;\n\tconst allLines = host.ui.render(width);\n\n\tconst debugLogPath = getDebugLogPath();\n\tconst debugData = [\n\t\t`Debug output at ${new Date().toISOString()}`,\n\t\t`Terminal: ${width}x${height}`,\n\t\t`Total lines: ${allLines.length}`,\n\t\t\"\",\n\t\t\"=== All rendered lines with visible widths ===\",\n\t\t...allLines.map((line, idx) => {\n\t\t\tconst vw = visibleWidth(line);\n\t\t\tconst escaped = JSON.stringify(line);\n\t\t\treturn `[${idx}] (w=${vw}) ${escaped}`;\n\t\t}),\n\t\t\"\",\n\t\t\"=== Agent messages (JSONL) ===\",\n\t\t...host.session.messages.map((msg) => JSON.stringify(msg)),\n\t\t\"\",\n\t].join(\"\\n\");\n\n\tfs.mkdirSync(path.dirname(debugLogPath), { recursive: true });\n\tfs.writeFileSync(debugLogPath, debugData);\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(\n\t\tnew Text(`${theme.fg(\"accent\", \"✓ Debug log written\")}\\n${theme.fg(\"muted\", debugLogPath)}`, 1, 1),\n\t);\n\thost.ui.requestRender();\n}\n\nexport function handleArminSaysHi(host: ReportRenderHost): void {\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new ArminComponent(host.ui));\n\thost.ui.requestRender();\n}\n\nexport function handleDementedDelves(host: ReportRenderHost): void {\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new EarendilAnnouncementComponent());\n\thost.ui.requestRender();\n}\n\nexport function handleDaxnuts(host: ReportRenderHost): void {\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new DaxnutsComponent(host.ui));\n\thost.ui.requestRender();\n}\n\nexport function checkDaxnutsEasterEgg(host: ReportRenderHost, model: { provider: string; id: string }): void {\n\tif (model.provider === \"opencode\" && model.id.toLowerCase().includes(\"kimi-k2.5\")) {\n\t\thandleDaxnuts(host);\n\t}\n}\n"]}
1
+ {"version":3,"file":"report-commands.js","sourceRoot":"","sources":["../../../src/modes/interactive/report-commands.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Read-only report and easter-egg commands extracted from interactive-mode.\n *\n * These build informational output (usage/cost summary, changelog, hotkeys\n * table, render debug dump) or render an easter-egg component, appending to the\n * chat container and requesting a render. None mutate agent/session state, so\n * they operate through narrow `host` seams (chat container, TUI, and a few\n * read accessors) while interactive-mode keeps thin delegating wrappers.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { Container, Keybinding, MarkdownTheme, TUI } from \"@caupulican/pi-tui\";\nimport { Markdown, Spacer, Text, visibleWidth } from \"@caupulican/pi-tui\";\nimport { getDebugLogPath } from \"../../config.ts\";\nimport type { AgentSession } from \"../../core/agent-session.ts\";\nimport type { AppKeybinding, KeybindingsManager } from \"../../core/keybindings.ts\";\nimport type { AutoLearnSettings } from \"../../core/settings-manager.ts\";\nimport { getChangelogPath, parseChangelog } from \"../../utils/changelog.ts\";\nimport { getProcessMemoryMb } from \"../../utils/process-memory.ts\";\nimport { ArminComponent } from \"./components/armin.ts\";\nimport { DaxnutsComponent } from \"./components/daxnuts.ts\";\nimport { DynamicBorder } from \"./components/dynamic-border.ts\";\nimport { EarendilAnnouncementComponent } from \"./components/earendil-announcement.ts\";\nimport { formatKeyText } from \"./components/keybinding-hints.ts\";\nimport { theme } from \"./theme/theme.ts\";\n\nexport interface ReportRenderHost {\n\treadonly chatContainer: Container;\n\treadonly ui: TUI;\n}\n\nexport interface UsageReportHost extends ReportRenderHost {\n\treadonly session: AgentSession;\n\tgetCurrentAutoLearnSettings(): Required<AutoLearnSettings>;\n}\n\nexport interface ChangelogReportHost extends ReportRenderHost {\n\tgetMarkdownThemeWithSettings(): MarkdownTheme;\n}\n\nexport interface HotkeysReportHost extends ReportRenderHost {\n\treadonly session: AgentSession;\n\treadonly keybindings: KeybindingsManager;\n\tgetMarkdownThemeWithSettings(): MarkdownTheme;\n\tgetAppKeyDisplay(action: AppKeybinding): string;\n\tgetEditorKeyDisplay(action: Keybinding): string;\n}\n\nexport interface DebugReportHost extends ReportRenderHost {\n\treadonly session: AgentSession;\n}\n\nexport function handleUsageCommand(host: UsageReportHost): void {\n\tconst stats = host.session.getSessionStats();\n\tconst costs = host.session.getCostSummary();\n\tconst context = host.session.getContextUsage();\n\tconst autoLearn = host.getCurrentAutoLearnSettings();\n\tconst costGuard = host.session.getLastCostGuardDecision();\n\n\tlet info = `${theme.bold(\"Usage & Optimization\")}\\n\\n`;\n\tinfo += `${theme.bold(\"Session tokens\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Input:\")} ${stats.tokens.input.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Output:\")} ${stats.tokens.output.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Cache read:\")} ${stats.tokens.cacheRead.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Cache write:\")} ${stats.tokens.cacheWrite.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Total:\")} ${stats.tokens.total.toLocaleString()}\\n\\n`;\n\n\tinfo += `${theme.bold(\"Cost\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"CURRENT (session):\")} $${costs.currentCost.toFixed(4)}\\n`;\n\tif (costs.subagentReports > 0 || costs.subagentCost > 0) {\n\t\tinfo += `${theme.fg(\"dim\", \"SUBAGENTS (included in CURRENT):\")} $${costs.subagentCost.toFixed(4)} (${costs.subagentReports} reports)\\n`;\n\t}\n\tinfo += `${theme.fg(\"dim\", \"TODAY (host local day):\")} $${costs.todayCost.toFixed(4)}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Today rollover:\")} local midnight\\n\\n`;\n\n\tconst processMemory = getProcessMemoryMb();\n\tinfo += `${theme.bold(\"Process\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Memory:\")} rss ${processMemory.rssMb}MB, heap ${processMemory.heapUsedMb}MB, external ${processMemory.externalMb}MB\\n\\n`;\n\n\tinfo += `${theme.bold(\"Optimization state\")}\\n`;\n\tconst contextPercent = context?.percent;\n\tconst contextTokens = context?.tokens;\n\tif (\n\t\tcontext &&\n\t\tcontextPercent !== undefined &&\n\t\tcontextPercent !== null &&\n\t\tcontextTokens !== undefined &&\n\t\tcontextTokens !== null\n\t) {\n\t\tinfo += `${theme.fg(\"dim\", \"Context:\")} ${contextPercent.toFixed(1)}% (${contextTokens.toLocaleString()}/${context.contextWindow.toLocaleString()})\\n`;\n\t} else {\n\t\tinfo += `${theme.fg(\"dim\", \"Context:\")} unknown until next provider usage sample\\n`;\n\t}\n\tinfo += `${theme.fg(\"dim\", \"Auto-compaction:\")} ${host.session.autoCompactionEnabled ? \"enabled\" : \"disabled\"}\\n`;\n\tif (costGuard) {\n\t\tconst status = costGuard.over ? \"over\" : \"ok\";\n\t\tinfo += `${theme.fg(\"dim\", \"Cost guard:\")} ${status} $${costGuard.estUsd.toFixed(4)}/$${costGuard.thresholdUsd.toFixed(4)} (${costGuard.action})\\n`;\n\t} else {\n\t\tinfo += `${theme.fg(\"dim\", \"Cost guard:\")} disabled\\n`;\n\t}\n\tinfo += `${theme.fg(\"dim\", \"Auto Learn:\")} ${autoLearn.enabled ? \"enabled\" : \"disabled\"}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Scavenger model:\")} ${autoLearn.model || \"active\"}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Reflection review:\")} ${autoLearn.reflectionReview ? \"enabled\" : \"disabled\"} (${autoLearn.reflectionMinToolCalls} tool-call trigger)\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Auto Learn concurrency:\")} ${autoLearn.maxConcurrentLearners} learner(s), ${autoLearn.cooldownMinutes}m cooldown\\n\\n`;\n\n\tinfo += `${theme.bold(\"Model Router\")}\\n`;\n\tinfo += `${host.session.getModelRouterStatus((label) => theme.fg(\"dim\", label))}\\n\\n`;\n\n\tinfo += `${theme.bold(\"Manual controls\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"/compact\")}: compact the active context now\\n`;\n\tinfo += `${theme.fg(\"dim\", \"/settings\")}: adjust Auto Learn, cost guard, compaction, and model-router config\\n`;\n\tinfo += `${theme.fg(\"dim\", \"/auto-learn status|run\")}: inspect or launch background learning\\n`;\n\tinfo += `${theme.fg(\"dim\", \"context_audit\")}: ask the agent to inspect provider-visible context contributors\\n`;\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new Text(info, 1, 0));\n\thost.ui.requestRender();\n}\n\nexport function handleChangelogCommand(host: ChangelogReportHost): void {\n\tconst changelogPath = getChangelogPath();\n\tconst allEntries = parseChangelog(changelogPath);\n\n\tconst changelogMarkdown =\n\t\tallEntries.length > 0\n\t\t\t? allEntries\n\t\t\t\t\t.reverse()\n\t\t\t\t\t.map((e) => e.content)\n\t\t\t\t\t.join(\"\\n\\n\")\n\t\t\t: \"No changelog entries found.\";\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new DynamicBorder());\n\thost.chatContainer.addChild(new Text(theme.bold(theme.fg(\"accent\", \"What's New\")), 1, 0));\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new Markdown(changelogMarkdown, 1, 1, host.getMarkdownThemeWithSettings()));\n\thost.chatContainer.addChild(new DynamicBorder());\n\thost.ui.requestRender();\n}\n\nexport function handleHotkeysCommand(host: HotkeysReportHost): void {\n\t// Navigation keybindings\n\tconst cursorUp = host.getEditorKeyDisplay(\"tui.editor.cursorUp\");\n\tconst cursorDown = host.getEditorKeyDisplay(\"tui.editor.cursorDown\");\n\tconst cursorLeft = host.getEditorKeyDisplay(\"tui.editor.cursorLeft\");\n\tconst cursorRight = host.getEditorKeyDisplay(\"tui.editor.cursorRight\");\n\tconst cursorWordLeft = host.getEditorKeyDisplay(\"tui.editor.cursorWordLeft\");\n\tconst cursorWordRight = host.getEditorKeyDisplay(\"tui.editor.cursorWordRight\");\n\tconst cursorLineStart = host.getEditorKeyDisplay(\"tui.editor.cursorLineStart\");\n\tconst cursorLineEnd = host.getEditorKeyDisplay(\"tui.editor.cursorLineEnd\");\n\tconst jumpForward = host.getEditorKeyDisplay(\"tui.editor.jumpForward\");\n\tconst jumpBackward = host.getEditorKeyDisplay(\"tui.editor.jumpBackward\");\n\tconst pageUp = host.getEditorKeyDisplay(\"tui.editor.pageUp\");\n\tconst pageDown = host.getEditorKeyDisplay(\"tui.editor.pageDown\");\n\n\t// Editing keybindings\n\tconst submit = host.getEditorKeyDisplay(\"tui.input.submit\");\n\tconst newLine = host.getEditorKeyDisplay(\"tui.input.newLine\");\n\tconst deleteWordBackward = host.getEditorKeyDisplay(\"tui.editor.deleteWordBackward\");\n\tconst deleteWordForward = host.getEditorKeyDisplay(\"tui.editor.deleteWordForward\");\n\tconst deleteToLineStart = host.getEditorKeyDisplay(\"tui.editor.deleteToLineStart\");\n\tconst deleteToLineEnd = host.getEditorKeyDisplay(\"tui.editor.deleteToLineEnd\");\n\tconst yank = host.getEditorKeyDisplay(\"tui.editor.yank\");\n\tconst yankPop = host.getEditorKeyDisplay(\"tui.editor.yankPop\");\n\tconst undo = host.getEditorKeyDisplay(\"tui.editor.undo\");\n\tconst tab = host.getEditorKeyDisplay(\"tui.input.tab\");\n\n\t// App keybindings\n\tconst interrupt = host.getAppKeyDisplay(\"app.interrupt\");\n\tconst clear = host.getAppKeyDisplay(\"app.clear\");\n\tconst exit = host.getAppKeyDisplay(\"app.exit\");\n\tconst suspend = host.getAppKeyDisplay(\"app.suspend\");\n\tconst cycleThinkingLevel = host.getAppKeyDisplay(\"app.thinking.cycle\");\n\tconst cycleModelForward = host.getAppKeyDisplay(\"app.model.cycleForward\");\n\tconst selectModel = host.getAppKeyDisplay(\"app.model.select\");\n\tconst expandTools = host.getAppKeyDisplay(\"app.tools.expand\");\n\tconst toggleThinking = host.getAppKeyDisplay(\"app.thinking.toggle\");\n\tconst externalEditor = host.getAppKeyDisplay(\"app.editor.external\");\n\tconst cycleModelBackward = host.getAppKeyDisplay(\"app.model.cycleBackward\");\n\tconst followUp = host.getAppKeyDisplay(\"app.message.followUp\");\n\tconst dequeue = host.getAppKeyDisplay(\"app.message.dequeue\");\n\tconst pasteImage = host.getAppKeyDisplay(\"app.clipboard.pasteImage\");\n\n\tlet hotkeys = `\n**Navigation**\n| Key | Action |\n|-----|--------|\n| \\`${cursorUp}\\` / \\`${cursorDown}\\` / \\`${cursorLeft}\\` / \\`${cursorRight}\\` | Move cursor / browse history (Up when empty) |\n| \\`${cursorWordLeft}\\` / \\`${cursorWordRight}\\` | Move by word |\n| \\`${cursorLineStart}\\` | Start of line |\n| \\`${cursorLineEnd}\\` | End of line |\n| \\`${jumpForward}\\` | Jump forward to character |\n| \\`${jumpBackward}\\` | Jump backward to character |\n| \\`${pageUp}\\` / \\`${pageDown}\\` | Scroll by page |\n\n**Editing**\n| Key | Action |\n|-----|--------|\n| \\`${submit}\\` | Send message |\n| \\`${newLine}\\` | New line${process.platform === \"win32\" ? \" (Ctrl+Enter on Windows Terminal)\" : \"\"} |\n| \\`${deleteWordBackward}\\` | Delete word backwards |\n| \\`${deleteWordForward}\\` | Delete word forwards |\n| \\`${deleteToLineStart}\\` | Delete to start of line |\n| \\`${deleteToLineEnd}\\` | Delete to end of line |\n| \\`${yank}\\` | Paste the most-recently-deleted text |\n| \\`${yankPop}\\` | Cycle through the deleted text after pasting |\n| \\`${undo}\\` | Undo |\n\n**Other**\n| Key | Action |\n|-----|--------|\n| \\`${tab}\\` | Path completion / accept autocomplete |\n| \\`${interrupt}\\` | Cancel autocomplete / abort streaming |\n| \\`${clear}\\` | Clear editor (first) / exit (second) |\n| \\`${exit}\\` | Exit (when editor is empty) |\n| \\`${suspend}\\` | Suspend to background |\n| \\`${cycleThinkingLevel}\\` | Cycle thinking level |\n| \\`${cycleModelForward}\\` / \\`${cycleModelBackward}\\` | Cycle models |\n| \\`${selectModel}\\` | Open model selector |\n| \\`${expandTools}\\` | Toggle tool output expansion |\n| \\`${toggleThinking}\\` | Toggle thinking block visibility |\n| \\`${externalEditor}\\` | Edit message in external editor |\n| \\`${followUp}\\` | Queue follow-up message |\n| \\`${dequeue}\\` | Restore queued messages |\n| \\`${pasteImage}\\` | Paste image from clipboard |\n| \\`/\\` | Slash commands |\n| \\`!\\` | Run bash command |\n| \\`!!\\` | Run bash command (excluded from context) |\n`;\n\n\t// Add extension-registered shortcuts\n\tconst extensionRunner = host.session.extensionRunner;\n\tconst shortcuts = extensionRunner.getShortcuts(host.keybindings.getEffectiveConfig());\n\tif (shortcuts.size > 0) {\n\t\thotkeys += `\n**Extensions**\n| Key | Action |\n|-----|--------|\n`;\n\t\tfor (const [key, shortcut] of shortcuts) {\n\t\t\tconst description = shortcut.description ?? shortcut.extensionPath;\n\t\t\tconst keyDisplay = formatKeyText(key, { capitalize: true });\n\t\t\thotkeys += `| \\`${keyDisplay}\\` | ${description} |\\n`;\n\t\t}\n\t}\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new DynamicBorder());\n\thost.chatContainer.addChild(new Text(theme.bold(theme.fg(\"accent\", \"Keyboard Shortcuts\")), 1, 0));\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new Markdown(hotkeys.trim(), 1, 1, host.getMarkdownThemeWithSettings()));\n\thost.chatContainer.addChild(new DynamicBorder());\n\thost.ui.requestRender();\n}\n\nexport function handleDebugCommand(host: DebugReportHost): void {\n\tconst width = host.ui.terminal.columns;\n\tconst height = host.ui.terminal.rows;\n\tconst allLines = host.ui.render(width);\n\n\tconst debugLogPath = getDebugLogPath();\n\tconst debugData = [\n\t\t`Debug output at ${new Date().toISOString()}`,\n\t\t`Terminal: ${width}x${height}`,\n\t\t`Total lines: ${allLines.length}`,\n\t\t\"\",\n\t\t\"=== All rendered lines with visible widths ===\",\n\t\t...allLines.map((line, idx) => {\n\t\t\tconst vw = visibleWidth(line);\n\t\t\tconst escaped = JSON.stringify(line);\n\t\t\treturn `[${idx}] (w=${vw}) ${escaped}`;\n\t\t}),\n\t\t\"\",\n\t\t\"=== Agent messages (JSONL) ===\",\n\t\t...host.session.messages.map((msg) => JSON.stringify(msg)),\n\t\t\"\",\n\t].join(\"\\n\");\n\n\tfs.mkdirSync(path.dirname(debugLogPath), { recursive: true });\n\tfs.writeFileSync(debugLogPath, debugData);\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(\n\t\tnew Text(`${theme.fg(\"accent\", \"✓ Debug log written\")}\\n${theme.fg(\"muted\", debugLogPath)}`, 1, 1),\n\t);\n\thost.ui.requestRender();\n}\n\nexport function handleArminSaysHi(host: ReportRenderHost): void {\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new ArminComponent(host.ui));\n\thost.ui.requestRender();\n}\n\nexport function handleDementedDelves(host: ReportRenderHost): void {\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new EarendilAnnouncementComponent());\n\thost.ui.requestRender();\n}\n\nexport function handleDaxnuts(host: ReportRenderHost): void {\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new DaxnutsComponent(host.ui));\n\thost.ui.requestRender();\n}\n\nexport function checkDaxnutsEasterEgg(host: ReportRenderHost, model: { provider: string; id: string }): void {\n\tif (model.provider === \"opencode\" && model.id.toLowerCase().includes(\"kimi-k2.5\")) {\n\t\thandleDaxnuts(host);\n\t}\n}\n"]}
@@ -139,8 +139,7 @@ export declare function handleGoalContinueCommand(host: GoalContinueCommandHost,
139
139
  export interface SessionInfoCommandHost {
140
140
  readonly session: {
141
141
  getSessionStats: () => ReturnType<AgentSession["getSessionStats"]>;
142
- getDailyUsageTotals: () => ReturnType<AgentSession["getDailyUsageTotals"]>;
143
- getDailyUsageBreakdown: (formatLabel: (label: string) => string) => string;
142
+ getCostSummary: () => ReturnType<AgentSession["getCostSummary"]>;
144
143
  getModelRouterStatus: (formatLabel: (label: string) => string) => string;
145
144
  };
146
145
  readonly sessionManager: {