@ashx-j/lunr 0.1.6 → 0.2.0

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 (149) hide show
  1. package/dist/builtin-extensions/index.d.ts.map +1 -1
  2. package/dist/builtin-extensions/index.js +3 -6
  3. package/dist/builtin-extensions/index.js.map +1 -1
  4. package/dist/builtin-extensions/lunr-todos.d.ts +7 -6
  5. package/dist/builtin-extensions/lunr-todos.d.ts.map +1 -1
  6. package/dist/builtin-extensions/lunr-todos.js +24 -11
  7. package/dist/builtin-extensions/lunr-todos.js.map +1 -1
  8. package/dist/builtin-extensions/narumiruna-pi-goal/src/commands.d.ts.map +1 -1
  9. package/dist/builtin-extensions/narumiruna-pi-goal/src/commands.js +9 -5
  10. package/dist/builtin-extensions/narumiruna-pi-goal/src/commands.js.map +1 -1
  11. package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.d.ts.map +1 -1
  12. package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.js +31 -3
  13. package/dist/builtin-extensions/narumiruna-pi-goal/src/goal.js.map +1 -1
  14. package/dist/builtin-extensions/narumiruna-pi-goal/src/runtime.d.ts +1 -0
  15. package/dist/builtin-extensions/narumiruna-pi-goal/src/runtime.d.ts.map +1 -1
  16. package/dist/builtin-extensions/narumiruna-pi-goal/src/runtime.js +14 -4
  17. package/dist/builtin-extensions/narumiruna-pi-goal/src/runtime.js.map +1 -1
  18. package/dist/builtin-extensions/pi-subagents/src/extension/index.d.ts.map +1 -1
  19. package/dist/builtin-extensions/pi-subagents/src/extension/index.js +4 -3
  20. package/dist/builtin-extensions/pi-subagents/src/extension/index.js.map +1 -1
  21. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.d.ts.map +1 -1
  22. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js +12 -1
  23. package/dist/builtin-extensions/pi-subagents/src/runs/foreground/execution.js.map +1 -1
  24. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts +3 -0
  25. package/dist/builtin-extensions/pi-subagents/src/shared/types.d.ts.map +1 -1
  26. package/dist/builtin-extensions/pi-subagents/src/shared/types.js.map +1 -1
  27. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts +8 -0
  28. package/dist/builtin-extensions/pi-subagents/src/tui/render.d.ts.map +1 -1
  29. package/dist/builtin-extensions/pi-subagents/src/tui/render.js +22 -2
  30. package/dist/builtin-extensions/pi-subagents/src/tui/render.js.map +1 -1
  31. package/dist/builtin-extensions/pi-web-access/index.d.ts.map +1 -1
  32. package/dist/builtin-extensions/pi-web-access/index.js +38 -230
  33. package/dist/builtin-extensions/pi-web-access/index.js.map +1 -1
  34. package/dist/builtin-extensions/pi-web-access/render-search-chrome.d.ts +35 -0
  35. package/dist/builtin-extensions/pi-web-access/render-search-chrome.d.ts.map +1 -0
  36. package/dist/builtin-extensions/pi-web-access/render-search-chrome.js +93 -0
  37. package/dist/builtin-extensions/pi-web-access/render-search-chrome.js.map +1 -0
  38. package/dist/bun/cli.d.ts.map +1 -1
  39. package/dist/bun/cli.js +1 -0
  40. package/dist/bun/cli.js.map +1 -1
  41. package/dist/catalog/models.json +1 -1
  42. package/dist/catalog/providers/cerebras.json +1 -1
  43. package/dist/catalog/providers/cloudflare-ai-gateway.json +1 -1
  44. package/dist/catalog/providers/cloudflare-workers-ai.json +1 -1
  45. package/dist/catalog/providers/huggingface.json +1 -1
  46. package/dist/catalog/providers/opencode-go.json +1 -1
  47. package/dist/catalog/providers/openrouter.json +1 -1
  48. package/dist/catalog/providers/vercel-ai-gateway.json +1 -1
  49. package/dist/catalog/publication.json +3 -3
  50. package/dist/cli.d.ts.map +1 -1
  51. package/dist/cli.js +4 -1
  52. package/dist/cli.js.map +1 -1
  53. package/dist/core/context-breakdown.d.ts +21 -1
  54. package/dist/core/context-breakdown.d.ts.map +1 -1
  55. package/dist/core/context-breakdown.js +58 -2
  56. package/dist/core/context-breakdown.js.map +1 -1
  57. package/dist/core/extensions/host-static.d.ts +2 -0
  58. package/dist/core/extensions/host-static.d.ts.map +1 -0
  59. package/dist/core/extensions/host-static.js +15 -0
  60. package/dist/core/extensions/host-static.js.map +1 -0
  61. package/dist/core/extensions/loader.d.ts +10 -0
  62. package/dist/core/extensions/loader.d.ts.map +1 -1
  63. package/dist/core/extensions/loader.js +75 -34
  64. package/dist/core/extensions/loader.js.map +1 -1
  65. package/dist/core/official-catalog.d.ts.map +1 -1
  66. package/dist/core/official-catalog.js +11 -4
  67. package/dist/core/official-catalog.js.map +1 -1
  68. package/dist/core/package-manager.d.ts +3 -0
  69. package/dist/core/package-manager.d.ts.map +1 -1
  70. package/dist/core/package-manager.js +11 -5
  71. package/dist/core/package-manager.js.map +1 -1
  72. package/dist/core/permission-mode-control.d.ts +27 -0
  73. package/dist/core/permission-mode-control.d.ts.map +1 -0
  74. package/dist/core/permission-mode-control.js +39 -0
  75. package/dist/core/permission-mode-control.js.map +1 -0
  76. package/dist/core/resource-loader.d.ts +4 -1
  77. package/dist/core/resource-loader.d.ts.map +1 -1
  78. package/dist/core/resource-loader.js +13 -5
  79. package/dist/core/resource-loader.js.map +1 -1
  80. package/dist/core/settings-manager.d.ts.map +1 -1
  81. package/dist/core/settings-manager.js.map +1 -1
  82. package/dist/core/slash-commands.d.ts.map +1 -1
  83. package/dist/core/slash-commands.js +0 -1
  84. package/dist/core/slash-commands.js.map +1 -1
  85. package/dist/core/timings.d.ts +1 -0
  86. package/dist/core/timings.d.ts.map +1 -1
  87. package/dist/core/timings.js +6 -1
  88. package/dist/core/timings.js.map +1 -1
  89. package/dist/core/tools/read.d.ts.map +1 -1
  90. package/dist/core/tools/read.js +14 -20
  91. package/dist/core/tools/read.js.map +1 -1
  92. package/dist/core/tools/render-utils.d.ts +2 -0
  93. package/dist/core/tools/render-utils.d.ts.map +1 -1
  94. package/dist/core/tools/render-utils.js +10 -0
  95. package/dist/core/tools/render-utils.js.map +1 -1
  96. package/dist/main.d.ts +8 -0
  97. package/dist/main.d.ts.map +1 -1
  98. package/dist/main.js +63 -16
  99. package/dist/main.js.map +1 -1
  100. package/dist/migrations.d.ts.map +1 -1
  101. package/dist/migrations.js +3 -0
  102. package/dist/migrations.js.map +1 -1
  103. package/dist/modes/interactive/components/assistant-message.d.ts +1 -0
  104. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  105. package/dist/modes/interactive/components/assistant-message.js +1 -0
  106. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  107. package/dist/modes/interactive/components/context-view.d.ts.map +1 -1
  108. package/dist/modes/interactive/components/context-view.js +3 -1
  109. package/dist/modes/interactive/components/context-view.js.map +1 -1
  110. package/dist/modes/interactive/components/plan-message.d.ts +17 -0
  111. package/dist/modes/interactive/components/plan-message.d.ts.map +1 -0
  112. package/dist/modes/interactive/components/plan-message.js +43 -0
  113. package/dist/modes/interactive/components/plan-message.js.map +1 -0
  114. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  115. package/dist/modes/interactive/components/settings-selector.js +1 -1
  116. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  117. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  118. package/dist/modes/interactive/components/tool-execution.js +3 -1
  119. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  120. package/dist/modes/interactive/components/usage-view.d.ts +4 -25
  121. package/dist/modes/interactive/components/usage-view.d.ts.map +1 -1
  122. package/dist/modes/interactive/components/usage-view.js +17 -69
  123. package/dist/modes/interactive/components/usage-view.js.map +1 -1
  124. package/dist/modes/interactive/components/user-message.d.ts +1 -0
  125. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  126. package/dist/modes/interactive/components/user-message.js +1 -0
  127. package/dist/modes/interactive/components/user-message.js.map +1 -1
  128. package/dist/modes/interactive/interactive-mode.d.ts +23 -6
  129. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  130. package/dist/modes/interactive/interactive-mode.js +267 -148
  131. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  132. package/dist/modes/interactive/smooth-streaming.d.ts +39 -6
  133. package/dist/modes/interactive/smooth-streaming.d.ts.map +1 -1
  134. package/dist/modes/interactive/smooth-streaming.js +160 -73
  135. package/dist/modes/interactive/smooth-streaming.js.map +1 -1
  136. package/dist/utils/clipboard-image.d.ts.map +1 -1
  137. package/dist/utils/clipboard-image.js +7 -3
  138. package/dist/utils/clipboard-image.js.map +1 -1
  139. package/docs/terminal-setup.md +13 -0
  140. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  141. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  142. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  143. package/examples/extensions/gondolin/package-lock.json +2 -2
  144. package/examples/extensions/gondolin/package.json +1 -1
  145. package/examples/extensions/sandbox/package-lock.json +2 -2
  146. package/examples/extensions/sandbox/package.json +1 -1
  147. package/examples/extensions/with-deps/package-lock.json +2 -2
  148. package/examples/extensions/with-deps/package.json +1 -1
  149. package/package.json +4 -4
@@ -1 +1 @@
1
- {"version":3,"file":"tool-execution.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-execution.ts"],"names":[],"mappings":"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","sourcesContent":["import { Box, type Component, Container, getCapabilities, Image, Spacer, Text, type TUI } from \"@ashx-j/lunr-tui\";\nimport type { ToolDefinition, ToolRenderContext } from \"../../../core/extensions/types.ts\";\nimport { createAllToolDefinitions, type ToolName } from \"../../../core/tools/index.ts\";\nimport { getTextOutput as getRenderedTextOutput, toolStatusDot } from \"../../../core/tools/render-utils.ts\";\nimport { convertToPng } from \"../../../utils/image-convert.ts\";\nimport { theme } from \"../theme/theme.ts\";\n\nexport interface ToolExecutionOptions {\n\tshowImages?: boolean;\n\timageWidthCells?: number;\n}\n\nexport class ToolExecutionComponent extends Container {\n\tprivate contentBox: Box;\n\tprivate contentText: Text;\n\tprivate selfRenderContainer: Container;\n\t// lunr: top spacer kept as a field so consecutive same-tool calls can be\n\t// grouped into one continuous background by zeroing it (setGroupContinuation).\n\tprivate topSpacer: Spacer;\n\tprivate callRendererComponent?: Component;\n\tprivate resultRendererComponent?: Component;\n\tprivate rendererState: any = {};\n\tprivate imageComponents: Image[] = [];\n\tprivate imageSpacers: Spacer[] = [];\n\tprivate toolName: string;\n\tprivate toolCallId: string;\n\tprivate args: any;\n\tprivate expanded = false;\n\tprivate showImages: boolean;\n\tprivate imageWidthCells: number;\n\tprivate isPartial = true;\n\tprivate toolDefinition?: ToolDefinition<any, any>;\n\tprivate builtInToolDefinition?: ToolDefinition<any, any>;\n\tprivate ui: TUI;\n\tprivate cwd: string;\n\tprivate executionStarted = false;\n\tprivate argsComplete = false;\n\tprivate result?: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tisError: boolean;\n\t\tdetails?: any;\n\t};\n\tprivate convertedImages: Map<number, { data: string; mimeType: string }> = new Map();\n\tprivate hideComponent = false;\n\n\tconstructor(\n\t\ttoolName: string,\n\t\ttoolCallId: string,\n\t\targs: any,\n\t\toptions: ToolExecutionOptions = {},\n\t\ttoolDefinition: ToolDefinition<any, any> | undefined,\n\t\tui: TUI,\n\t\tcwd: string,\n\t) {\n\t\tsuper();\n\t\tthis.toolName = toolName;\n\t\tthis.toolCallId = toolCallId;\n\t\tthis.args = args;\n\t\tthis.toolDefinition = toolDefinition;\n\t\tthis.builtInToolDefinition = createAllToolDefinitions(cwd)[toolName as ToolName];\n\t\tthis.showImages = options.showImages ?? true;\n\t\tthis.imageWidthCells = options.imageWidthCells ?? 60;\n\t\tthis.ui = ui;\n\t\tthis.cwd = cwd;\n\n\t\tthis.topSpacer = new Spacer(1);\n\t\tthis.addChild(this.topSpacer);\n\n\t\t// Always create all shell variants. contentBox is used for default renderer-based composition.\n\t\t// selfRenderContainer is used when the tool renders its own framing.\n\t\t// contentText is reserved for generic fallback rendering when no tool definition exists.\n\t\tthis.contentBox = new Box(1, 1, (text: string) => theme.bg(\"toolPendingBg\", text));\n\t\tthis.contentText = new Text(\"\", 1, 1, (text: string) => theme.bg(\"toolPendingBg\", text));\n\t\tthis.selfRenderContainer = new Container();\n\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tthis.addChild(this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox);\n\t\t} else {\n\t\t\tthis.addChild(this.contentText);\n\t\t}\n\n\t\tthis.updateDisplay();\n\t}\n\n\tprivate getCallRenderer(): ToolDefinition<any, any>[\"renderCall\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderCall;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderCall;\n\t\t}\n\t\treturn this.toolDefinition.renderCall ?? this.builtInToolDefinition.renderCall;\n\t}\n\n\tprivate getResultRenderer(): ToolDefinition<any, any>[\"renderResult\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderResult;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderResult;\n\t\t}\n\t\treturn this.toolDefinition.renderResult ?? this.builtInToolDefinition.renderResult;\n\t}\n\n\tprivate hasRendererDefinition(): boolean {\n\t\treturn this.builtInToolDefinition !== undefined || this.toolDefinition !== undefined;\n\t}\n\n\tprivate getRenderShell(): \"default\" | \"self\" {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderShell ?? \"default\";\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderShell ?? \"default\";\n\t\t}\n\t\treturn this.toolDefinition.renderShell ?? this.builtInToolDefinition.renderShell ?? \"default\";\n\t}\n\n\tprivate getRenderContext(lastComponent: Component | undefined): ToolRenderContext {\n\t\treturn {\n\t\t\targs: this.args,\n\t\t\ttoolCallId: this.toolCallId,\n\t\t\tinvalidate: () => {\n\t\t\t\tthis.invalidate();\n\t\t\t\tthis.ui.requestRender();\n\t\t\t},\n\t\t\trequestRender: () => {\n\t\t\t\tthis.ui.requestRender();\n\t\t\t},\n\t\t\tlastComponent,\n\t\t\tstate: this.rendererState,\n\t\t\tcwd: this.cwd,\n\t\t\texecutionStarted: this.executionStarted,\n\t\t\targsComplete: this.argsComplete,\n\t\t\tisPartial: this.isPartial,\n\t\t\texpanded: this.expanded,\n\t\t\tshowImages: this.showImages,\n\t\t\tisError: this.result?.isError ?? false,\n\t\t};\n\t}\n\n\tprivate getStatusDot(): string {\n\t\tconst state = this.isPartial ? \"pending\" : this.result?.isError ? \"error\" : \"success\";\n\t\treturn toolStatusDot(state, theme);\n\t}\n\n\tprivate createCallFallback(): Component {\n\t\treturn new Text(`${this.getStatusDot()} ${theme.fg(\"toolTitle\", theme.bold(this.toolName))}`, 0, 0);\n\t}\n\n\tprivate createResultFallback(): Component | undefined {\n\t\tconst output = this.getTextOutput();\n\t\tif (!output) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn new Text(theme.fg(\"toolOutput\", output), 0, 0);\n\t}\n\n\tupdateArgs(args: any): void {\n\t\tthis.args = args;\n\t\tthis.updateDisplay();\n\t}\n\n\tmarkExecutionStarted(): void {\n\t\tthis.executionStarted = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tsetArgsComplete(): void {\n\t\tthis.argsComplete = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tupdateResult(\n\t\tresult: {\n\t\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\t\tdetails?: any;\n\t\t\tisError: boolean;\n\t\t},\n\t\tisPartial = false,\n\t): void {\n\t\tthis.result = result;\n\t\tthis.isPartial = isPartial;\n\t\tthis.updateDisplay();\n\t\tthis.maybeConvertImagesForKitty();\n\t}\n\n\tprivate maybeConvertImagesForKitty(): void {\n\t\tconst caps = getCapabilities();\n\t\tif (caps.images !== \"kitty\") return;\n\t\tif (!this.result) return;\n\n\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\tconst img = imageBlocks[i];\n\t\t\tif (!img.data || !img.mimeType) continue;\n\t\t\tif (img.mimeType === \"image/png\") continue;\n\t\t\tif (this.convertedImages.has(i)) continue;\n\n\t\t\tconst index = i;\n\t\t\tconvertToPng(img.data, img.mimeType).then((converted) => {\n\t\t\t\tif (converted) {\n\t\t\t\t\tthis.convertedImages.set(index, converted);\n\t\t\t\t\tthis.updateDisplay();\n\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.expanded = expanded;\n\t\tthis.updateDisplay();\n\t}\n\n\t// lunr: consecutive same-tool grouping — exposes the tool name so the caller\n\t// can detect adjacency.\n\tgetToolName(): string {\n\t\treturn this.toolName;\n\t}\n\n\t// lunr: consecutive same-tool grouping — continuation calls hide the top\n\t// spacer so adjacent same-bg boxes read as one continuous background; each\n\t// call's content still renders normally inside its own box.\n\tsetGroupContinuation(on: boolean): void {\n\t\tthis.topSpacer.setLines(on ? 0 : 1);\n\t\tthis.invalidate();\n\t}\n\n\tsetShowImages(show: boolean): void {\n\t\tthis.showImages = show;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetImageWidthCells(width: number): void {\n\t\tthis.imageWidthCells = Math.max(1, Math.floor(width));\n\t\tthis.updateDisplay();\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tthis.updateDisplay();\n\t}\n\n\toverride render(width: number): string[] {\n\t\tif (this.hideComponent) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && this.getRenderShell() === \"self\") {\n\t\t\tconst contentLines = this.selfRenderContainer.render(width);\n\t\t\tif (contentLines.length === 0 && this.imageComponents.length === 0) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\tconst lines: string[] = [];\n\t\t\tif (contentLines.length > 0) {\n\t\t\t\tlines.push(\"\");\n\t\t\t\tlines.push(...contentLines);\n\t\t\t}\n\t\t\tfor (let i = 0; i < this.imageComponents.length; i++) {\n\t\t\t\tconst spacer = this.imageSpacers[i];\n\t\t\t\tif (spacer) {\n\t\t\t\t\tlines.push(...spacer.render(width));\n\t\t\t\t}\n\t\t\t\tconst imageComponent = this.imageComponents[i];\n\t\t\t\tif (imageComponent) {\n\t\t\t\t\tlines.push(...imageComponent.render(width));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn lines;\n\t\t}\n\n\t\treturn super.render(width);\n\t}\n\n\tprivate updateDisplay(): void {\n\t\tconst bgFn = this.isPartial\n\t\t\t? (text: string) => theme.bg(\"toolPendingBg\", text)\n\t\t\t: this.result?.isError\n\t\t\t\t? (text: string) => theme.bg(\"toolErrorBg\", text)\n\t\t\t\t: (text: string) => theme.bg(\"toolSuccessBg\", text);\n\n\t\tlet hasContent = false;\n\t\tthis.hideComponent = false;\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tconst renderContainer = this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox;\n\t\t\tif (renderContainer instanceof Box) {\n\t\t\t\trenderContainer.setBgFn(bgFn);\n\t\t\t}\n\t\t\trenderContainer.clear();\n\n\t\t\tconst callRenderer = this.getCallRenderer();\n\t\t\tif (!callRenderer) {\n\t\t\t\trenderContainer.addChild(this.createCallFallback());\n\t\t\t\thasContent = true;\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst component = callRenderer(this.args, theme, this.getRenderContext(this.callRendererComponent));\n\t\t\t\t\tthis.callRendererComponent = component;\n\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\thasContent = true;\n\t\t\t\t} catch {\n\t\t\t\t\tthis.callRendererComponent = undefined;\n\t\t\t\t\trenderContainer.addChild(this.createCallFallback());\n\t\t\t\t\thasContent = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.result) {\n\t\t\t\tconst resultRenderer = this.getResultRenderer();\n\t\t\t\tif (!resultRenderer) {\n\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\tif (component) {\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst component = resultRenderer(\n\t\t\t\t\t\t\t{ content: this.result.content as any, details: this.result.details },\n\t\t\t\t\t\t\t{ expanded: this.expanded, isPartial: this.isPartial },\n\t\t\t\t\t\t\ttheme,\n\t\t\t\t\t\t\tthis.getRenderContext(this.resultRendererComponent),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis.resultRendererComponent = component;\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tthis.resultRendererComponent = undefined;\n\t\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\t\tif (component) {\n\t\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.contentText.setCustomBgFn(bgFn);\n\t\t\tthis.contentText.setText(this.formatToolExecution());\n\t\t\thasContent = true;\n\t\t}\n\n\t\tfor (const img of this.imageComponents) {\n\t\t\tthis.removeChild(img);\n\t\t}\n\t\tthis.imageComponents = [];\n\t\tfor (const spacer of this.imageSpacers) {\n\t\t\tthis.removeChild(spacer);\n\t\t}\n\t\tthis.imageSpacers = [];\n\n\t\tif (this.result) {\n\t\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\t\tconst caps = getCapabilities();\n\t\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\t\tconst img = imageBlocks[i];\n\t\t\t\tif (caps.images && this.showImages && img.data && img.mimeType) {\n\t\t\t\t\tconst converted = this.convertedImages.get(i);\n\t\t\t\t\tconst imageData = converted?.data ?? img.data;\n\t\t\t\t\tconst imageMimeType = converted?.mimeType ?? img.mimeType;\n\t\t\t\t\tif (caps.images === \"kitty\" && imageMimeType !== \"image/png\") continue;\n\n\t\t\t\t\tconst spacer = new Spacer(1);\n\t\t\t\t\tthis.addChild(spacer);\n\t\t\t\t\tthis.imageSpacers.push(spacer);\n\t\t\t\t\tconst imageComponent = new Image(\n\t\t\t\t\t\timageData,\n\t\t\t\t\t\timageMimeType,\n\t\t\t\t\t\t{ fallbackColor: (s: string) => theme.fg(\"toolOutput\", s) },\n\t\t\t\t\t\t{ maxWidthCells: this.imageWidthCells },\n\t\t\t\t\t);\n\t\t\t\t\tthis.imageComponents.push(imageComponent);\n\t\t\t\t\tthis.addChild(imageComponent);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && !hasContent && this.imageComponents.length === 0) {\n\t\t\tthis.hideComponent = true;\n\t\t}\n\t}\n\n\tprivate getTextOutput(): string {\n\t\treturn getRenderedTextOutput(this.result, this.showImages);\n\t}\n\n\tprivate formatToolExecution(): string {\n\t\tlet text = `${this.getStatusDot()} ${theme.fg(\"toolTitle\", theme.bold(this.toolName))}`;\n\t\tconst content = JSON.stringify(this.args, null, 2);\n\t\tif (content) {\n\t\t\ttext += `\\n\\n${content}`;\n\t\t}\n\t\tconst output = this.getTextOutput();\n\t\tif (output) {\n\t\t\ttext += `\\n${output}`;\n\t\t}\n\t\treturn text;\n\t}\n}\n"]}
1
+ {"version":3,"file":"tool-execution.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-execution.ts"],"names":[],"mappings":"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","sourcesContent":["import { Box, type Component, Container, getCapabilities, Image, Spacer, Text, type TUI } from \"@ashx-j/lunr-tui\";\nimport type { ToolDefinition, ToolRenderContext } from \"../../../core/extensions/types.ts\";\nimport { createAllToolDefinitions, type ToolName } from \"../../../core/tools/index.ts\";\nimport { getTextOutput as getRenderedTextOutput, toolStatusDot } from \"../../../core/tools/render-utils.ts\";\nimport { convertToPng } from \"../../../utils/image-convert.ts\";\nimport { theme } from \"../theme/theme.ts\";\n\nexport interface ToolExecutionOptions {\n\tshowImages?: boolean;\n\timageWidthCells?: number;\n}\n\nexport class ToolExecutionComponent extends Container {\n\tprivate contentBox: Box;\n\tprivate contentText: Text;\n\tprivate selfRenderContainer: Container;\n\t// lunr: top spacer kept as a field so consecutive same-tool calls can be\n\t// grouped into one continuous background by zeroing it (setGroupContinuation).\n\tprivate topSpacer: Spacer;\n\tprivate callRendererComponent?: Component;\n\tprivate resultRendererComponent?: Component;\n\tprivate rendererState: any = {};\n\tprivate imageComponents: Image[] = [];\n\tprivate imageSpacers: Spacer[] = [];\n\tprivate toolName: string;\n\tprivate toolCallId: string;\n\tprivate args: any;\n\tprivate expanded = false;\n\tprivate showImages: boolean;\n\tprivate imageWidthCells: number;\n\tprivate isPartial = true;\n\tprivate toolDefinition?: ToolDefinition<any, any>;\n\tprivate builtInToolDefinition?: ToolDefinition<any, any>;\n\tprivate ui: TUI;\n\tprivate cwd: string;\n\tprivate executionStarted = false;\n\tprivate argsComplete = false;\n\tprivate result?: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tisError: boolean;\n\t\tdetails?: any;\n\t};\n\tprivate convertedImages: Map<number, { data: string; mimeType: string }> = new Map();\n\tprivate hideComponent = false;\n\n\tconstructor(\n\t\ttoolName: string,\n\t\ttoolCallId: string,\n\t\targs: any,\n\t\toptions: ToolExecutionOptions = {},\n\t\ttoolDefinition: ToolDefinition<any, any> | undefined,\n\t\tui: TUI,\n\t\tcwd: string,\n\t) {\n\t\tsuper();\n\t\tthis.toolName = toolName;\n\t\tthis.toolCallId = toolCallId;\n\t\tthis.args = args;\n\t\tthis.toolDefinition = toolDefinition;\n\t\tthis.builtInToolDefinition = createAllToolDefinitions(cwd)[toolName as ToolName];\n\t\tthis.showImages = options.showImages ?? true;\n\t\tthis.imageWidthCells = options.imageWidthCells ?? 60;\n\t\tthis.ui = ui;\n\t\tthis.cwd = cwd;\n\n\t\tthis.topSpacer = new Spacer(1);\n\t\tthis.addChild(this.topSpacer);\n\n\t\t// Always create all shell variants. contentBox is used for default renderer-based composition.\n\t\t// selfRenderContainer is used when the tool renders its own framing.\n\t\t// contentText is reserved for generic fallback rendering when no tool definition exists.\n\t\t// lunr: compact tool chrome — no vertical box pad. Consecutive same-tool\n\t\t// rows sit flush; mixed-tool neighbors stay one-line compact too.\n\t\tthis.contentBox = new Box(1, 0, (text: string) => theme.bg(\"toolPendingBg\", text));\n\t\tthis.contentText = new Text(\"\", 1, 1, (text: string) => theme.bg(\"toolPendingBg\", text));\n\t\tthis.selfRenderContainer = new Container();\n\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tthis.addChild(this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox);\n\t\t} else {\n\t\t\tthis.addChild(this.contentText);\n\t\t}\n\n\t\tthis.updateDisplay();\n\t}\n\n\tprivate getCallRenderer(): ToolDefinition<any, any>[\"renderCall\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderCall;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderCall;\n\t\t}\n\t\treturn this.toolDefinition.renderCall ?? this.builtInToolDefinition.renderCall;\n\t}\n\n\tprivate getResultRenderer(): ToolDefinition<any, any>[\"renderResult\"] | undefined {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderResult;\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderResult;\n\t\t}\n\t\treturn this.toolDefinition.renderResult ?? this.builtInToolDefinition.renderResult;\n\t}\n\n\tprivate hasRendererDefinition(): boolean {\n\t\treturn this.builtInToolDefinition !== undefined || this.toolDefinition !== undefined;\n\t}\n\n\tprivate getRenderShell(): \"default\" | \"self\" {\n\t\tif (!this.builtInToolDefinition) {\n\t\t\treturn this.toolDefinition?.renderShell ?? \"default\";\n\t\t}\n\t\tif (!this.toolDefinition) {\n\t\t\treturn this.builtInToolDefinition.renderShell ?? \"default\";\n\t\t}\n\t\treturn this.toolDefinition.renderShell ?? this.builtInToolDefinition.renderShell ?? \"default\";\n\t}\n\n\tprivate getRenderContext(lastComponent: Component | undefined): ToolRenderContext {\n\t\treturn {\n\t\t\targs: this.args,\n\t\t\ttoolCallId: this.toolCallId,\n\t\t\tinvalidate: () => {\n\t\t\t\tthis.invalidate();\n\t\t\t\tthis.ui.requestRender();\n\t\t\t},\n\t\t\trequestRender: () => {\n\t\t\t\tthis.ui.requestRender();\n\t\t\t},\n\t\t\tlastComponent,\n\t\t\tstate: this.rendererState,\n\t\t\tcwd: this.cwd,\n\t\t\texecutionStarted: this.executionStarted,\n\t\t\targsComplete: this.argsComplete,\n\t\t\tisPartial: this.isPartial,\n\t\t\texpanded: this.expanded,\n\t\t\tshowImages: this.showImages,\n\t\t\tisError: this.result?.isError ?? false,\n\t\t};\n\t}\n\n\tprivate getStatusDot(): string {\n\t\tconst state = this.isPartial ? \"pending\" : this.result?.isError ? \"error\" : \"success\";\n\t\treturn toolStatusDot(state, theme);\n\t}\n\n\tprivate createCallFallback(): Component {\n\t\treturn new Text(`${this.getStatusDot()} ${theme.fg(\"toolTitle\", theme.bold(this.toolName))}`, 0, 0);\n\t}\n\n\tprivate createResultFallback(): Component | undefined {\n\t\tconst output = this.getTextOutput();\n\t\tif (!output) {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn new Text(theme.fg(\"toolOutput\", output), 0, 0);\n\t}\n\n\tupdateArgs(args: any): void {\n\t\tthis.args = args;\n\t\tthis.updateDisplay();\n\t}\n\n\tmarkExecutionStarted(): void {\n\t\tthis.executionStarted = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tsetArgsComplete(): void {\n\t\tthis.argsComplete = true;\n\t\tthis.updateDisplay();\n\t\tthis.ui.requestRender();\n\t}\n\n\tupdateResult(\n\t\tresult: {\n\t\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\t\tdetails?: any;\n\t\t\tisError: boolean;\n\t\t},\n\t\tisPartial = false,\n\t): void {\n\t\tthis.result = result;\n\t\tthis.isPartial = isPartial;\n\t\tthis.updateDisplay();\n\t\tthis.maybeConvertImagesForKitty();\n\t}\n\n\tprivate maybeConvertImagesForKitty(): void {\n\t\tconst caps = getCapabilities();\n\t\tif (caps.images !== \"kitty\") return;\n\t\tif (!this.result) return;\n\n\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\tconst img = imageBlocks[i];\n\t\t\tif (!img.data || !img.mimeType) continue;\n\t\t\tif (img.mimeType === \"image/png\") continue;\n\t\t\tif (this.convertedImages.has(i)) continue;\n\n\t\t\tconst index = i;\n\t\t\tconvertToPng(img.data, img.mimeType).then((converted) => {\n\t\t\t\tif (converted) {\n\t\t\t\t\tthis.convertedImages.set(index, converted);\n\t\t\t\t\tthis.updateDisplay();\n\t\t\t\t\tthis.ui.requestRender();\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t}\n\n\tsetExpanded(expanded: boolean): void {\n\t\tthis.expanded = expanded;\n\t\tthis.updateDisplay();\n\t}\n\n\t// lunr: consecutive same-tool grouping — exposes the tool name so the caller\n\t// can detect adjacency.\n\tgetToolName(): string {\n\t\treturn this.toolName;\n\t}\n\n\t// lunr: consecutive same-tool grouping — continuation calls hide the top\n\t// spacer so adjacent same-bg boxes read as one continuous background; each\n\t// call's content still renders normally inside its own box.\n\tsetGroupContinuation(on: boolean): void {\n\t\tthis.topSpacer.setLines(on ? 0 : 1);\n\t\tthis.invalidate();\n\t}\n\n\tsetShowImages(show: boolean): void {\n\t\tthis.showImages = show;\n\t\tthis.updateDisplay();\n\t}\n\n\tsetImageWidthCells(width: number): void {\n\t\tthis.imageWidthCells = Math.max(1, Math.floor(width));\n\t\tthis.updateDisplay();\n\t}\n\n\toverride invalidate(): void {\n\t\tsuper.invalidate();\n\t\tthis.updateDisplay();\n\t}\n\n\toverride render(width: number): string[] {\n\t\tif (this.hideComponent) {\n\t\t\treturn [];\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && this.getRenderShell() === \"self\") {\n\t\t\tconst contentLines = this.selfRenderContainer.render(width);\n\t\t\tif (contentLines.length === 0 && this.imageComponents.length === 0) {\n\t\t\t\treturn [];\n\t\t\t}\n\n\t\t\tconst lines: string[] = [];\n\t\t\tif (contentLines.length > 0) {\n\t\t\t\tlines.push(\"\");\n\t\t\t\tlines.push(...contentLines);\n\t\t\t}\n\t\t\tfor (let i = 0; i < this.imageComponents.length; i++) {\n\t\t\t\tconst spacer = this.imageSpacers[i];\n\t\t\t\tif (spacer) {\n\t\t\t\t\tlines.push(...spacer.render(width));\n\t\t\t\t}\n\t\t\t\tconst imageComponent = this.imageComponents[i];\n\t\t\t\tif (imageComponent) {\n\t\t\t\t\tlines.push(...imageComponent.render(width));\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn lines;\n\t\t}\n\n\t\treturn super.render(width);\n\t}\n\n\tprivate updateDisplay(): void {\n\t\tconst bgFn = this.isPartial\n\t\t\t? (text: string) => theme.bg(\"toolPendingBg\", text)\n\t\t\t: this.result?.isError\n\t\t\t\t? (text: string) => theme.bg(\"toolErrorBg\", text)\n\t\t\t\t: (text: string) => theme.bg(\"toolSuccessBg\", text);\n\n\t\tlet hasContent = false;\n\t\tthis.hideComponent = false;\n\t\tif (this.hasRendererDefinition()) {\n\t\t\tconst renderContainer = this.getRenderShell() === \"self\" ? this.selfRenderContainer : this.contentBox;\n\t\t\tif (renderContainer instanceof Box) {\n\t\t\t\trenderContainer.setBgFn(bgFn);\n\t\t\t}\n\t\t\trenderContainer.clear();\n\n\t\t\tconst callRenderer = this.getCallRenderer();\n\t\t\tif (!callRenderer) {\n\t\t\t\trenderContainer.addChild(this.createCallFallback());\n\t\t\t\thasContent = true;\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tconst component = callRenderer(this.args, theme, this.getRenderContext(this.callRendererComponent));\n\t\t\t\t\tthis.callRendererComponent = component;\n\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\thasContent = true;\n\t\t\t\t} catch {\n\t\t\t\t\tthis.callRendererComponent = undefined;\n\t\t\t\t\trenderContainer.addChild(this.createCallFallback());\n\t\t\t\t\thasContent = true;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (this.result) {\n\t\t\t\tconst resultRenderer = this.getResultRenderer();\n\t\t\t\tif (!resultRenderer) {\n\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\tif (component) {\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst component = resultRenderer(\n\t\t\t\t\t\t\t{ content: this.result.content as any, details: this.result.details },\n\t\t\t\t\t\t\t{ expanded: this.expanded, isPartial: this.isPartial },\n\t\t\t\t\t\t\ttheme,\n\t\t\t\t\t\t\tthis.getRenderContext(this.resultRendererComponent),\n\t\t\t\t\t\t);\n\t\t\t\t\t\tthis.resultRendererComponent = component;\n\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tthis.resultRendererComponent = undefined;\n\t\t\t\t\t\tconst component = this.createResultFallback();\n\t\t\t\t\t\tif (component) {\n\t\t\t\t\t\t\trenderContainer.addChild(component);\n\t\t\t\t\t\t\thasContent = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tthis.contentText.setCustomBgFn(bgFn);\n\t\t\tthis.contentText.setText(this.formatToolExecution());\n\t\t\thasContent = true;\n\t\t}\n\n\t\tfor (const img of this.imageComponents) {\n\t\t\tthis.removeChild(img);\n\t\t}\n\t\tthis.imageComponents = [];\n\t\tfor (const spacer of this.imageSpacers) {\n\t\t\tthis.removeChild(spacer);\n\t\t}\n\t\tthis.imageSpacers = [];\n\n\t\tif (this.result) {\n\t\t\tconst imageBlocks = this.result.content.filter((c) => c.type === \"image\");\n\t\t\tconst caps = getCapabilities();\n\t\t\tfor (let i = 0; i < imageBlocks.length; i++) {\n\t\t\t\tconst img = imageBlocks[i];\n\t\t\t\tif (caps.images && this.showImages && img.data && img.mimeType) {\n\t\t\t\t\tconst converted = this.convertedImages.get(i);\n\t\t\t\t\tconst imageData = converted?.data ?? img.data;\n\t\t\t\t\tconst imageMimeType = converted?.mimeType ?? img.mimeType;\n\t\t\t\t\tif (caps.images === \"kitty\" && imageMimeType !== \"image/png\") continue;\n\n\t\t\t\t\tconst spacer = new Spacer(1);\n\t\t\t\t\tthis.addChild(spacer);\n\t\t\t\t\tthis.imageSpacers.push(spacer);\n\t\t\t\t\tconst imageComponent = new Image(\n\t\t\t\t\t\timageData,\n\t\t\t\t\t\timageMimeType,\n\t\t\t\t\t\t{ fallbackColor: (s: string) => theme.fg(\"toolOutput\", s) },\n\t\t\t\t\t\t{ maxWidthCells: this.imageWidthCells },\n\t\t\t\t\t);\n\t\t\t\t\tthis.imageComponents.push(imageComponent);\n\t\t\t\t\tthis.addChild(imageComponent);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif (this.hasRendererDefinition() && !hasContent && this.imageComponents.length === 0) {\n\t\t\tthis.hideComponent = true;\n\t\t}\n\t}\n\n\tprivate getTextOutput(): string {\n\t\treturn getRenderedTextOutput(this.result, this.showImages);\n\t}\n\n\tprivate formatToolExecution(): string {\n\t\tlet text = `${this.getStatusDot()} ${theme.fg(\"toolTitle\", theme.bold(this.toolName))}`;\n\t\tconst content = JSON.stringify(this.args, null, 2);\n\t\tif (content) {\n\t\t\ttext += `\\n\\n${content}`;\n\t\t}\n\t\tconst output = this.getTextOutput();\n\t\tif (output) {\n\t\t\ttext += `\\n${output}`;\n\t\t}\n\t\treturn text;\n\t}\n}\n"]}
@@ -1,14 +1,5 @@
1
- import type { UsageHistory } from "../../../core/usage-history.ts";
1
+ import type { ContextBreakdown } from "../../../core/context-breakdown.ts";
2
2
  import type { PlanUsage } from "../../../core/usage-service.ts";
3
- /** Per-model token totals (rendered by /token-usage). */
4
- export interface UsageSessionRow {
5
- model: string;
6
- input: number;
7
- output: number;
8
- cacheRead: number;
9
- cacheWrite: number;
10
- total: number;
11
- }
12
3
  /** Simple token totals (rendered by /usage). */
13
4
  export interface UsageTotals {
14
5
  input: number;
@@ -26,14 +17,8 @@ export interface UsageViewData {
26
17
  percent: number | null;
27
18
  } | undefined;
28
19
  plan: PlanUsage | undefined;
29
- /** 30-day history from core/usage-history.ts; omitted entirely when empty. */
30
- history?: UsageHistory;
31
- }
32
- export interface TokenUsageViewData {
33
- /** Per-model rows for the current session. */
34
- sessionRows: UsageSessionRow[];
35
- /** 30-day history from core/usage-history.ts (per-model rows only). */
36
- history?: UsageHistory;
20
+ /** Live session context split; omitted when the window is unknown. */
21
+ breakdown?: ContextBreakdown;
37
22
  }
38
23
  /** Traffic-light token for a 0–100 usage percent. Matches footer thresholds. */
39
24
  export declare function usageLevelColor(percent: number): "success" | "warning" | "error";
@@ -50,14 +35,8 @@ export declare function formatResetCountdown(resetsAt: number, now?: number): st
50
35
  export declare function renderThemedBox(headerText: string, content: string[], maxWidth: number): string[];
51
36
  /**
52
37
  * Render the /usage bordered box (moon theme conventions).
53
- * Simple totals only per-model rows live in /token-usage.
38
+ * Current session only: token totals, live context split, window bar, plan quota.
54
39
  * `maxWidth` is the available terminal width; content truncates to fit.
55
40
  */
56
41
  export declare function renderUsageBox(data: UsageViewData, maxWidth: number): string[];
57
- /**
58
- * Render the /token-usage bordered box: per-model token rows for the current
59
- * session and the last 30 days. Zero-token rows (aborted/errored messages)
60
- * are filtered out.
61
- */
62
- export declare function renderTokenUsageBox(data: TokenUsageViewData, maxWidth: number): string[];
63
42
  //# sourceMappingURL=usage-view.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"usage-view.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/usage-view.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,SAAS,EAAmB,MAAM,gCAAgC,CAAC;AAIjF,yDAAyD;AACzD,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACd;AAED,gDAAgD;AAChD,MAAM,WAAW,WAAW;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC7B,mFAAmF;IACnF,aAAa,EAAE,WAAW,GAAG,SAAS,CAAC;IACvC,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,SAAS,CAAC;IAC9F,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;IAC5B,8EAA8E;IAC9E,OAAO,CAAC,EAAE,YAAY,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IAClC,8CAA8C;IAC9C,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,uEAAuE;IACvE,OAAO,CAAC,EAAE,YAAY,CAAC;CACvB;AAID,kFAAgF;AAChF,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAIhF;AAWD,uEAAuE;AACvE,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOhD;AAED,2DAA2D;AAC3D,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,MAAM,CAevF;AAQD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAiBjG;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CA4E9E;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAoCxF","sourcesContent":["import { truncateToWidth, visibleWidth } from \"@ashx-j/lunr-tui\";\nimport type { UsageHistory } from \"../../../core/usage-history.ts\";\nimport type { PlanUsage, PlanUsageWindow } from \"../../../core/usage-service.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { formatTokens } from \"./footer.ts\";\n\n/** Per-model token totals (rendered by /token-usage). */\nexport interface UsageSessionRow {\n\tmodel: string;\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\ttotal: number;\n}\n\n/** Simple token totals (rendered by /usage). */\nexport interface UsageTotals {\n\tinput: number;\n\toutput: number;\n\tcacheRead?: number;\n\tcacheWrite?: number;\n\ttotal: number;\n}\n\nexport interface UsageViewData {\n\t/** Session-wide token totals (summed across models); omitted when no usage yet. */\n\tsessionTotals: UsageTotals | undefined;\n\tcontext: { tokens: number | null; contextWindow: number; percent: number | null } | undefined;\n\tplan: PlanUsage | undefined;\n\t/** 30-day history from core/usage-history.ts; omitted entirely when empty. */\n\thistory?: UsageHistory;\n}\n\nexport interface TokenUsageViewData {\n\t/** Per-model rows for the current session. */\n\tsessionRows: UsageSessionRow[];\n\t/** 30-day history from core/usage-history.ts (per-model rows only). */\n\thistory?: UsageHistory;\n}\n\nconst BAR_CELLS = 20;\n\n/** Traffic-light token for a 0–100 usage percent. Matches footer thresholds. */\nexport function usageLevelColor(percent: number): \"success\" | \"warning\" | \"error\" {\n\tif (percent > 90) return \"error\";\n\tif (percent > 70) return \"warning\";\n\treturn \"success\";\n}\n\n/** `cached X (Y%)` where Y = cacheRead / (input + cacheRead + cacheWrite). */\nfunction formatCachedSuffix(input: number, cacheRead: number, cacheWrite: number): string {\n\tif (cacheRead <= 0) return \"\";\n\tconst prompt = input + cacheRead + cacheWrite;\n\tif (prompt <= 0) return \"\";\n\tconst percent = Math.round((cacheRead / prompt) * 100);\n\treturn ` cached ${formatTokens(cacheRead)} (${percent}%)`;\n}\n\n/** 20-cell bar: filled cells green / yellow / red, empty cells dim. */\nexport function usageBar(percent: number): string {\n\tconst clamped = Math.max(0, Math.min(100, percent));\n\tconst filled = Math.round((clamped / 100) * BAR_CELLS);\n\tconst empty = BAR_CELLS - filled;\n\tconst fill = filled > 0 ? theme.fg(usageLevelColor(clamped), \"█\".repeat(filled)) : \"\";\n\tconst rest = empty > 0 ? theme.fg(\"dim\", \"░\".repeat(empty)) : \"\";\n\treturn fill + rest;\n}\n\n/** Compact countdown: `6d 21h`, `2h 51m`, `45m`, `now`. */\nexport function formatResetCountdown(resetsAt: number, now: number = Date.now()): string {\n\tconst diff = resetsAt - now;\n\tif (diff <= 0) return \"now\";\n\tconst minutes = Math.floor(diff / 60000);\n\tif (minutes >= 24 * 60) {\n\t\tconst days = Math.floor(minutes / (24 * 60));\n\t\tconst hours = Math.floor((minutes % (24 * 60)) / 60);\n\t\treturn hours > 0 ? `${days}d ${hours}h` : `${days}d`;\n\t}\n\tif (minutes >= 60) {\n\t\tconst hours = Math.floor(minutes / 60);\n\t\tconst rest = minutes % 60;\n\t\treturn rest > 0 ? `${hours}h ${rest}m` : `${hours}h`;\n\t}\n\treturn `${Math.max(1, minutes)}m`;\n}\n\nfunction planWindowLine(window: PlanUsageWindow, labelWidth: number): string {\n\tconst pct = `${Math.round(window.usedPercent)}% used`;\n\tconst reset = window.resetsAt !== undefined ? ` resets in ${formatResetCountdown(window.resetsAt)}` : \"\";\n\treturn ` ${window.label.padEnd(labelWidth)} ${usageBar(window.usedPercent)} ${pct}${reset}`;\n}\n\n/**\n * Shared bordered box chrome (monochrome, moon theme conventions) used by\n * /usage and /context. `headerText` includes its surrounding spaces (e.g.\n * \" Usage \"). `maxWidth` is the available terminal width; content truncates\n * to fit.\n */\nexport function renderThemedBox(headerText: string, content: string[], maxWidth: number): string[] {\n\t// Box width: widest content + `│ ` / ` │` chrome, capped by the terminal.\n\tconst contentWidth = Math.max(...content.map((line) => visibleWidth(line)));\n\tconst totalWidth = Math.max(24, Math.min(contentWidth + 4, Math.max(24, maxWidth)));\n\tconst innerWidth = totalWidth - 4;\n\n\tconst border = (text: string): string => theme.fg(\"border\", text);\n\tconst top = border(`╭${headerText}${\"─\".repeat(Math.max(0, totalWidth - 2 - headerText.length))}╮`);\n\tconst bottom = border(`╰${\"─\".repeat(totalWidth - 2)}╯`);\n\tconst lines = [top];\n\tfor (const rawLine of content) {\n\t\tconst line = rawLine.length > 0 ? truncateToWidth(rawLine, innerWidth, \"\") : \"\";\n\t\tconst padding = \" \".repeat(Math.max(0, innerWidth - visibleWidth(line)));\n\t\tlines.push(`${border(\"│ \")}${line}${padding}${border(\" │\")}`);\n\t}\n\tlines.push(bottom);\n\treturn lines;\n}\n\n/**\n * Render the /usage bordered box (moon theme conventions).\n * Simple totals only — per-model rows live in /token-usage.\n * `maxWidth` is the available terminal width; content truncates to fit.\n */\nexport function renderUsageBox(data: UsageViewData, maxWidth: number): string[] {\n\tconst content: string[] = [];\n\n\tif (data.sessionTotals && data.sessionTotals.total > 0) {\n\t\tcontent.push(\"Session usage\");\n\t\tcontent.push(\n\t\t\t` input ${formatTokens(data.sessionTotals.input)} output ${formatTokens(data.sessionTotals.output)} total ${formatTokens(data.sessionTotals.total)}${formatCachedSuffix(data.sessionTotals.input, data.sessionTotals.cacheRead ?? 0, data.sessionTotals.cacheWrite ?? 0)}`,\n\t\t);\n\t}\n\n\t// lunr: 30-day history section — aggregate total from session files plus an\n\t// estimated (chars/4) category breakdown. Per-model rows live in /token-usage.\n\tif (data.history && data.history.perModel.length > 0) {\n\t\tconst totals = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 };\n\t\tfor (const row of data.history.perModel) {\n\t\t\ttotals.input += row.input;\n\t\t\ttotals.output += row.output;\n\t\t\ttotals.cacheRead += row.cacheRead;\n\t\t\ttotals.cacheWrite += row.cacheWrite;\n\t\t\ttotals.total += row.total;\n\t\t}\n\t\tif (totals.total > 0) {\n\t\t\tif (content.length > 0) content.push(\"\");\n\t\t\tcontent.push(\"Last 30 days\");\n\t\t\tcontent.push(\n\t\t\t\t` input ${formatTokens(totals.input)} output ${formatTokens(totals.output)} total ${formatTokens(totals.total)}${formatCachedSuffix(totals.input, totals.cacheRead, totals.cacheWrite)}`,\n\t\t\t);\n\t\t}\n\t}\n\tif (data.history && data.history.categories.total > 0) {\n\t\tconst categories = data.history.categories;\n\t\tconst rows: { label: string; tokens: number }[] = [\n\t\t\t{ label: \"User messages\", tokens: categories.user },\n\t\t\t{ label: \"Assistant text\", tokens: categories.assistantText },\n\t\t\t{ label: \"Thinking\", tokens: categories.thinking },\n\t\t\t{ label: \"Tool calls\", tokens: categories.toolCalls },\n\t\t\t{ label: \"Tool results\", tokens: categories.toolResults },\n\t\t\t{ label: \"Summaries\", tokens: categories.summaries },\n\t\t].filter((row) => row.tokens > 0);\n\t\tif (rows.length > 0) {\n\t\t\tif (content.length > 0) content.push(\"\");\n\t\t\tcontent.push(theme.fg(\"dim\", \"Last 30 days by category (estimated, chars/4)\"));\n\t\t\tconst labelWidth = Math.max(...rows.map((row) => row.label.length));\n\t\t\tfor (const row of rows) {\n\t\t\t\tcontent.push(` ${row.label.padEnd(labelWidth)} ${formatTokens(row.tokens)}`);\n\t\t\t}\n\t\t\tif (!data.history.includesSystemPrompt) {\n\t\t\t\tcontent.push(theme.fg(\"dim\", \"(message categories only — system prompt/tools not stored per session)\"));\n\t\t\t}\n\t\t}\n\t}\n\n\tif (data.context) {\n\t\tconst pct = data.context.percent;\n\t\tconst tokens = data.context.tokens;\n\t\tif (content.length > 0) content.push(\"\");\n\t\tcontent.push(\"Context window\");\n\t\tconst pctText = pct == null ? \"?\" : `${Math.round(pct)}%`;\n\t\tconst tokensText = tokens == null ? \"?\" : formatTokens(tokens);\n\t\tcontent.push(\n\t\t\t` ${usageBar(pct ?? 0)} ${pctText} (${tokensText} / ${formatTokens(data.context.contextWindow)})`,\n\t\t);\n\t}\n\n\tif (data.plan && data.plan.windows.length > 0) {\n\t\tif (content.length > 0) content.push(\"\");\n\t\tcontent.push(data.plan.planLabel ? `Plan usage (${data.plan.planLabel})` : \"Plan usage\");\n\t\tconst labelWidth = Math.max(...data.plan.windows.map((window) => window.label.length));\n\t\tfor (const window of data.plan.windows) {\n\t\t\tcontent.push(planWindowLine(window, labelWidth));\n\t\t}\n\t}\n\n\tif (content.length === 0) content.push(\"No usage data yet.\");\n\n\treturn renderThemedBox(\" Usage \", content, maxWidth);\n}\n\n/**\n * Render the /token-usage bordered box: per-model token rows for the current\n * session and the last 30 days. Zero-token rows (aborted/errored messages)\n * are filtered out.\n */\nexport function renderTokenUsageBox(data: TokenUsageViewData, maxWidth: number): string[] {\n\tconst content: string[] = [];\n\n\tconst modelRow = (row: UsageSessionRow): string =>\n\t\t` ${row.model} input ${formatTokens(row.input)} output ${formatTokens(row.output)} ${formatTokens(row.total)}${formatCachedSuffix(row.input, row.cacheRead, row.cacheWrite)}`;\n\n\tconst sessionRows = data.sessionRows.filter((row) => row.total > 0);\n\tif (sessionRows.length > 0) {\n\t\tcontent.push(\"Session\");\n\t\tfor (const row of sessionRows) {\n\t\t\tcontent.push(modelRow(row));\n\t\t}\n\t}\n\n\t// lunr: 30-day per-model rows from session files on disk.\n\tconst historyRows = (data.history?.perModel ?? []).filter((row) => row.total > 0);\n\tif (historyRows.length > 0) {\n\t\tif (content.length > 0) content.push(\"\");\n\t\tcontent.push(\"Last 30 days\");\n\t\tfor (const row of historyRows) {\n\t\t\tcontent.push(\n\t\t\t\tmodelRow({\n\t\t\t\t\tmodel: row.model,\n\t\t\t\t\tinput: row.input,\n\t\t\t\t\toutput: row.output,\n\t\t\t\t\tcacheRead: row.cacheRead,\n\t\t\t\t\tcacheWrite: row.cacheWrite,\n\t\t\t\t\ttotal: row.total,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t}\n\n\tif (content.length === 0) content.push(\"No token usage yet.\");\n\n\treturn renderThemedBox(\" Token usage \", content, maxWidth);\n}\n"]}
1
+ {"version":3,"file":"usage-view.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/usage-view.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAC3E,OAAO,KAAK,EAAE,SAAS,EAAmB,MAAM,gCAAgC,CAAC;AAIjF,gDAAgD;AAChD,MAAM,WAAW,WAAW;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC7B,mFAAmF;IACnF,aAAa,EAAE,WAAW,GAAG,SAAS,CAAC;IACvC,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,aAAa,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,GAAG,SAAS,CAAC;IAC9F,IAAI,EAAE,SAAS,GAAG,SAAS,CAAC;IAC5B,sEAAsE;IACtE,SAAS,CAAC,EAAE,gBAAgB,CAAC;CAC7B;AAID,kFAAgF;AAChF,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAIhF;AAWD,uEAAuE;AACvE,wBAAgB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAOhD;AAED,2DAA2D;AAC3D,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,MAAM,CAevF;AAQD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CAiBjG;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,EAAE,CA2D9E","sourcesContent":["import { truncateToWidth, visibleWidth } from \"@ashx-j/lunr-tui\";\nimport type { ContextBreakdown } from \"../../../core/context-breakdown.ts\";\nimport type { PlanUsage, PlanUsageWindow } from \"../../../core/usage-service.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { formatTokens } from \"./footer.ts\";\n\n/** Simple token totals (rendered by /usage). */\nexport interface UsageTotals {\n\tinput: number;\n\toutput: number;\n\tcacheRead?: number;\n\tcacheWrite?: number;\n\ttotal: number;\n}\n\nexport interface UsageViewData {\n\t/** Session-wide token totals (summed across models); omitted when no usage yet. */\n\tsessionTotals: UsageTotals | undefined;\n\tcontext: { tokens: number | null; contextWindow: number; percent: number | null } | undefined;\n\tplan: PlanUsage | undefined;\n\t/** Live session context split; omitted when the window is unknown. */\n\tbreakdown?: ContextBreakdown;\n}\n\nconst BAR_CELLS = 20;\n\n/** Traffic-light token for a 0–100 usage percent. Matches footer thresholds. */\nexport function usageLevelColor(percent: number): \"success\" | \"warning\" | \"error\" {\n\tif (percent > 90) return \"error\";\n\tif (percent > 70) return \"warning\";\n\treturn \"success\";\n}\n\n/** `cached X (Y%)` where Y = cacheRead / (input + cacheRead + cacheWrite). */\nfunction formatCachedSuffix(input: number, cacheRead: number, cacheWrite: number): string {\n\tif (cacheRead <= 0) return \"\";\n\tconst prompt = input + cacheRead + cacheWrite;\n\tif (prompt <= 0) return \"\";\n\tconst percent = Math.round((cacheRead / prompt) * 100);\n\treturn ` cached ${formatTokens(cacheRead)} (${percent}%)`;\n}\n\n/** 20-cell bar: filled cells green / yellow / red, empty cells dim. */\nexport function usageBar(percent: number): string {\n\tconst clamped = Math.max(0, Math.min(100, percent));\n\tconst filled = Math.round((clamped / 100) * BAR_CELLS);\n\tconst empty = BAR_CELLS - filled;\n\tconst fill = filled > 0 ? theme.fg(usageLevelColor(clamped), \"█\".repeat(filled)) : \"\";\n\tconst rest = empty > 0 ? theme.fg(\"dim\", \"░\".repeat(empty)) : \"\";\n\treturn fill + rest;\n}\n\n/** Compact countdown: `6d 21h`, `2h 51m`, `45m`, `now`. */\nexport function formatResetCountdown(resetsAt: number, now: number = Date.now()): string {\n\tconst diff = resetsAt - now;\n\tif (diff <= 0) return \"now\";\n\tconst minutes = Math.floor(diff / 60000);\n\tif (minutes >= 24 * 60) {\n\t\tconst days = Math.floor(minutes / (24 * 60));\n\t\tconst hours = Math.floor((minutes % (24 * 60)) / 60);\n\t\treturn hours > 0 ? `${days}d ${hours}h` : `${days}d`;\n\t}\n\tif (minutes >= 60) {\n\t\tconst hours = Math.floor(minutes / 60);\n\t\tconst rest = minutes % 60;\n\t\treturn rest > 0 ? `${hours}h ${rest}m` : `${hours}h`;\n\t}\n\treturn `${Math.max(1, minutes)}m`;\n}\n\nfunction planWindowLine(window: PlanUsageWindow, labelWidth: number): string {\n\tconst pct = `${Math.round(window.usedPercent)}% used`;\n\tconst reset = window.resetsAt !== undefined ? ` resets in ${formatResetCountdown(window.resetsAt)}` : \"\";\n\treturn ` ${window.label.padEnd(labelWidth)} ${usageBar(window.usedPercent)} ${pct}${reset}`;\n}\n\n/**\n * Shared bordered box chrome (monochrome, moon theme conventions) used by\n * /usage and /context. `headerText` includes its surrounding spaces (e.g.\n * \" Usage \"). `maxWidth` is the available terminal width; content truncates\n * to fit.\n */\nexport function renderThemedBox(headerText: string, content: string[], maxWidth: number): string[] {\n\t// Box width: widest content + `│ ` / ` │` chrome, capped by the terminal.\n\tconst contentWidth = Math.max(...content.map((line) => visibleWidth(line)));\n\tconst totalWidth = Math.max(24, Math.min(contentWidth + 4, Math.max(24, maxWidth)));\n\tconst innerWidth = totalWidth - 4;\n\n\tconst border = (text: string): string => theme.fg(\"border\", text);\n\tconst top = border(`╭${headerText}${\"─\".repeat(Math.max(0, totalWidth - 2 - headerText.length))}╮`);\n\tconst bottom = border(`╰${\"─\".repeat(totalWidth - 2)}╯`);\n\tconst lines = [top];\n\tfor (const rawLine of content) {\n\t\tconst line = rawLine.length > 0 ? truncateToWidth(rawLine, innerWidth, \"\") : \"\";\n\t\tconst padding = \" \".repeat(Math.max(0, innerWidth - visibleWidth(line)));\n\t\tlines.push(`${border(\"│ \")}${line}${padding}${border(\" │\")}`);\n\t}\n\tlines.push(bottom);\n\treturn lines;\n}\n\n/**\n * Render the /usage bordered box (moon theme conventions).\n * Current session only: token totals, live context split, window bar, plan quota.\n * `maxWidth` is the available terminal width; content truncates to fit.\n */\nexport function renderUsageBox(data: UsageViewData, maxWidth: number): string[] {\n\tconst content: string[] = [];\n\n\tif (data.sessionTotals && data.sessionTotals.total > 0) {\n\t\tcontent.push(\"Session usage\");\n\t\tcontent.push(\n\t\t\t` input ${formatTokens(data.sessionTotals.input)} output ${formatTokens(data.sessionTotals.output)} total ${formatTokens(data.sessionTotals.total)}${formatCachedSuffix(data.sessionTotals.input, data.sessionTotals.cacheRead ?? 0, data.sessionTotals.cacheWrite ?? 0)}`,\n\t\t);\n\t}\n\n\tif (data.breakdown) {\n\t\tif (content.length > 0) content.push(\"\");\n\t\tcontent.push(\"Context\");\n\t\tcontent.push(theme.fg(\"dim\", \"Estimated (chars/4), current session only — actual token counts may differ.\"));\n\t\tconst rows: { label: string; tokens: number }[] = [\n\t\t\t{ label: \"System prompt\", tokens: data.breakdown.systemPrompt },\n\t\t\t...data.breakdown.contextFiles.map((file) => ({ label: file.label, tokens: file.tokens })),\n\t\t\t{ label: \"Skills\", tokens: data.breakdown.skills },\n\t\t\t{ label: \"Tool definitions\", tokens: data.breakdown.toolDefinitions },\n\t\t\t{ label: \"User messages\", tokens: data.breakdown.user },\n\t\t\t{ label: \"Assistant text\", tokens: data.breakdown.assistantText },\n\t\t\t{ label: \"Thinking\", tokens: data.breakdown.thinking },\n\t\t\t{ label: \"Tool calls\", tokens: data.breakdown.toolCalls },\n\t\t\t{ label: \"Tool results\", tokens: data.breakdown.toolResults },\n\t\t\t{ label: \"Summaries\", tokens: data.breakdown.summaries },\n\t\t\t{ label: \"Free\", tokens: data.breakdown.free },\n\t\t].filter((row) => row.tokens > 0);\n\t\tif (rows.length > 0) {\n\t\t\tconst labelWidth = Math.max(...rows.map((row) => row.label.length));\n\t\t\tfor (const row of rows) {\n\t\t\t\tcontent.push(` ${row.label.padEnd(labelWidth)} ${formatTokens(row.tokens)}`);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (data.context) {\n\t\tconst pct = data.context.percent;\n\t\tconst tokens = data.context.tokens;\n\t\tif (content.length > 0) content.push(\"\");\n\t\tcontent.push(\"Context window\");\n\t\tconst pctText = pct == null ? \"?\" : `${Math.round(pct)}%`;\n\t\tconst tokensText = tokens == null ? \"?\" : formatTokens(tokens);\n\t\tcontent.push(\n\t\t\t` ${usageBar(pct ?? 0)} ${pctText} (${tokensText} / ${formatTokens(data.context.contextWindow)})`,\n\t\t);\n\t}\n\n\tif (data.plan && data.plan.windows.length > 0) {\n\t\tif (content.length > 0) content.push(\"\");\n\t\tcontent.push(data.plan.planLabel ? `Plan usage (${data.plan.planLabel})` : \"Plan usage\");\n\t\tconst labelWidth = Math.max(...data.plan.windows.map((window) => window.label.length));\n\t\tfor (const window of data.plan.windows) {\n\t\t\tcontent.push(planWindowLine(window, labelWidth));\n\t\t}\n\t}\n\n\tif (content.length === 0) content.push(\"No usage data yet.\");\n\n\treturn renderThemedBox(\" Usage \", content, maxWidth);\n}\n"]}
@@ -77,7 +77,7 @@ export function renderThemedBox(headerText, content, maxWidth) {
77
77
  }
78
78
  /**
79
79
  * Render the /usage bordered box (moon theme conventions).
80
- * Simple totals only per-model rows live in /token-usage.
80
+ * Current session only: token totals, live context split, window bar, plan quota.
81
81
  * `maxWidth` is the available terminal width; content truncates to fit.
82
82
  */
83
83
  export function renderUsageBox(data, maxWidth) {
@@ -86,45 +86,29 @@ export function renderUsageBox(data, maxWidth) {
86
86
  content.push("Session usage");
87
87
  content.push(` input ${formatTokens(data.sessionTotals.input)} output ${formatTokens(data.sessionTotals.output)} total ${formatTokens(data.sessionTotals.total)}${formatCachedSuffix(data.sessionTotals.input, data.sessionTotals.cacheRead ?? 0, data.sessionTotals.cacheWrite ?? 0)}`);
88
88
  }
89
- // lunr: 30-day history section — aggregate total from session files plus an
90
- // estimated (chars/4) category breakdown. Per-model rows live in /token-usage.
91
- if (data.history && data.history.perModel.length > 0) {
92
- const totals = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 };
93
- for (const row of data.history.perModel) {
94
- totals.input += row.input;
95
- totals.output += row.output;
96
- totals.cacheRead += row.cacheRead;
97
- totals.cacheWrite += row.cacheWrite;
98
- totals.total += row.total;
99
- }
100
- if (totals.total > 0) {
101
- if (content.length > 0)
102
- content.push("");
103
- content.push("Last 30 days");
104
- content.push(` input ${formatTokens(totals.input)} output ${formatTokens(totals.output)} total ${formatTokens(totals.total)}${formatCachedSuffix(totals.input, totals.cacheRead, totals.cacheWrite)}`);
105
- }
106
- }
107
- if (data.history && data.history.categories.total > 0) {
108
- const categories = data.history.categories;
89
+ if (data.breakdown) {
90
+ if (content.length > 0)
91
+ content.push("");
92
+ content.push("Context");
93
+ content.push(theme.fg("dim", "Estimated (chars/4), current session only — actual token counts may differ."));
109
94
  const rows = [
110
- { label: "User messages", tokens: categories.user },
111
- { label: "Assistant text", tokens: categories.assistantText },
112
- { label: "Thinking", tokens: categories.thinking },
113
- { label: "Tool calls", tokens: categories.toolCalls },
114
- { label: "Tool results", tokens: categories.toolResults },
115
- { label: "Summaries", tokens: categories.summaries },
95
+ { label: "System prompt", tokens: data.breakdown.systemPrompt },
96
+ ...data.breakdown.contextFiles.map((file) => ({ label: file.label, tokens: file.tokens })),
97
+ { label: "Skills", tokens: data.breakdown.skills },
98
+ { label: "Tool definitions", tokens: data.breakdown.toolDefinitions },
99
+ { label: "User messages", tokens: data.breakdown.user },
100
+ { label: "Assistant text", tokens: data.breakdown.assistantText },
101
+ { label: "Thinking", tokens: data.breakdown.thinking },
102
+ { label: "Tool calls", tokens: data.breakdown.toolCalls },
103
+ { label: "Tool results", tokens: data.breakdown.toolResults },
104
+ { label: "Summaries", tokens: data.breakdown.summaries },
105
+ { label: "Free", tokens: data.breakdown.free },
116
106
  ].filter((row) => row.tokens > 0);
117
107
  if (rows.length > 0) {
118
- if (content.length > 0)
119
- content.push("");
120
- content.push(theme.fg("dim", "Last 30 days by category (estimated, chars/4)"));
121
108
  const labelWidth = Math.max(...rows.map((row) => row.label.length));
122
109
  for (const row of rows) {
123
110
  content.push(` ${row.label.padEnd(labelWidth)} ${formatTokens(row.tokens)}`);
124
111
  }
125
- if (!data.history.includesSystemPrompt) {
126
- content.push(theme.fg("dim", "(message categories only — system prompt/tools not stored per session)"));
127
- }
128
112
  }
129
113
  }
130
114
  if (data.context) {
@@ -150,40 +134,4 @@ export function renderUsageBox(data, maxWidth) {
150
134
  content.push("No usage data yet.");
151
135
  return renderThemedBox(" Usage ", content, maxWidth);
152
136
  }
153
- /**
154
- * Render the /token-usage bordered box: per-model token rows for the current
155
- * session and the last 30 days. Zero-token rows (aborted/errored messages)
156
- * are filtered out.
157
- */
158
- export function renderTokenUsageBox(data, maxWidth) {
159
- const content = [];
160
- const modelRow = (row) => ` ${row.model} input ${formatTokens(row.input)} output ${formatTokens(row.output)} ${formatTokens(row.total)}${formatCachedSuffix(row.input, row.cacheRead, row.cacheWrite)}`;
161
- const sessionRows = data.sessionRows.filter((row) => row.total > 0);
162
- if (sessionRows.length > 0) {
163
- content.push("Session");
164
- for (const row of sessionRows) {
165
- content.push(modelRow(row));
166
- }
167
- }
168
- // lunr: 30-day per-model rows from session files on disk.
169
- const historyRows = (data.history?.perModel ?? []).filter((row) => row.total > 0);
170
- if (historyRows.length > 0) {
171
- if (content.length > 0)
172
- content.push("");
173
- content.push("Last 30 days");
174
- for (const row of historyRows) {
175
- content.push(modelRow({
176
- model: row.model,
177
- input: row.input,
178
- output: row.output,
179
- cacheRead: row.cacheRead,
180
- cacheWrite: row.cacheWrite,
181
- total: row.total,
182
- }));
183
- }
184
- }
185
- if (content.length === 0)
186
- content.push("No token usage yet.");
187
- return renderThemedBox(" Token usage ", content, maxWidth);
188
- }
189
137
  //# sourceMappingURL=usage-view.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"usage-view.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/usage-view.ts"],"names":[],"mappings":"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","sourcesContent":["import { truncateToWidth, visibleWidth } from \"@ashx-j/lunr-tui\";\nimport type { UsageHistory } from \"../../../core/usage-history.ts\";\nimport type { PlanUsage, PlanUsageWindow } from \"../../../core/usage-service.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { formatTokens } from \"./footer.ts\";\n\n/** Per-model token totals (rendered by /token-usage). */\nexport interface UsageSessionRow {\n\tmodel: string;\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\ttotal: number;\n}\n\n/** Simple token totals (rendered by /usage). */\nexport interface UsageTotals {\n\tinput: number;\n\toutput: number;\n\tcacheRead?: number;\n\tcacheWrite?: number;\n\ttotal: number;\n}\n\nexport interface UsageViewData {\n\t/** Session-wide token totals (summed across models); omitted when no usage yet. */\n\tsessionTotals: UsageTotals | undefined;\n\tcontext: { tokens: number | null; contextWindow: number; percent: number | null } | undefined;\n\tplan: PlanUsage | undefined;\n\t/** 30-day history from core/usage-history.ts; omitted entirely when empty. */\n\thistory?: UsageHistory;\n}\n\nexport interface TokenUsageViewData {\n\t/** Per-model rows for the current session. */\n\tsessionRows: UsageSessionRow[];\n\t/** 30-day history from core/usage-history.ts (per-model rows only). */\n\thistory?: UsageHistory;\n}\n\nconst BAR_CELLS = 20;\n\n/** Traffic-light token for a 0–100 usage percent. Matches footer thresholds. */\nexport function usageLevelColor(percent: number): \"success\" | \"warning\" | \"error\" {\n\tif (percent > 90) return \"error\";\n\tif (percent > 70) return \"warning\";\n\treturn \"success\";\n}\n\n/** `cached X (Y%)` where Y = cacheRead / (input + cacheRead + cacheWrite). */\nfunction formatCachedSuffix(input: number, cacheRead: number, cacheWrite: number): string {\n\tif (cacheRead <= 0) return \"\";\n\tconst prompt = input + cacheRead + cacheWrite;\n\tif (prompt <= 0) return \"\";\n\tconst percent = Math.round((cacheRead / prompt) * 100);\n\treturn ` cached ${formatTokens(cacheRead)} (${percent}%)`;\n}\n\n/** 20-cell bar: filled cells green / yellow / red, empty cells dim. */\nexport function usageBar(percent: number): string {\n\tconst clamped = Math.max(0, Math.min(100, percent));\n\tconst filled = Math.round((clamped / 100) * BAR_CELLS);\n\tconst empty = BAR_CELLS - filled;\n\tconst fill = filled > 0 ? theme.fg(usageLevelColor(clamped), \"█\".repeat(filled)) : \"\";\n\tconst rest = empty > 0 ? theme.fg(\"dim\", \"░\".repeat(empty)) : \"\";\n\treturn fill + rest;\n}\n\n/** Compact countdown: `6d 21h`, `2h 51m`, `45m`, `now`. */\nexport function formatResetCountdown(resetsAt: number, now: number = Date.now()): string {\n\tconst diff = resetsAt - now;\n\tif (diff <= 0) return \"now\";\n\tconst minutes = Math.floor(diff / 60000);\n\tif (minutes >= 24 * 60) {\n\t\tconst days = Math.floor(minutes / (24 * 60));\n\t\tconst hours = Math.floor((minutes % (24 * 60)) / 60);\n\t\treturn hours > 0 ? `${days}d ${hours}h` : `${days}d`;\n\t}\n\tif (minutes >= 60) {\n\t\tconst hours = Math.floor(minutes / 60);\n\t\tconst rest = minutes % 60;\n\t\treturn rest > 0 ? `${hours}h ${rest}m` : `${hours}h`;\n\t}\n\treturn `${Math.max(1, minutes)}m`;\n}\n\nfunction planWindowLine(window: PlanUsageWindow, labelWidth: number): string {\n\tconst pct = `${Math.round(window.usedPercent)}% used`;\n\tconst reset = window.resetsAt !== undefined ? ` resets in ${formatResetCountdown(window.resetsAt)}` : \"\";\n\treturn ` ${window.label.padEnd(labelWidth)} ${usageBar(window.usedPercent)} ${pct}${reset}`;\n}\n\n/**\n * Shared bordered box chrome (monochrome, moon theme conventions) used by\n * /usage and /context. `headerText` includes its surrounding spaces (e.g.\n * \" Usage \"). `maxWidth` is the available terminal width; content truncates\n * to fit.\n */\nexport function renderThemedBox(headerText: string, content: string[], maxWidth: number): string[] {\n\t// Box width: widest content + `│ ` / ` │` chrome, capped by the terminal.\n\tconst contentWidth = Math.max(...content.map((line) => visibleWidth(line)));\n\tconst totalWidth = Math.max(24, Math.min(contentWidth + 4, Math.max(24, maxWidth)));\n\tconst innerWidth = totalWidth - 4;\n\n\tconst border = (text: string): string => theme.fg(\"border\", text);\n\tconst top = border(`╭${headerText}${\"─\".repeat(Math.max(0, totalWidth - 2 - headerText.length))}╮`);\n\tconst bottom = border(`╰${\"─\".repeat(totalWidth - 2)}╯`);\n\tconst lines = [top];\n\tfor (const rawLine of content) {\n\t\tconst line = rawLine.length > 0 ? truncateToWidth(rawLine, innerWidth, \"\") : \"\";\n\t\tconst padding = \" \".repeat(Math.max(0, innerWidth - visibleWidth(line)));\n\t\tlines.push(`${border(\"│ \")}${line}${padding}${border(\" │\")}`);\n\t}\n\tlines.push(bottom);\n\treturn lines;\n}\n\n/**\n * Render the /usage bordered box (moon theme conventions).\n * Simple totals only — per-model rows live in /token-usage.\n * `maxWidth` is the available terminal width; content truncates to fit.\n */\nexport function renderUsageBox(data: UsageViewData, maxWidth: number): string[] {\n\tconst content: string[] = [];\n\n\tif (data.sessionTotals && data.sessionTotals.total > 0) {\n\t\tcontent.push(\"Session usage\");\n\t\tcontent.push(\n\t\t\t` input ${formatTokens(data.sessionTotals.input)} output ${formatTokens(data.sessionTotals.output)} total ${formatTokens(data.sessionTotals.total)}${formatCachedSuffix(data.sessionTotals.input, data.sessionTotals.cacheRead ?? 0, data.sessionTotals.cacheWrite ?? 0)}`,\n\t\t);\n\t}\n\n\t// lunr: 30-day history section — aggregate total from session files plus an\n\t// estimated (chars/4) category breakdown. Per-model rows live in /token-usage.\n\tif (data.history && data.history.perModel.length > 0) {\n\t\tconst totals = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 };\n\t\tfor (const row of data.history.perModel) {\n\t\t\ttotals.input += row.input;\n\t\t\ttotals.output += row.output;\n\t\t\ttotals.cacheRead += row.cacheRead;\n\t\t\ttotals.cacheWrite += row.cacheWrite;\n\t\t\ttotals.total += row.total;\n\t\t}\n\t\tif (totals.total > 0) {\n\t\t\tif (content.length > 0) content.push(\"\");\n\t\t\tcontent.push(\"Last 30 days\");\n\t\t\tcontent.push(\n\t\t\t\t` input ${formatTokens(totals.input)} output ${formatTokens(totals.output)} total ${formatTokens(totals.total)}${formatCachedSuffix(totals.input, totals.cacheRead, totals.cacheWrite)}`,\n\t\t\t);\n\t\t}\n\t}\n\tif (data.history && data.history.categories.total > 0) {\n\t\tconst categories = data.history.categories;\n\t\tconst rows: { label: string; tokens: number }[] = [\n\t\t\t{ label: \"User messages\", tokens: categories.user },\n\t\t\t{ label: \"Assistant text\", tokens: categories.assistantText },\n\t\t\t{ label: \"Thinking\", tokens: categories.thinking },\n\t\t\t{ label: \"Tool calls\", tokens: categories.toolCalls },\n\t\t\t{ label: \"Tool results\", tokens: categories.toolResults },\n\t\t\t{ label: \"Summaries\", tokens: categories.summaries },\n\t\t].filter((row) => row.tokens > 0);\n\t\tif (rows.length > 0) {\n\t\t\tif (content.length > 0) content.push(\"\");\n\t\t\tcontent.push(theme.fg(\"dim\", \"Last 30 days by category (estimated, chars/4)\"));\n\t\t\tconst labelWidth = Math.max(...rows.map((row) => row.label.length));\n\t\t\tfor (const row of rows) {\n\t\t\t\tcontent.push(` ${row.label.padEnd(labelWidth)} ${formatTokens(row.tokens)}`);\n\t\t\t}\n\t\t\tif (!data.history.includesSystemPrompt) {\n\t\t\t\tcontent.push(theme.fg(\"dim\", \"(message categories only — system prompt/tools not stored per session)\"));\n\t\t\t}\n\t\t}\n\t}\n\n\tif (data.context) {\n\t\tconst pct = data.context.percent;\n\t\tconst tokens = data.context.tokens;\n\t\tif (content.length > 0) content.push(\"\");\n\t\tcontent.push(\"Context window\");\n\t\tconst pctText = pct == null ? \"?\" : `${Math.round(pct)}%`;\n\t\tconst tokensText = tokens == null ? \"?\" : formatTokens(tokens);\n\t\tcontent.push(\n\t\t\t` ${usageBar(pct ?? 0)} ${pctText} (${tokensText} / ${formatTokens(data.context.contextWindow)})`,\n\t\t);\n\t}\n\n\tif (data.plan && data.plan.windows.length > 0) {\n\t\tif (content.length > 0) content.push(\"\");\n\t\tcontent.push(data.plan.planLabel ? `Plan usage (${data.plan.planLabel})` : \"Plan usage\");\n\t\tconst labelWidth = Math.max(...data.plan.windows.map((window) => window.label.length));\n\t\tfor (const window of data.plan.windows) {\n\t\t\tcontent.push(planWindowLine(window, labelWidth));\n\t\t}\n\t}\n\n\tif (content.length === 0) content.push(\"No usage data yet.\");\n\n\treturn renderThemedBox(\" Usage \", content, maxWidth);\n}\n\n/**\n * Render the /token-usage bordered box: per-model token rows for the current\n * session and the last 30 days. Zero-token rows (aborted/errored messages)\n * are filtered out.\n */\nexport function renderTokenUsageBox(data: TokenUsageViewData, maxWidth: number): string[] {\n\tconst content: string[] = [];\n\n\tconst modelRow = (row: UsageSessionRow): string =>\n\t\t` ${row.model} input ${formatTokens(row.input)} output ${formatTokens(row.output)} ${formatTokens(row.total)}${formatCachedSuffix(row.input, row.cacheRead, row.cacheWrite)}`;\n\n\tconst sessionRows = data.sessionRows.filter((row) => row.total > 0);\n\tif (sessionRows.length > 0) {\n\t\tcontent.push(\"Session\");\n\t\tfor (const row of sessionRows) {\n\t\t\tcontent.push(modelRow(row));\n\t\t}\n\t}\n\n\t// lunr: 30-day per-model rows from session files on disk.\n\tconst historyRows = (data.history?.perModel ?? []).filter((row) => row.total > 0);\n\tif (historyRows.length > 0) {\n\t\tif (content.length > 0) content.push(\"\");\n\t\tcontent.push(\"Last 30 days\");\n\t\tfor (const row of historyRows) {\n\t\t\tcontent.push(\n\t\t\t\tmodelRow({\n\t\t\t\t\tmodel: row.model,\n\t\t\t\t\tinput: row.input,\n\t\t\t\t\toutput: row.output,\n\t\t\t\t\tcacheRead: row.cacheRead,\n\t\t\t\t\tcacheWrite: row.cacheWrite,\n\t\t\t\t\ttotal: row.total,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t}\n\n\tif (content.length === 0) content.push(\"No token usage yet.\");\n\n\treturn renderThemedBox(\" Token usage \", content, maxWidth);\n}\n"]}
1
+ {"version":3,"file":"usage-view.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/usage-view.ts"],"names":[],"mappings":"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","sourcesContent":["import { truncateToWidth, visibleWidth } from \"@ashx-j/lunr-tui\";\nimport type { ContextBreakdown } from \"../../../core/context-breakdown.ts\";\nimport type { PlanUsage, PlanUsageWindow } from \"../../../core/usage-service.ts\";\nimport { theme } from \"../theme/theme.ts\";\nimport { formatTokens } from \"./footer.ts\";\n\n/** Simple token totals (rendered by /usage). */\nexport interface UsageTotals {\n\tinput: number;\n\toutput: number;\n\tcacheRead?: number;\n\tcacheWrite?: number;\n\ttotal: number;\n}\n\nexport interface UsageViewData {\n\t/** Session-wide token totals (summed across models); omitted when no usage yet. */\n\tsessionTotals: UsageTotals | undefined;\n\tcontext: { tokens: number | null; contextWindow: number; percent: number | null } | undefined;\n\tplan: PlanUsage | undefined;\n\t/** Live session context split; omitted when the window is unknown. */\n\tbreakdown?: ContextBreakdown;\n}\n\nconst BAR_CELLS = 20;\n\n/** Traffic-light token for a 0–100 usage percent. Matches footer thresholds. */\nexport function usageLevelColor(percent: number): \"success\" | \"warning\" | \"error\" {\n\tif (percent > 90) return \"error\";\n\tif (percent > 70) return \"warning\";\n\treturn \"success\";\n}\n\n/** `cached X (Y%)` where Y = cacheRead / (input + cacheRead + cacheWrite). */\nfunction formatCachedSuffix(input: number, cacheRead: number, cacheWrite: number): string {\n\tif (cacheRead <= 0) return \"\";\n\tconst prompt = input + cacheRead + cacheWrite;\n\tif (prompt <= 0) return \"\";\n\tconst percent = Math.round((cacheRead / prompt) * 100);\n\treturn ` cached ${formatTokens(cacheRead)} (${percent}%)`;\n}\n\n/** 20-cell bar: filled cells green / yellow / red, empty cells dim. */\nexport function usageBar(percent: number): string {\n\tconst clamped = Math.max(0, Math.min(100, percent));\n\tconst filled = Math.round((clamped / 100) * BAR_CELLS);\n\tconst empty = BAR_CELLS - filled;\n\tconst fill = filled > 0 ? theme.fg(usageLevelColor(clamped), \"█\".repeat(filled)) : \"\";\n\tconst rest = empty > 0 ? theme.fg(\"dim\", \"░\".repeat(empty)) : \"\";\n\treturn fill + rest;\n}\n\n/** Compact countdown: `6d 21h`, `2h 51m`, `45m`, `now`. */\nexport function formatResetCountdown(resetsAt: number, now: number = Date.now()): string {\n\tconst diff = resetsAt - now;\n\tif (diff <= 0) return \"now\";\n\tconst minutes = Math.floor(diff / 60000);\n\tif (minutes >= 24 * 60) {\n\t\tconst days = Math.floor(minutes / (24 * 60));\n\t\tconst hours = Math.floor((minutes % (24 * 60)) / 60);\n\t\treturn hours > 0 ? `${days}d ${hours}h` : `${days}d`;\n\t}\n\tif (minutes >= 60) {\n\t\tconst hours = Math.floor(minutes / 60);\n\t\tconst rest = minutes % 60;\n\t\treturn rest > 0 ? `${hours}h ${rest}m` : `${hours}h`;\n\t}\n\treturn `${Math.max(1, minutes)}m`;\n}\n\nfunction planWindowLine(window: PlanUsageWindow, labelWidth: number): string {\n\tconst pct = `${Math.round(window.usedPercent)}% used`;\n\tconst reset = window.resetsAt !== undefined ? ` resets in ${formatResetCountdown(window.resetsAt)}` : \"\";\n\treturn ` ${window.label.padEnd(labelWidth)} ${usageBar(window.usedPercent)} ${pct}${reset}`;\n}\n\n/**\n * Shared bordered box chrome (monochrome, moon theme conventions) used by\n * /usage and /context. `headerText` includes its surrounding spaces (e.g.\n * \" Usage \"). `maxWidth` is the available terminal width; content truncates\n * to fit.\n */\nexport function renderThemedBox(headerText: string, content: string[], maxWidth: number): string[] {\n\t// Box width: widest content + `│ ` / ` │` chrome, capped by the terminal.\n\tconst contentWidth = Math.max(...content.map((line) => visibleWidth(line)));\n\tconst totalWidth = Math.max(24, Math.min(contentWidth + 4, Math.max(24, maxWidth)));\n\tconst innerWidth = totalWidth - 4;\n\n\tconst border = (text: string): string => theme.fg(\"border\", text);\n\tconst top = border(`╭${headerText}${\"─\".repeat(Math.max(0, totalWidth - 2 - headerText.length))}╮`);\n\tconst bottom = border(`╰${\"─\".repeat(totalWidth - 2)}╯`);\n\tconst lines = [top];\n\tfor (const rawLine of content) {\n\t\tconst line = rawLine.length > 0 ? truncateToWidth(rawLine, innerWidth, \"\") : \"\";\n\t\tconst padding = \" \".repeat(Math.max(0, innerWidth - visibleWidth(line)));\n\t\tlines.push(`${border(\"│ \")}${line}${padding}${border(\" │\")}`);\n\t}\n\tlines.push(bottom);\n\treturn lines;\n}\n\n/**\n * Render the /usage bordered box (moon theme conventions).\n * Current session only: token totals, live context split, window bar, plan quota.\n * `maxWidth` is the available terminal width; content truncates to fit.\n */\nexport function renderUsageBox(data: UsageViewData, maxWidth: number): string[] {\n\tconst content: string[] = [];\n\n\tif (data.sessionTotals && data.sessionTotals.total > 0) {\n\t\tcontent.push(\"Session usage\");\n\t\tcontent.push(\n\t\t\t` input ${formatTokens(data.sessionTotals.input)} output ${formatTokens(data.sessionTotals.output)} total ${formatTokens(data.sessionTotals.total)}${formatCachedSuffix(data.sessionTotals.input, data.sessionTotals.cacheRead ?? 0, data.sessionTotals.cacheWrite ?? 0)}`,\n\t\t);\n\t}\n\n\tif (data.breakdown) {\n\t\tif (content.length > 0) content.push(\"\");\n\t\tcontent.push(\"Context\");\n\t\tcontent.push(theme.fg(\"dim\", \"Estimated (chars/4), current session only — actual token counts may differ.\"));\n\t\tconst rows: { label: string; tokens: number }[] = [\n\t\t\t{ label: \"System prompt\", tokens: data.breakdown.systemPrompt },\n\t\t\t...data.breakdown.contextFiles.map((file) => ({ label: file.label, tokens: file.tokens })),\n\t\t\t{ label: \"Skills\", tokens: data.breakdown.skills },\n\t\t\t{ label: \"Tool definitions\", tokens: data.breakdown.toolDefinitions },\n\t\t\t{ label: \"User messages\", tokens: data.breakdown.user },\n\t\t\t{ label: \"Assistant text\", tokens: data.breakdown.assistantText },\n\t\t\t{ label: \"Thinking\", tokens: data.breakdown.thinking },\n\t\t\t{ label: \"Tool calls\", tokens: data.breakdown.toolCalls },\n\t\t\t{ label: \"Tool results\", tokens: data.breakdown.toolResults },\n\t\t\t{ label: \"Summaries\", tokens: data.breakdown.summaries },\n\t\t\t{ label: \"Free\", tokens: data.breakdown.free },\n\t\t].filter((row) => row.tokens > 0);\n\t\tif (rows.length > 0) {\n\t\t\tconst labelWidth = Math.max(...rows.map((row) => row.label.length));\n\t\t\tfor (const row of rows) {\n\t\t\t\tcontent.push(` ${row.label.padEnd(labelWidth)} ${formatTokens(row.tokens)}`);\n\t\t\t}\n\t\t}\n\t}\n\n\tif (data.context) {\n\t\tconst pct = data.context.percent;\n\t\tconst tokens = data.context.tokens;\n\t\tif (content.length > 0) content.push(\"\");\n\t\tcontent.push(\"Context window\");\n\t\tconst pctText = pct == null ? \"?\" : `${Math.round(pct)}%`;\n\t\tconst tokensText = tokens == null ? \"?\" : formatTokens(tokens);\n\t\tcontent.push(\n\t\t\t` ${usageBar(pct ?? 0)} ${pctText} (${tokensText} / ${formatTokens(data.context.contextWindow)})`,\n\t\t);\n\t}\n\n\tif (data.plan && data.plan.windows.length > 0) {\n\t\tif (content.length > 0) content.push(\"\");\n\t\tcontent.push(data.plan.planLabel ? `Plan usage (${data.plan.planLabel})` : \"Plan usage\");\n\t\tconst labelWidth = Math.max(...data.plan.windows.map((window) => window.label.length));\n\t\tfor (const window of data.plan.windows) {\n\t\t\tcontent.push(planWindowLine(window, labelWidth));\n\t\t}\n\t}\n\n\tif (content.length === 0) content.push(\"No usage data yet.\");\n\n\treturn renderThemedBox(\" Usage \", content, maxWidth);\n}\n"]}
@@ -3,6 +3,7 @@ import { Container, type MarkdownTheme } from "@ashx-j/lunr-tui";
3
3
  * Component that renders a user message
4
4
  */
5
5
  export declare class UserMessageComponent extends Container {
6
+ selectable: boolean;
6
7
  private text;
7
8
  private markdownTheme;
8
9
  private outputPad;
@@ -1 +1 @@
1
- {"version":3,"file":"user-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/user-message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,SAAS,EAAY,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAOtF;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;IAClD,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,SAAS,CAAS;IAG1B,OAAO,CAAC,UAAU,CAAU;IAE5B,YAAY,IAAI,EAAE,MAAM,EAAE,aAAa,GAAE,aAAkC,EAAE,SAAS,SAAI,EAAE,UAAU,UAAQ,EAO7G;IAED,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAGlC;IAED,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAEpC;IAED,OAAO,CAAC,OAAO;IAqBN,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAoBvC;CACD","sourcesContent":["import { Box, Container, Markdown, type MarkdownTheme } from \"@ashx-j/lunr-tui\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.ts\";\n\nconst OSC133_ZONE_START = \"\\x1b]133;A\\x07\";\nconst OSC133_ZONE_END = \"\\x1b]133;B\\x07\";\nconst OSC133_ZONE_FINAL = \"\\x1b]133;C\\x07\";\n\n/**\n * Component that renders a user message\n */\nexport class UserMessageComponent extends Container {\n\tprivate text: string;\n\tprivate markdownTheme: MarkdownTheme;\n\tprivate outputPad: number;\n\t// lunr: gutter rail — prefix rendered lines with a dim │ (last line ╰ when this\n\t// component closes a turn; user messages open the rail so all lines use │).\n\tprivate gutterRail: boolean;\n\n\tconstructor(text: string, markdownTheme: MarkdownTheme = getMarkdownTheme(), outputPad = 1, gutterRail = false) {\n\t\tsuper();\n\t\tthis.text = text;\n\t\tthis.markdownTheme = markdownTheme;\n\t\tthis.outputPad = outputPad;\n\t\tthis.gutterRail = gutterRail;\n\t\tthis.rebuild();\n\t}\n\n\tsetOutputPad(padding: number): void {\n\t\tthis.outputPad = padding;\n\t\tthis.rebuild();\n\t}\n\n\tsetGutterRail(enabled: boolean): void {\n\t\tthis.gutterRail = enabled;\n\t}\n\n\tprivate rebuild(): void {\n\t\tthis.clear();\n\t\tconst contentBox = new Box(this.outputPad, 1, (content: string) => theme.bg(\"userMessageBg\", content));\n\t\t// lunr: leading ● marks the first line of a user message. Kept uncolored in the\n\t\t// markdown source so the message's own text color applies (white in moon theme);\n\t\t// embedding ANSI here would strip the text color from the rest of the paragraph.\n\t\tcontentBox.addChild(\n\t\t\tnew Markdown(\n\t\t\t\t`● ${this.text}`,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tthis.markdownTheme,\n\t\t\t\t{\n\t\t\t\t\tcolor: (content: string) => theme.fg(\"userMessageText\", content),\n\t\t\t\t},\n\t\t\t\t{ preserveOrderedListMarkers: true, preserveBackslashEscapes: true },\n\t\t\t),\n\t\t);\n\t\tthis.addChild(contentBox);\n\t}\n\n\toverride render(width: number): string[] {\n\t\t// lunr: gutter rail — render content at width-2 and prefix each line with a\n\t\t// dim │ so a thin rail runs down the left of the user message.\n\t\tconst railEnabled = this.gutterRail;\n\t\tconst contentWidth = railEnabled ? Math.max(1, width - 2) : width;\n\t\tconst lines = super.render(contentWidth);\n\t\tif (lines.length === 0) {\n\t\t\treturn lines;\n\t\t}\n\n\t\tlines[0] = OSC133_ZONE_START + lines[0];\n\t\tlines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n\n\t\tif (railEnabled) {\n\t\t\tconst rail = theme.fg(\"dim\", \"│ \");\n\t\t\tfor (let i = 0; i < lines.length; i++) {\n\t\t\t\tlines[i] = rail + lines[i];\n\t\t\t}\n\t\t}\n\t\treturn lines;\n\t}\n}\n"]}
1
+ {"version":3,"file":"user-message.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/user-message.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,SAAS,EAAY,KAAK,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAOtF;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,SAAS;IAClD,UAAU,UAAQ;IAClB,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,SAAS,CAAS;IAG1B,OAAO,CAAC,UAAU,CAAU;IAE5B,YAAY,IAAI,EAAE,MAAM,EAAE,aAAa,GAAE,aAAkC,EAAE,SAAS,SAAI,EAAE,UAAU,UAAQ,EAO7G;IAED,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAGlC;IAED,aAAa,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAEpC;IAED,OAAO,CAAC,OAAO;IAqBN,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAoBvC;CACD","sourcesContent":["import { Box, Container, Markdown, type MarkdownTheme } from \"@ashx-j/lunr-tui\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.ts\";\n\nconst OSC133_ZONE_START = \"\\x1b]133;A\\x07\";\nconst OSC133_ZONE_END = \"\\x1b]133;B\\x07\";\nconst OSC133_ZONE_FINAL = \"\\x1b]133;C\\x07\";\n\n/**\n * Component that renders a user message\n */\nexport class UserMessageComponent extends Container {\n\tselectable = true;\n\tprivate text: string;\n\tprivate markdownTheme: MarkdownTheme;\n\tprivate outputPad: number;\n\t// lunr: gutter rail — prefix rendered lines with a dim │ (last line ╰ when this\n\t// component closes a turn; user messages open the rail so all lines use │).\n\tprivate gutterRail: boolean;\n\n\tconstructor(text: string, markdownTheme: MarkdownTheme = getMarkdownTheme(), outputPad = 1, gutterRail = false) {\n\t\tsuper();\n\t\tthis.text = text;\n\t\tthis.markdownTheme = markdownTheme;\n\t\tthis.outputPad = outputPad;\n\t\tthis.gutterRail = gutterRail;\n\t\tthis.rebuild();\n\t}\n\n\tsetOutputPad(padding: number): void {\n\t\tthis.outputPad = padding;\n\t\tthis.rebuild();\n\t}\n\n\tsetGutterRail(enabled: boolean): void {\n\t\tthis.gutterRail = enabled;\n\t}\n\n\tprivate rebuild(): void {\n\t\tthis.clear();\n\t\tconst contentBox = new Box(this.outputPad, 1, (content: string) => theme.bg(\"userMessageBg\", content));\n\t\t// lunr: leading ● marks the first line of a user message. Kept uncolored in the\n\t\t// markdown source so the message's own text color applies (white in moon theme);\n\t\t// embedding ANSI here would strip the text color from the rest of the paragraph.\n\t\tcontentBox.addChild(\n\t\t\tnew Markdown(\n\t\t\t\t`● ${this.text}`,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tthis.markdownTheme,\n\t\t\t\t{\n\t\t\t\t\tcolor: (content: string) => theme.fg(\"userMessageText\", content),\n\t\t\t\t},\n\t\t\t\t{ preserveOrderedListMarkers: true, preserveBackslashEscapes: true },\n\t\t\t),\n\t\t);\n\t\tthis.addChild(contentBox);\n\t}\n\n\toverride render(width: number): string[] {\n\t\t// lunr: gutter rail — render content at width-2 and prefix each line with a\n\t\t// dim │ so a thin rail runs down the left of the user message.\n\t\tconst railEnabled = this.gutterRail;\n\t\tconst contentWidth = railEnabled ? Math.max(1, width - 2) : width;\n\t\tconst lines = super.render(contentWidth);\n\t\tif (lines.length === 0) {\n\t\t\treturn lines;\n\t\t}\n\n\t\tlines[0] = OSC133_ZONE_START + lines[0];\n\t\tlines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n\n\t\tif (railEnabled) {\n\t\t\tconst rail = theme.fg(\"dim\", \"│ \");\n\t\t\tfor (let i = 0; i < lines.length; i++) {\n\t\t\t\tlines[i] = rail + lines[i];\n\t\t\t}\n\t\t}\n\t\treturn lines;\n\t}\n}\n"]}
@@ -7,6 +7,7 @@ const OSC133_ZONE_FINAL = "\x1b]133;C\x07";
7
7
  * Component that renders a user message
8
8
  */
9
9
  export class UserMessageComponent extends Container {
10
+ selectable = true;
10
11
  text;
11
12
  markdownTheme;
12
13
  outputPad;
@@ -1 +1 @@
1
- {"version":3,"file":"user-message.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/user-message.ts"],"names":[],"mappings":"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","sourcesContent":["import { Box, Container, Markdown, type MarkdownTheme } from \"@ashx-j/lunr-tui\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.ts\";\n\nconst OSC133_ZONE_START = \"\\x1b]133;A\\x07\";\nconst OSC133_ZONE_END = \"\\x1b]133;B\\x07\";\nconst OSC133_ZONE_FINAL = \"\\x1b]133;C\\x07\";\n\n/**\n * Component that renders a user message\n */\nexport class UserMessageComponent extends Container {\n\tprivate text: string;\n\tprivate markdownTheme: MarkdownTheme;\n\tprivate outputPad: number;\n\t// lunr: gutter rail — prefix rendered lines with a dim │ (last line ╰ when this\n\t// component closes a turn; user messages open the rail so all lines use │).\n\tprivate gutterRail: boolean;\n\n\tconstructor(text: string, markdownTheme: MarkdownTheme = getMarkdownTheme(), outputPad = 1, gutterRail = false) {\n\t\tsuper();\n\t\tthis.text = text;\n\t\tthis.markdownTheme = markdownTheme;\n\t\tthis.outputPad = outputPad;\n\t\tthis.gutterRail = gutterRail;\n\t\tthis.rebuild();\n\t}\n\n\tsetOutputPad(padding: number): void {\n\t\tthis.outputPad = padding;\n\t\tthis.rebuild();\n\t}\n\n\tsetGutterRail(enabled: boolean): void {\n\t\tthis.gutterRail = enabled;\n\t}\n\n\tprivate rebuild(): void {\n\t\tthis.clear();\n\t\tconst contentBox = new Box(this.outputPad, 1, (content: string) => theme.bg(\"userMessageBg\", content));\n\t\t// lunr: leading ● marks the first line of a user message. Kept uncolored in the\n\t\t// markdown source so the message's own text color applies (white in moon theme);\n\t\t// embedding ANSI here would strip the text color from the rest of the paragraph.\n\t\tcontentBox.addChild(\n\t\t\tnew Markdown(\n\t\t\t\t`● ${this.text}`,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tthis.markdownTheme,\n\t\t\t\t{\n\t\t\t\t\tcolor: (content: string) => theme.fg(\"userMessageText\", content),\n\t\t\t\t},\n\t\t\t\t{ preserveOrderedListMarkers: true, preserveBackslashEscapes: true },\n\t\t\t),\n\t\t);\n\t\tthis.addChild(contentBox);\n\t}\n\n\toverride render(width: number): string[] {\n\t\t// lunr: gutter rail — render content at width-2 and prefix each line with a\n\t\t// dim │ so a thin rail runs down the left of the user message.\n\t\tconst railEnabled = this.gutterRail;\n\t\tconst contentWidth = railEnabled ? Math.max(1, width - 2) : width;\n\t\tconst lines = super.render(contentWidth);\n\t\tif (lines.length === 0) {\n\t\t\treturn lines;\n\t\t}\n\n\t\tlines[0] = OSC133_ZONE_START + lines[0];\n\t\tlines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n\n\t\tif (railEnabled) {\n\t\t\tconst rail = theme.fg(\"dim\", \"│ \");\n\t\t\tfor (let i = 0; i < lines.length; i++) {\n\t\t\t\tlines[i] = rail + lines[i];\n\t\t\t}\n\t\t}\n\t\treturn lines;\n\t}\n}\n"]}
1
+ {"version":3,"file":"user-message.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/user-message.ts"],"names":[],"mappings":"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","sourcesContent":["import { Box, Container, Markdown, type MarkdownTheme } from \"@ashx-j/lunr-tui\";\nimport { getMarkdownTheme, theme } from \"../theme/theme.ts\";\n\nconst OSC133_ZONE_START = \"\\x1b]133;A\\x07\";\nconst OSC133_ZONE_END = \"\\x1b]133;B\\x07\";\nconst OSC133_ZONE_FINAL = \"\\x1b]133;C\\x07\";\n\n/**\n * Component that renders a user message\n */\nexport class UserMessageComponent extends Container {\n\tselectable = true;\n\tprivate text: string;\n\tprivate markdownTheme: MarkdownTheme;\n\tprivate outputPad: number;\n\t// lunr: gutter rail — prefix rendered lines with a dim │ (last line ╰ when this\n\t// component closes a turn; user messages open the rail so all lines use │).\n\tprivate gutterRail: boolean;\n\n\tconstructor(text: string, markdownTheme: MarkdownTheme = getMarkdownTheme(), outputPad = 1, gutterRail = false) {\n\t\tsuper();\n\t\tthis.text = text;\n\t\tthis.markdownTheme = markdownTheme;\n\t\tthis.outputPad = outputPad;\n\t\tthis.gutterRail = gutterRail;\n\t\tthis.rebuild();\n\t}\n\n\tsetOutputPad(padding: number): void {\n\t\tthis.outputPad = padding;\n\t\tthis.rebuild();\n\t}\n\n\tsetGutterRail(enabled: boolean): void {\n\t\tthis.gutterRail = enabled;\n\t}\n\n\tprivate rebuild(): void {\n\t\tthis.clear();\n\t\tconst contentBox = new Box(this.outputPad, 1, (content: string) => theme.bg(\"userMessageBg\", content));\n\t\t// lunr: leading ● marks the first line of a user message. Kept uncolored in the\n\t\t// markdown source so the message's own text color applies (white in moon theme);\n\t\t// embedding ANSI here would strip the text color from the rest of the paragraph.\n\t\tcontentBox.addChild(\n\t\t\tnew Markdown(\n\t\t\t\t`● ${this.text}`,\n\t\t\t\t0,\n\t\t\t\t0,\n\t\t\t\tthis.markdownTheme,\n\t\t\t\t{\n\t\t\t\t\tcolor: (content: string) => theme.fg(\"userMessageText\", content),\n\t\t\t\t},\n\t\t\t\t{ preserveOrderedListMarkers: true, preserveBackslashEscapes: true },\n\t\t\t),\n\t\t);\n\t\tthis.addChild(contentBox);\n\t}\n\n\toverride render(width: number): string[] {\n\t\t// lunr: gutter rail — render content at width-2 and prefix each line with a\n\t\t// dim │ so a thin rail runs down the left of the user message.\n\t\tconst railEnabled = this.gutterRail;\n\t\tconst contentWidth = railEnabled ? Math.max(1, width - 2) : width;\n\t\tconst lines = super.render(contentWidth);\n\t\tif (lines.length === 0) {\n\t\t\treturn lines;\n\t\t}\n\n\t\tlines[0] = OSC133_ZONE_START + lines[0];\n\t\tlines[lines.length - 1] = OSC133_ZONE_END + OSC133_ZONE_FINAL + lines[lines.length - 1];\n\n\t\tif (railEnabled) {\n\t\t\tconst rail = theme.fg(\"dim\", \"│ \");\n\t\t\tfor (let i = 0; i < lines.length; i++) {\n\t\t\t\tlines[i] = rail + lines[i];\n\t\t\t}\n\t\t}\n\t\treturn lines;\n\t}\n}\n"]}
@@ -68,7 +68,6 @@ export declare class InteractiveMode {
68
68
  private streamingMessage;
69
69
  private streamingTargetMessage;
70
70
  private streamingDisplayedLength;
71
- private lastSmoothRenderAt;
72
71
  private smoothStreamingTimer;
73
72
  private pendingTools;
74
73
  private toolOutputExpanded;
@@ -84,6 +83,7 @@ export declare class InteractiveMode {
84
83
  private swarmMode;
85
84
  private researchMode;
86
85
  private previousPermissionMode;
86
+ private preGoalPermissionMode;
87
87
  private redoStack;
88
88
  private autoNameTriggered;
89
89
  private bashComponent;
@@ -108,6 +108,7 @@ export declare class InteractiveMode {
108
108
  private autoTrustOnReloadCwd;
109
109
  private themeController;
110
110
  private deferredBuiltinsAttached;
111
+ private deferredBuiltinAttachPromise;
111
112
  private get session();
112
113
  private get agent();
113
114
  private get sessionManager();
@@ -119,6 +120,8 @@ export declare class InteractiveMode {
119
120
  private createBaseAutocompleteProvider;
120
121
  private setupAutocompleteProvider;
121
122
  init(): Promise<void>;
123
+ /** Wait until deferred builtins have attached (or were skipped). */
124
+ waitForDeferredBuiltins(): Promise<void>;
122
125
  /**
123
126
  * Update terminal title with session name and cwd.
124
127
  */
@@ -153,6 +156,9 @@ export declare class InteractiveMode {
153
156
  private formatPathWithSource;
154
157
  private formatDiagnostics;
155
158
  private showLoadedResources;
159
+ private awaitDeferredBuiltinsForPrompt;
160
+ private promptAfterDeferredBuiltins;
161
+ private sendUserMessageAfterDeferredBuiltins;
156
162
  private attachDeferredBuiltinExtensions;
157
163
  private bindCurrentSessionExtensions;
158
164
  private applyRuntimeSettings;
@@ -247,12 +253,22 @@ export declare class InteractiveMode {
247
253
  private setupKeyHandlers;
248
254
  private handleClipboardPaste;
249
255
  private setupEditorSubmitHandler;
250
- /** Smooth streaming tick rate (ms) and base reveal speed (graphemes per tick). */
256
+ /** Smooth streaming tick rate (~30 FPS). TUI already caps paints at 16ms. */
251
257
  private static readonly SMOOTH_STREAMING_TICK_MS;
252
- private static readonly SMOOTH_STREAMING_BASE_GRAPHEMES_PER_TICK;
258
+ private getSmoothStreamingOptions;
259
+ private clearSmoothStreamingTimer;
253
260
  private startSmoothStreaming;
261
+ /** Apply the current reveal slice and sync tool cards that have crossed the frontier. */
262
+ private paintSmoothStreamingFrame;
263
+ /**
264
+ * Create/update tool cards only once smooth streaming has revealed past their
265
+ * leading text. Args always come from the full target so later arg deltas apply.
266
+ */
267
+ private syncRevealedStreamingTools;
254
268
  private advanceSmoothStreaming;
255
269
  private stopSmoothStreaming;
270
+ /** Apply a mid-stream smoothStreaming setting change without rewinding. */
271
+ private applySmoothStreamingSettingChange;
256
272
  private subscribeToAgent;
257
273
  private handleEvent;
258
274
  /** Extract text content from a user message */
@@ -417,10 +433,8 @@ export declare class InteractiveMode {
417
433
  private maybeAutoNameSession;
418
434
  private generateSessionTitle;
419
435
  private handleSessionCommand;
420
- private collectSessionModelRows;
421
- private collectUsageHistorySafe;
436
+ private collectUsageBreakdown;
422
437
  private handleUsageCommand;
423
- private handleTokenUsageCommand;
424
438
  private handleContextCommand;
425
439
  private handlePlanCommand;
426
440
  private handleModeCommand;
@@ -428,9 +442,12 @@ export declare class InteractiveMode {
428
442
  private restoreTargetAfterPlan;
429
443
  /** Apply addendum + auto-rollback for a mode without a status toast. */
430
444
  private syncPermissionModeEffects;
445
+ private enterGoalAuto;
446
+ private leaveGoalAuto;
431
447
  private applyPermissionMode;
432
448
  private showApprovalDialog;
433
449
  private showSwarmApprovalDialog;
450
+ private showPlanInChat;
434
451
  private showPlanApprovalDialog;
435
452
  private showProcessesSelector;
436
453
  private handleRollbackCommand;