@slkiser/opencode-quota 4.8.2 → 4.10.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 (270) hide show
  1. package/README.md +18 -18
  2. package/dist/bin/opencode-quota.d.ts.map +1 -1
  3. package/dist/bin/opencode-quota.js +5 -3
  4. package/dist/bin/opencode-quota.js.map +1 -1
  5. package/dist/lib/accounting-format.d.ts +54 -0
  6. package/dist/lib/accounting-format.d.ts.map +1 -0
  7. package/dist/lib/accounting-format.js +271 -0
  8. package/dist/lib/accounting-format.js.map +1 -0
  9. package/dist/lib/anthropic.d.ts +21 -2
  10. package/dist/lib/anthropic.d.ts.map +1 -1
  11. package/dist/lib/anthropic.js +141 -22
  12. package/dist/lib/anthropic.js.map +1 -1
  13. package/dist/lib/cli-show.d.ts.map +1 -1
  14. package/dist/lib/cli-show.js +7 -1
  15. package/dist/lib/cli-show.js.map +1 -1
  16. package/dist/lib/config.d.ts +10 -1
  17. package/dist/lib/config.d.ts.map +1 -1
  18. package/dist/lib/config.js +69 -3
  19. package/dist/lib/config.js.map +1 -1
  20. package/dist/lib/copilot.d.ts +2 -0
  21. package/dist/lib/copilot.d.ts.map +1 -1
  22. package/dist/lib/copilot.js +38 -0
  23. package/dist/lib/copilot.js.map +1 -1
  24. package/dist/lib/cursor-usage.d.ts +1 -0
  25. package/dist/lib/cursor-usage.d.ts.map +1 -1
  26. package/dist/lib/cursor-usage.js +1 -0
  27. package/dist/lib/cursor-usage.js.map +1 -1
  28. package/dist/lib/deepseek.d.ts +12 -12
  29. package/dist/lib/deepseek.d.ts.map +1 -1
  30. package/dist/lib/deepseek.js +33 -29
  31. package/dist/lib/deepseek.js.map +1 -1
  32. package/dist/lib/display-sanitize.d.ts.map +1 -1
  33. package/dist/lib/display-sanitize.js +75 -22
  34. package/dist/lib/display-sanitize.js.map +1 -1
  35. package/dist/lib/entries.d.ts +122 -23
  36. package/dist/lib/entries.d.ts.map +1 -1
  37. package/dist/lib/entries.js +41 -1
  38. package/dist/lib/entries.js.map +1 -1
  39. package/dist/lib/format-utils.d.ts +11 -8
  40. package/dist/lib/format-utils.d.ts.map +1 -1
  41. package/dist/lib/format-utils.js +47 -6
  42. package/dist/lib/format-utils.js.map +1 -1
  43. package/dist/lib/format.d.ts +4 -0
  44. package/dist/lib/format.d.ts.map +1 -1
  45. package/dist/lib/format.js +144 -42
  46. package/dist/lib/format.js.map +1 -1
  47. package/dist/lib/glm-coding-plan.d.ts.map +1 -1
  48. package/dist/lib/glm-coding-plan.js +12 -3
  49. package/dist/lib/glm-coding-plan.js.map +1 -1
  50. package/dist/lib/google-agy.d.ts +2 -0
  51. package/dist/lib/google-agy.d.ts.map +1 -1
  52. package/dist/lib/google-agy.js +29 -14
  53. package/dist/lib/google-agy.js.map +1 -1
  54. package/dist/lib/google-gemini-cli.d.ts +2 -0
  55. package/dist/lib/google-gemini-cli.d.ts.map +1 -1
  56. package/dist/lib/google-gemini-cli.js +29 -3
  57. package/dist/lib/google-gemini-cli.js.map +1 -1
  58. package/dist/lib/google-token-cache.d.ts +5 -8
  59. package/dist/lib/google-token-cache.d.ts.map +1 -1
  60. package/dist/lib/google-token-cache.js +30 -118
  61. package/dist/lib/google-token-cache.js.map +1 -1
  62. package/dist/lib/google.d.ts +2 -0
  63. package/dist/lib/google.d.ts.map +1 -1
  64. package/dist/lib/google.js +31 -6
  65. package/dist/lib/google.js.map +1 -1
  66. package/dist/lib/grouped-entry-normalization.d.ts.map +1 -1
  67. package/dist/lib/grouped-entry-normalization.js +53 -20
  68. package/dist/lib/grouped-entry-normalization.js.map +1 -1
  69. package/dist/lib/minimax-auth.d.ts +1 -1
  70. package/dist/lib/minimax-auth.js +1 -1
  71. package/dist/lib/nanogpt.d.ts +5 -5
  72. package/dist/lib/nanogpt.d.ts.map +1 -1
  73. package/dist/lib/nanogpt.js +59 -23
  74. package/dist/lib/nanogpt.js.map +1 -1
  75. package/dist/lib/ollama-cloud.d.ts +2 -2
  76. package/dist/lib/ollama-cloud.d.ts.map +1 -1
  77. package/dist/lib/ollama-cloud.js +3 -45
  78. package/dist/lib/ollama-cloud.js.map +1 -1
  79. package/dist/lib/openai.d.ts +6 -0
  80. package/dist/lib/openai.d.ts.map +1 -1
  81. package/dist/lib/openai.js +51 -16
  82. package/dist/lib/openai.js.map +1 -1
  83. package/dist/lib/opencode-go-auth.js +1 -1
  84. package/dist/lib/opencode-go-auth.js.map +1 -1
  85. package/dist/lib/opencode-go.d.ts.map +1 -1
  86. package/dist/lib/opencode-go.js +28 -3
  87. package/dist/lib/opencode-go.js.map +1 -1
  88. package/dist/lib/opencode-zen-config.d.ts +0 -1
  89. package/dist/lib/opencode-zen-config.d.ts.map +1 -1
  90. package/dist/lib/opencode-zen-config.js +0 -22
  91. package/dist/lib/opencode-zen-config.js.map +1 -1
  92. package/dist/lib/opencode-zen.d.ts +3 -0
  93. package/dist/lib/opencode-zen.d.ts.map +1 -1
  94. package/dist/lib/opencode-zen.js +18 -1
  95. package/dist/lib/opencode-zen.js.map +1 -1
  96. package/dist/lib/openrouter.d.ts +2 -0
  97. package/dist/lib/openrouter.d.ts.map +1 -1
  98. package/dist/lib/openrouter.js +10 -0
  99. package/dist/lib/openrouter.js.map +1 -1
  100. package/dist/lib/provider-metadata.d.ts +2 -307
  101. package/dist/lib/provider-metadata.d.ts.map +1 -1
  102. package/dist/lib/provider-metadata.js +14 -316
  103. package/dist/lib/provider-metadata.js.map +1 -1
  104. package/dist/lib/provider-registration.d.ts +325 -0
  105. package/dist/lib/provider-registration.d.ts.map +1 -0
  106. package/dist/lib/provider-registration.js +338 -0
  107. package/dist/lib/provider-registration.js.map +1 -0
  108. package/dist/lib/quota-accounting-projection.d.ts +9 -0
  109. package/dist/lib/quota-accounting-projection.d.ts.map +1 -0
  110. package/dist/lib/quota-accounting-projection.js +254 -0
  111. package/dist/lib/quota-accounting-projection.js.map +1 -0
  112. package/dist/lib/quota-command-format.d.ts +5 -2
  113. package/dist/lib/quota-command-format.d.ts.map +1 -1
  114. package/dist/lib/quota-command-format.js +66 -44
  115. package/dist/lib/quota-command-format.js.map +1 -1
  116. package/dist/lib/quota-dialog-commands.d.ts.map +1 -1
  117. package/dist/lib/quota-dialog-commands.js +3 -0
  118. package/dist/lib/quota-dialog-commands.js.map +1 -1
  119. package/dist/lib/quota-exhaustion-projection.d.ts +11 -0
  120. package/dist/lib/quota-exhaustion-projection.d.ts.map +1 -0
  121. package/dist/lib/quota-exhaustion-projection.js +105 -0
  122. package/dist/lib/quota-exhaustion-projection.js.map +1 -0
  123. package/dist/lib/quota-export.d.ts +2 -1
  124. package/dist/lib/quota-export.d.ts.map +1 -1
  125. package/dist/lib/quota-export.js +36 -10
  126. package/dist/lib/quota-export.js.map +1 -1
  127. package/dist/lib/quota-providers-local.d.ts.map +1 -1
  128. package/dist/lib/quota-providers-local.js +14 -0
  129. package/dist/lib/quota-providers-local.js.map +1 -1
  130. package/dist/lib/quota-providers-remote.d.ts.map +1 -1
  131. package/dist/lib/quota-providers-remote.js +6 -2
  132. package/dist/lib/quota-providers-remote.js.map +1 -1
  133. package/dist/lib/quota-render-data.d.ts +0 -1
  134. package/dist/lib/quota-render-data.d.ts.map +1 -1
  135. package/dist/lib/quota-render-data.js +13 -138
  136. package/dist/lib/quota-render-data.js.map +1 -1
  137. package/dist/lib/quota-reset-notifications.d.ts.map +1 -1
  138. package/dist/lib/quota-reset-notifications.js +3 -0
  139. package/dist/lib/quota-reset-notifications.js.map +1 -1
  140. package/dist/lib/quota-state-codec.d.ts +16 -0
  141. package/dist/lib/quota-state-codec.d.ts.map +1 -0
  142. package/dist/lib/quota-state-codec.js +412 -0
  143. package/dist/lib/quota-state-codec.js.map +1 -0
  144. package/dist/lib/quota-state.d.ts +2 -11
  145. package/dist/lib/quota-state.d.ts.map +1 -1
  146. package/dist/lib/quota-state.js +165 -305
  147. package/dist/lib/quota-state.js.map +1 -1
  148. package/dist/lib/quota-status.d.ts.map +1 -1
  149. package/dist/lib/quota-status.js +15 -7
  150. package/dist/lib/quota-status.js.map +1 -1
  151. package/dist/lib/quota-telemetry.d.ts.map +1 -1
  152. package/dist/lib/quota-telemetry.js +7 -3
  153. package/dist/lib/quota-telemetry.js.map +1 -1
  154. package/dist/lib/quota-toast-runtime.d.ts +60 -0
  155. package/dist/lib/quota-toast-runtime.d.ts.map +1 -0
  156. package/dist/lib/quota-toast-runtime.js +774 -0
  157. package/dist/lib/quota-toast-runtime.js.map +1 -0
  158. package/dist/lib/qwen-local-quota.d.ts +2 -0
  159. package/dist/lib/qwen-local-quota.d.ts.map +1 -1
  160. package/dist/lib/qwen-local-quota.js +17 -1
  161. package/dist/lib/qwen-local-quota.js.map +1 -1
  162. package/dist/lib/resolved-auth-identity.d.ts +36 -0
  163. package/dist/lib/resolved-auth-identity.d.ts.map +1 -0
  164. package/dist/lib/resolved-auth-identity.js +193 -0
  165. package/dist/lib/resolved-auth-identity.js.map +1 -0
  166. package/dist/lib/scoped-update-migration.d.ts +101 -0
  167. package/dist/lib/scoped-update-migration.d.ts.map +1 -0
  168. package/dist/lib/scoped-update-migration.js +348 -0
  169. package/dist/lib/scoped-update-migration.js.map +1 -0
  170. package/dist/lib/scoped-update.d.ts +8 -0
  171. package/dist/lib/scoped-update.d.ts.map +1 -1
  172. package/dist/lib/scoped-update.js +263 -50
  173. package/dist/lib/scoped-update.js.map +1 -1
  174. package/dist/lib/toast-format-grouped.d.ts +4 -0
  175. package/dist/lib/toast-format-grouped.d.ts.map +1 -1
  176. package/dist/lib/toast-format-grouped.js +140 -39
  177. package/dist/lib/toast-format-grouped.js.map +1 -1
  178. package/dist/lib/tui-compact-format.d.ts +2 -0
  179. package/dist/lib/tui-compact-format.d.ts.map +1 -1
  180. package/dist/lib/tui-compact-format.js +224 -31
  181. package/dist/lib/tui-compact-format.js.map +1 -1
  182. package/dist/lib/tui-panel-state.d.ts +6 -0
  183. package/dist/lib/tui-panel-state.d.ts.map +1 -1
  184. package/dist/lib/tui-panel-state.js.map +1 -1
  185. package/dist/lib/tui-runtime.d.ts.map +1 -1
  186. package/dist/lib/tui-runtime.js +109 -10
  187. package/dist/lib/tui-runtime.js.map +1 -1
  188. package/dist/lib/tui-sidebar-format.d.ts +1 -1
  189. package/dist/lib/tui-sidebar-format.d.ts.map +1 -1
  190. package/dist/lib/tui-sidebar-format.js +4 -0
  191. package/dist/lib/tui-sidebar-format.js.map +1 -1
  192. package/dist/lib/types.d.ts +21 -13
  193. package/dist/lib/types.d.ts.map +1 -1
  194. package/dist/lib/types.js +2 -0
  195. package/dist/lib/types.js.map +1 -1
  196. package/dist/lib/xai.d.ts +4 -0
  197. package/dist/lib/xai.d.ts.map +1 -1
  198. package/dist/lib/xai.js +29 -3
  199. package/dist/lib/xai.js.map +1 -1
  200. package/dist/plugin.d.ts.map +1 -1
  201. package/dist/plugin.js +27 -720
  202. package/dist/plugin.js.map +1 -1
  203. package/dist/providers/accounting-decimal.d.ts +2 -0
  204. package/dist/providers/accounting-decimal.d.ts.map +1 -0
  205. package/dist/providers/accounting-decimal.js +23 -0
  206. package/dist/providers/accounting-decimal.js.map +1 -0
  207. package/dist/providers/anthropic.d.ts.map +1 -1
  208. package/dist/providers/anthropic.js +36 -0
  209. package/dist/providers/anthropic.js.map +1 -1
  210. package/dist/providers/cache-policies.d.ts +64 -0
  211. package/dist/providers/cache-policies.d.ts.map +1 -0
  212. package/dist/providers/cache-policies.js +197 -0
  213. package/dist/providers/cache-policies.js.map +1 -0
  214. package/dist/providers/cursor.d.ts.map +1 -1
  215. package/dist/providers/cursor.js +85 -58
  216. package/dist/providers/cursor.js.map +1 -1
  217. package/dist/providers/deepseek.d.ts +2 -2
  218. package/dist/providers/deepseek.d.ts.map +1 -1
  219. package/dist/providers/deepseek.js +64 -33
  220. package/dist/providers/deepseek.js.map +1 -1
  221. package/dist/providers/google-agy.js +2 -2
  222. package/dist/providers/google-agy.js.map +1 -1
  223. package/dist/providers/kilo.d.ts.map +1 -1
  224. package/dist/providers/kilo.js +56 -29
  225. package/dist/providers/kilo.js.map +1 -1
  226. package/dist/providers/mimo.d.ts.map +1 -1
  227. package/dist/providers/mimo.js +37 -15
  228. package/dist/providers/mimo.js.map +1 -1
  229. package/dist/providers/minimax-coding-plan.d.ts +8 -7
  230. package/dist/providers/minimax-coding-plan.d.ts.map +1 -1
  231. package/dist/providers/minimax-coding-plan.js +97 -83
  232. package/dist/providers/minimax-coding-plan.js.map +1 -1
  233. package/dist/providers/nanogpt.d.ts.map +1 -1
  234. package/dist/providers/nanogpt.js +72 -51
  235. package/dist/providers/nanogpt.js.map +1 -1
  236. package/dist/providers/ollama-cloud.d.ts +1 -2
  237. package/dist/providers/ollama-cloud.d.ts.map +1 -1
  238. package/dist/providers/ollama-cloud.js +1 -20
  239. package/dist/providers/ollama-cloud.js.map +1 -1
  240. package/dist/providers/openai.d.ts.map +1 -1
  241. package/dist/providers/openai.js +0 -3
  242. package/dist/providers/openai.js.map +1 -1
  243. package/dist/providers/opencode-go.d.ts +1 -0
  244. package/dist/providers/opencode-go.d.ts.map +1 -1
  245. package/dist/providers/opencode-go.js +32 -5
  246. package/dist/providers/opencode-go.js.map +1 -1
  247. package/dist/providers/opencode-zen.d.ts.map +1 -1
  248. package/dist/providers/opencode-zen.js +78 -17
  249. package/dist/providers/opencode-zen.js.map +1 -1
  250. package/dist/providers/quota-providers.d.ts.map +1 -1
  251. package/dist/providers/quota-providers.js +31 -23
  252. package/dist/providers/quota-providers.js.map +1 -1
  253. package/dist/providers/qwen-code.d.ts.map +1 -1
  254. package/dist/providers/qwen-code.js +1 -0
  255. package/dist/providers/qwen-code.js.map +1 -1
  256. package/dist/providers/registry.d.ts +3 -2
  257. package/dist/providers/registry.d.ts.map +1 -1
  258. package/dist/providers/registry.js +41 -31
  259. package/dist/providers/registry.js.map +1 -1
  260. package/dist/providers/result-helpers.d.ts +12 -6
  261. package/dist/providers/result-helpers.d.ts.map +1 -1
  262. package/dist/providers/result-helpers.js +4 -3
  263. package/dist/providers/result-helpers.js.map +1 -1
  264. package/dist/providers/xai.d.ts.map +1 -1
  265. package/dist/providers/xai.js +3 -0
  266. package/dist/providers/xai.js.map +1 -1
  267. package/dist/tui.d.ts.map +1 -1
  268. package/dist/tui.js +24 -11
  269. package/dist/tui.tsx +39 -10
  270. package/package.json +1 -1
@@ -4,11 +4,13 @@
4
4
  * Renders quota entries grouped by provider/account with compact bars.
5
5
  * Designed to feel like a status dashboard while still respecting OpenCode toast width.
6
6
  */
7
- import { isValueEntry } from "./entries.js";
8
- import { bar, DISPLAYED_PERCENT_LABEL_WIDTH, formatDisplayedPercentLabel, formatResetCountdown, isResetTimeDecimals, padLeft, padRight, resolveDisplayedPercent, } from "./format-utils.js";
7
+ import { interpretAccountingRow } from "./accounting-format.js";
8
+ import { isPercentEntry } from "./entries.js";
9
+ import { bar, displayedPercentLabelWidth, formatDisplayedPercentLabel, formatResetCountdown, isResetTimeDecimals, padLeft, padRight, resolveDisplayedPercent, wrapDisplayText, } from "./format-utils.js";
9
10
  import { normalizeGroupedQuotaEntries } from "./grouped-entry-normalization.js";
10
11
  import { formatGroupedHeader } from "./grouped-header-format.js";
11
12
  import { classifyQuotaWindowText } from "./quota-entry-display.js";
13
+ import { formatQuotaRunway } from "./quota-exhaustion-projection.js";
12
14
  import { renderSessionTokensLines } from "./session-tokens-format.js";
13
15
  function normalizeLabelText(value) {
14
16
  return value?.trim().replace(/:+$/u, "").trim() ?? "";
@@ -28,7 +30,9 @@ function extractWindowLabel(text) {
28
30
  const kind = classifyQuotaWindowText(text);
29
31
  return kind ? GROUPED_WINDOW_LABELS[kind] : null;
30
32
  }
31
- function resolveGroupedRowLabel(entry) {
33
+ function resolveGroupedRowLabel(entry, semanticLabel) {
34
+ if (entry.semantic)
35
+ return semanticLabel;
32
36
  const rawLabel = normalizeLabelText(entry.label);
33
37
  const fromLabel = extractWindowLabel(rawLabel);
34
38
  if (fromLabel)
@@ -52,10 +56,11 @@ export function formatQuotaRowsGrouped(params) {
52
56
  const isTiny = maxWidth <= layout.tinyAt;
53
57
  const isNarrow = !isTiny && maxWidth <= layout.narrowAt;
54
58
  const separator = " ";
55
- const percentCol = Math.max(DISPLAYED_PERCENT_LABEL_WIDTH, ...(params.entries ?? [])
56
- .filter((entry) => !isValueEntry(entry))
57
- .map((entry) => formatDisplayedPercentLabel(entry.percentRemaining, params.percentDisplayMode).length));
58
- const barWidth = Math.max(10, maxWidth - separator.length - percentCol);
59
+ const percentCol = Math.max(displayedPercentLabelWidth(params.percentLabelStyle), ...(params.entries ?? [])
60
+ .filter(isPercentEntry)
61
+ .map((entry) => formatDisplayedPercentLabel(entry.percentRemaining, params.percentDisplayMode, params.percentLabelStyle).length));
62
+ const percentValueCol = percentCol;
63
+ const barWidth = Math.max(10, maxWidth - separator.length - percentValueCol);
59
64
  const timeCol = isTiny ? 6 : isNarrow ? 7 : 7;
60
65
  const lines = [];
61
66
  // Group entries in stable order.
@@ -75,21 +80,64 @@ export function formatQuotaRowsGrouped(params) {
75
80
  const list = groups.get(g) ?? [];
76
81
  if (gi > 0)
77
82
  lines.push("");
78
- lines.push(formatGroupedHeader(g).slice(0, maxWidth));
83
+ const groupHeader = formatGroupedHeader(g);
84
+ lines.push(...(params.wrapLabels
85
+ ? wrapDisplayText(groupHeader, maxWidth)
86
+ : [groupHeader.slice(0, maxWidth)]));
79
87
  for (const entry of list) {
88
+ const interpretation = interpretAccountingRow(entry, {
89
+ booleanWording: "semantic",
90
+ ...(!isTiny
91
+ ? {
92
+ basis: (params.accountingDetail ?? "summary") === "detailed"
93
+ ? { kind: "detailed" }
94
+ : {
95
+ kind: "summary",
96
+ mode: params.percentDisplayMode ?? "remaining",
97
+ },
98
+ }
99
+ : {}),
100
+ });
80
101
  const right = entry.right ? entry.right.trim() : "";
81
- if (isValueEntry(entry)) {
82
- const label = entry.label?.trim() || entry.name;
83
- const timeStr = formatResetCountdown(entry.resetTimeIso, {
84
- compactRounded: true,
85
- decimals: params.resetTimeDecimals,
86
- });
87
- const value = entry.value.trim();
102
+ if (interpretation.display.kind === "value") {
103
+ const isAtomicValue = interpretation.display.entryKind !== "value";
104
+ const label = entry.semantic ? interpretation.label : entry.label?.trim() || entry.name;
105
+ const timeStr = entry.resetTimeIso
106
+ ? formatResetCountdown(entry.resetTimeIso, isResetTimeDecimals(params.resetTimeDecimals)
107
+ ? { compactRounded: true, decimals: params.resetTimeDecimals }
108
+ : { spaced: params.resetTimeSpaced })
109
+ : "";
110
+ const value = interpretation.display.entryKind === "value"
111
+ ? interpretation.display.text.trim()
112
+ : interpretation.display.text;
113
+ const leftText = right ? `${label} ${right}` : label;
114
+ const labelAndValue = [leftText, value].filter(Boolean).join(separator);
115
+ if (timeStr &&
116
+ labelAndValue.length <= maxWidth &&
117
+ labelAndValue.length + separator.length + timeStr.length > maxWidth) {
118
+ lines.push(labelAndValue);
119
+ lines.push(padLeft(timeStr, maxWidth));
120
+ continue;
121
+ }
122
+ if (isAtomicValue) {
123
+ const suffix = [value, timeStr].filter(Boolean).join(separator);
124
+ if (suffix.length > maxWidth) {
125
+ if (value.length <= maxWidth)
126
+ lines.push(padLeft(value, maxWidth));
127
+ continue;
128
+ }
129
+ const availableLabelWidth = maxWidth - (suffix ? separator.length + suffix.length : 0);
130
+ if (availableLabelWidth <= 0) {
131
+ lines.push(padLeft(suffix, maxWidth));
132
+ continue;
133
+ }
134
+ const leftText = label.slice(0, availableLabelWidth).trimEnd();
135
+ lines.push(`${padRight(leftText, availableLabelWidth)}${suffix ? `${separator}${suffix}` : ""}`);
136
+ continue;
137
+ }
88
138
  if (isTiny) {
89
139
  // Tiny: "label time value"
90
- const timeWidth = isResetTimeDecimals(params.resetTimeDecimals)
91
- ? Math.max(timeCol, timeStr.length)
92
- : timeCol;
140
+ const timeWidth = Math.max(timeCol, timeStr.length);
93
141
  const valueCol = Math.min(value.length, Math.max(6, percentCol + 2));
94
142
  const tinyNameCol = Math.max(1, maxWidth - separator.length - timeWidth - separator.length - valueCol);
95
143
  const leftText = right ? `${label} ${right}` : label;
@@ -105,7 +153,6 @@ export function formatQuotaRowsGrouped(params) {
105
153
  const timeWidth = Math.max(timeStr.length, timeCol);
106
154
  const valueWidth = Math.max(value.length, 6);
107
155
  const leftMax = Math.max(1, barWidth - separator.length - valueWidth - separator.length - timeWidth);
108
- const leftText = right ? `${label} ${right}` : label;
109
156
  lines.push((padRight(leftText, leftMax) +
110
157
  separator +
111
158
  padLeft(value, valueWidth) +
@@ -113,40 +160,94 @@ export function formatQuotaRowsGrouped(params) {
113
160
  padLeft(timeStr, timeWidth)).slice(0, maxWidth));
114
161
  continue;
115
162
  }
116
- const label = resolveGroupedRowLabel(entry);
163
+ const label = resolveGroupedRowLabel(entry, interpretation.label);
164
+ // A "value row" has no explicit label and carries a `right` summary to be
165
+ // shown instead of a name. When present, the `right` is justified to the
166
+ // edges of line 1 (left + right) and no reset countdown is shown.
167
+ const isValueRow = !entry.label?.trim() && !entry.metricLabel?.trim() && !!entry.right?.trim();
168
+ const displayedPercent = resolveDisplayedPercent(interpretation.display.percentRemaining, params.percentDisplayMode);
169
+ const percentLabel = formatDisplayedPercentLabel(interpretation.display.percentRemaining, params.percentDisplayMode, params.percentLabelStyle);
117
170
  // Percent entries
118
171
  // Show reset countdown whenever quota is not fully available.
119
172
  // (i.e., any usage at all, or depleted)
120
- const timeStr = entry.percentRemaining < 100
121
- ? formatResetCountdown(entry.resetTimeIso, {
122
- compactRounded: true,
123
- decimals: params.resetTimeDecimals,
124
- })
173
+ const timeStr = interpretation.display.percentRemaining < 100
174
+ ? formatResetCountdown(entry.resetTimeIso, isResetTimeDecimals(params.resetTimeDecimals)
175
+ ? { compactRounded: true, decimals: params.resetTimeDecimals }
176
+ : { spaced: params.resetTimeSpaced })
125
177
  : "";
126
- const displayedPercent = resolveDisplayedPercent(entry.percentRemaining, params.percentDisplayMode);
127
- const percentLabel = formatDisplayedPercentLabel(entry.percentRemaining, params.percentDisplayMode);
178
+ const runway = isPercentEntry(entry) ? formatQuotaRunway(entry.runway) : "";
179
+ const addRunwayLine = () => {
180
+ if (runway)
181
+ lines.push(`Runs out ${runway}`.slice(0, maxWidth));
182
+ };
128
183
  if (isTiny) {
129
- // Tiny: "label time XX%" (ignore bar)
130
- const timeWidth = isResetTimeDecimals(params.resetTimeDecimals)
131
- ? Math.max(timeCol, timeStr.length)
132
- : timeCol;
133
- const tinyNameCol = Math.max(1, maxWidth - separator.length - timeWidth - separator.length - percentCol);
184
+ // Tiny: single line with name/time/percent (or just the right summary)
185
+ const timeWidth = Math.max(timeCol, timeStr.length);
186
+ const visibleBarSuffix = percentLabel.slice(0, percentValueCol);
187
+ if (isValueRow) {
188
+ const tinyNameCol = Math.max(1, maxWidth - separator.length - timeWidth - separator.length - percentValueCol);
189
+ const line = [
190
+ padRight(entry.right.trim(), tinyNameCol),
191
+ padLeft(timeStr, timeWidth),
192
+ padLeft(visibleBarSuffix, percentValueCol),
193
+ ].join(separator);
194
+ lines.push(line.slice(0, maxWidth));
195
+ addRunwayLine();
196
+ continue;
197
+ }
198
+ const tinyNameCol = Math.max(1, maxWidth - separator.length - timeWidth - separator.length - percentValueCol);
134
199
  const line = [
135
200
  padRight(label, tinyNameCol),
136
201
  padLeft(timeStr, timeWidth),
137
- padLeft(percentLabel, percentCol),
202
+ padLeft(visibleBarSuffix, percentValueCol),
138
203
  ].join(separator);
139
204
  lines.push(line.slice(0, maxWidth));
205
+ addRunwayLine();
140
206
  continue;
141
207
  }
142
- // Line 1: label + optional right + time at end
143
- const timeWidth = Math.max(timeStr.length, timeCol);
144
- const leftMax = Math.max(1, maxWidth - separator.length - timeWidth);
145
- lines.push((padRight(label, leftMax) + separator + padLeft(timeStr, timeWidth)).slice(0, maxWidth));
208
+ if (isValueRow) {
209
+ // Line 1: right summary. Two segments -> justified to the edges;
210
+ // a single segment -> right-aligned. No name, no reset.
211
+ const text = entry.right.trim();
212
+ const parts = text.split(/\s{2,}/u).filter(Boolean);
213
+ if (parts.length >= 2) {
214
+ const left = parts[0] ?? "";
215
+ const rightText = parts.slice(1).join(" ");
216
+ const sep = " ";
217
+ const leftWidth = Math.max(1, maxWidth - sep.length - rightText.length);
218
+ lines.push((padRight(left, leftWidth) + sep + rightText).slice(0, maxWidth));
219
+ }
220
+ else {
221
+ lines.push(padLeft(text, maxWidth));
222
+ }
223
+ }
224
+ else {
225
+ // Line 1: label + time at end
226
+ const timeWidth = Math.max(timeStr.length, timeCol);
227
+ const leftMax = Math.max(1, maxWidth - separator.length - timeWidth);
228
+ lines.push((padRight(label, leftMax) + separator + padLeft(timeStr, timeWidth)).slice(0, maxWidth));
229
+ }
146
230
  // Line 2: bar + percent
147
231
  const barCell = bar(displayedPercent, barWidth);
148
- const percentCell = padLeft(percentLabel, percentCol);
149
- lines.push([barCell, percentCell].join(separator));
232
+ const suffixCell = padLeft(percentLabel.slice(0, percentValueCol), percentValueCol);
233
+ lines.push([barCell, suffixCell].join(separator));
234
+ addRunwayLine();
235
+ if (interpretation.basis) {
236
+ const candidates = interpretation.basis.kind === "detailed"
237
+ ? interpretation.basis.facts.map((fact) => fact.text)
238
+ : interpretation.basis.text
239
+ ? [interpretation.basis.text]
240
+ : [];
241
+ let detailLine = "";
242
+ for (const candidate of candidates) {
243
+ const next = detailLine ? `${detailLine} | ${candidate}` : candidate;
244
+ if (next.length > maxWidth)
245
+ break;
246
+ detailLine = next;
247
+ }
248
+ if (detailLine)
249
+ lines.push(detailLine);
250
+ }
150
251
  }
151
252
  }
152
253
  for (const err of params.errors ?? []) {
@@ -1 +1 @@
1
- {"version":3,"file":"toast-format-grouped.js","sourceRoot":"","sources":["../../src/lib/toast-format-grouped.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"toast-format-grouped.js","sourceRoot":"","sources":["../../src/lib/toast-format-grouped.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,8 @@ import type { QuotaToastConfig } from "./types.js";
3
3
  export declare function buildCompactQuotaStatusLine(params: {
4
4
  data: QuotaRenderData;
5
5
  percentDisplayMode?: QuotaToastConfig["percentDisplayMode"];
6
+ accountingDetail?: QuotaToastConfig["accountingDetail"];
7
+ resetTimeSpaced?: boolean;
6
8
  maxWidth: number;
7
9
  }): string;
8
10
  //# sourceMappingURL=tui-compact-format.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tui-compact-format.d.ts","sourceRoot":"","sources":["../../src/lib/tui-compact-format.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AA6MnD,wBAAgB,2BAA2B,CAAC,MAAM,EAAE;IAClD,IAAI,EAAE,eAAe,CAAC;IACtB,kBAAkB,CAAC,EAAE,gBAAgB,CAAC,oBAAoB,CAAC,CAAC;IAC5D,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,MAAM,CA4BT"}
1
+ {"version":3,"file":"tui-compact-format.d.ts","sourceRoot":"","sources":["../../src/lib/tui-compact-format.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAqbnD,wBAAgB,2BAA2B,CAAC,MAAM,EAAE;IAClD,IAAI,EAAE,eAAe,CAAC;IACtB,kBAAkB,CAAC,EAAE,gBAAgB,CAAC,oBAAoB,CAAC,CAAC;IAC5D,gBAAgB,CAAC,EAAE,gBAAgB,CAAC,kBAAkB,CAAC,CAAC;IACxD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,EAAE,MAAM,CAAC;CAClB,GAAG,MAAM,CAwCT"}
@@ -1,8 +1,10 @@
1
+ import { interpretAccountingRow } from "./accounting-format.js";
1
2
  import { sanitizeQuotaRenderData, sanitizeSingleLineDisplayText } from "./display-sanitize.js";
2
- import { isValueEntry } from "./entries.js";
3
- import { formatDisplayedPercentLabel } from "./format-utils.js";
3
+ import { isPercentEntry, isValueEntry } from "./entries.js";
4
+ import { formatDisplayedPercentLabel, formatResetCountdown } from "./format-utils.js";
4
5
  import { formatGroupedHeader } from "./grouped-header-format.js";
5
6
  import { extractSingleWindowWindowLabel } from "./quota-entry-display.js";
7
+ import { compareQuotaRunwayUrgency, formatQuotaRunway } from "./quota-exhaustion-projection.js";
6
8
  const COMPACT_SEGMENT_SEPARATOR = " | ";
7
9
  const COMPACT_WINDOW_SEPARATOR = ", ";
8
10
  const ELLIPSIS = "…";
@@ -71,57 +73,238 @@ function getWindowLabel(entry) {
71
73
  const explicitLabel = entry.label?.trim().replace(/:+$/u, "").trim();
72
74
  return explicitLabel ? { text: compactText(explicitLabel), isWindow: false } : null;
73
75
  }
74
- function formatCompactValueEntrySegment(entry) {
76
+ function formatCompactValueEntrySegment(entry, resetTimeSpaced) {
75
77
  const name = getProviderName(entry);
76
78
  const value = compactText(entry.value);
77
- const segment = [name, value].filter(Boolean).join(" - ");
79
+ const reset = formatResetCountdown(entry.resetTimeIso, { spaced: resetTimeSpaced });
80
+ const segment = [name, value, reset].filter(Boolean).join(" - ");
78
81
  return segment || null;
79
82
  }
80
- function formatCompactPercentGroupSegment(group) {
81
- const windows = group.windows;
83
+ function formatCompactPercentGroupSegment(group, windows = group.windows) {
82
84
  if (windows.length === 0)
83
85
  return null;
84
86
  const summary = windows.length === 1
85
87
  ? windows[0].label && !windows[0].isWindow
86
- ? `${windows[0].label} ${windows[0].percent}`
87
- : windows[0].percent
88
+ ? `${windows[0].label} ${windows[0].value}`
89
+ : windows[0].value
88
90
  : windows
89
- .map((window) => (window.label ? `${window.label} ${window.percent}` : window.percent))
91
+ .map((window) => (window.label ? `${window.label} ${window.value}` : window.value))
90
92
  .join(COMPACT_WINDOW_SEPARATOR);
91
93
  const separator = windows.every((window) => window.label && !window.isWindow) ? ": " : " ";
92
94
  return compactText(`${group.provider}${separator}${summary}`);
93
95
  }
94
- function formatCompactEntrySegments(params) {
96
+ function buildSemanticCandidate(entry, percentDisplayMode, accountingDetail, resetTimeSpaced) {
97
+ if (!entry.semantic)
98
+ return null;
99
+ const shouldRequestBasis = accountingDetail === "detailed" &&
100
+ isPercentEntry(entry) &&
101
+ Number.isFinite(entry.percentRemaining);
102
+ const interpretation = interpretAccountingRow(entry, {
103
+ booleanWording: "semantic",
104
+ ...(shouldRequestBasis ? { basis: { kind: "detailed" } } : {}),
105
+ });
106
+ const value = interpretation.display.kind === "percent"
107
+ ? Number.isFinite(interpretation.display.percentRemaining)
108
+ ? formatCompactPercentLabel(interpretation.display.percentRemaining, percentDisplayMode)
109
+ : null
110
+ : interpretation.display.entryKind === "value"
111
+ ? compactText(interpretation.display.text)
112
+ : interpretation.display.text;
113
+ if (!value)
114
+ return null;
115
+ const provider = getProviderName(entry);
116
+ const label = compactText(interpretation.label);
117
+ const prefix = compactText([provider, label].filter(Boolean).join(": "));
118
+ const runway = isPercentEntry(entry) ? formatQuotaRunway(entry.runway) : "";
119
+ const displayValue = compactText([
120
+ value,
121
+ formatResetCountdown(entry.resetTimeIso, { spaced: resetTimeSpaced }),
122
+ runway ? `r/o ${runway}` : "",
123
+ ]
124
+ .filter(Boolean)
125
+ .join(" "));
126
+ const segment = compactText([prefix, displayValue].filter(Boolean).join(" "));
127
+ if (!segment)
128
+ return null;
129
+ const detailRole = percentDisplayMode === "used" ? "used" : "remaining";
130
+ const detail = interpretation.basis?.kind === "detailed"
131
+ ? interpretation.basis.facts.find((fact) => fact.role === detailRole)?.text
132
+ : undefined;
133
+ return {
134
+ segment,
135
+ prominence: entry.semantic.prominence === "supplementary" ? 1 : 0,
136
+ ...(isPercentEntry(entry) && entry.runway ? { runway: entry.runway } : {}),
137
+ ...(detail ? { detail } : {}),
138
+ ...(interpretation.display.kind === "value" && interpretation.display.entryKind !== "value"
139
+ ? { atomic: { prefix, value: displayValue } }
140
+ : {}),
141
+ };
142
+ }
143
+ function formatCompactEntryCandidates(params) {
144
+ const semantic = [];
95
145
  const groups = new Map();
96
- const pendingSegments = [];
146
+ const pendingLegacy = [];
97
147
  for (const entry of params.entries) {
148
+ if (entry.semantic) {
149
+ const candidate = buildSemanticCandidate(entry, params.percentDisplayMode, params.accountingDetail, params.resetTimeSpaced);
150
+ if (candidate)
151
+ semantic.push(candidate);
152
+ continue;
153
+ }
98
154
  if (isValueEntry(entry)) {
99
- const segment = formatCompactValueEntrySegment(entry);
155
+ const segment = formatCompactValueEntrySegment(entry, params.resetTimeSpaced);
100
156
  if (segment)
101
- pendingSegments.push({ kind: "value", segment });
157
+ pendingLegacy.push({ kind: "value", segment });
102
158
  continue;
103
159
  }
160
+ if (!isPercentEntry(entry))
161
+ continue;
104
162
  const provider = getProviderName(entry);
105
- const percent = formatCompactPercentLabel(entry.percentRemaining, params.percentDisplayMode);
163
+ const runway = formatQuotaRunway(entry.runway);
164
+ const value = compactText([
165
+ formatCompactPercentLabel(entry.percentRemaining, params.percentDisplayMode),
166
+ formatResetCountdown(entry.resetTimeIso, { spaced: params.resetTimeSpaced }),
167
+ runway ? `r/o ${runway}` : "",
168
+ ]
169
+ .filter(Boolean)
170
+ .join(" "));
106
171
  const label = getWindowLabel(entry);
107
172
  const key = provider.toLowerCase();
108
173
  let group = groups.get(key);
109
174
  if (!group) {
110
175
  group = { provider, windows: [] };
111
176
  groups.set(key, group);
112
- pendingSegments.push({ kind: "percent", key });
177
+ pendingLegacy.push({ kind: "percent", key });
113
178
  }
114
179
  group.windows.push({
115
180
  label: label?.text ?? null,
116
- percent,
181
+ value,
117
182
  isWindow: label?.isWindow ?? false,
183
+ ...(entry.runway ? { runway: entry.runway } : {}),
118
184
  });
119
185
  }
120
- return pendingSegments
121
- .map((pending) => pending.kind === "value"
122
- ? pending.segment
123
- : formatCompactPercentGroupSegment(groups.get(pending.key)))
124
- .filter((segment) => Boolean(segment));
186
+ const legacy = pendingLegacy
187
+ .map((pending) => {
188
+ if (pending.kind === "value")
189
+ return { segment: pending.segment, prominence: 0 };
190
+ const group = groups.get(pending.key);
191
+ const segment = formatCompactPercentGroupSegment(group);
192
+ if (!segment)
193
+ return null;
194
+ const eligible = group.windows
195
+ .map((window, index) => ({ window, index }))
196
+ .filter(({ window }) => window.runway)
197
+ .sort((left, right) => compareQuotaRunwayUrgency(left.window.runway, right.window.runway) ||
198
+ left.index - right.index);
199
+ const urgent = eligible[0]?.window;
200
+ const fallbackValue = urgent
201
+ ? compactText([urgent.label, urgent.value].filter(Boolean).join(" ")) || undefined
202
+ : undefined;
203
+ const fallbackSegment = fallbackValue
204
+ ? compactText(`${group.provider} ${fallbackValue}`) || undefined
205
+ : undefined;
206
+ return {
207
+ segment,
208
+ prominence: 0,
209
+ ...(fallbackSegment && fallbackSegment !== segment && fallbackValue
210
+ ? {
211
+ fallbackSegment,
212
+ fallbackAtomic: { prefix: group.provider, value: fallbackValue },
213
+ }
214
+ : {}),
215
+ ...(urgent?.runway ? { runway: urgent.runway } : {}),
216
+ };
217
+ })
218
+ .filter((candidate) => Boolean(candidate));
219
+ return [...legacy, ...semantic]
220
+ .map((candidate, index) => ({ candidate, index }))
221
+ .sort((left, right) => left.candidate.prominence - right.candidate.prominence || left.index - right.index)
222
+ .map(({ candidate }) => candidate);
223
+ }
224
+ function fitAtomicCandidate(atomic, maxWidth) {
225
+ if (atomic.value.length > maxWidth)
226
+ return null;
227
+ const full = compactText(`${atomic.prefix} ${atomic.value}`);
228
+ if (full.length <= maxWidth)
229
+ return full;
230
+ const prefixWidth = maxWidth - atomic.value.length - 1;
231
+ if (prefixWidth <= 0)
232
+ return atomic.value;
233
+ const prefix = truncateSingleLine(atomic.prefix, prefixWidth);
234
+ return compactText(`${prefix} ${atomic.value}`);
235
+ }
236
+ function admitCompactCandidates(candidates, maxWidth) {
237
+ const admitted = [];
238
+ const fullLine = candidates.map((candidate) => candidate.segment).join(COMPACT_SEGMENT_SEPARATOR);
239
+ const ordered = fullLine.length <= maxWidth
240
+ ? candidates
241
+ : candidates
242
+ .map((candidate, index) => ({ candidate, index }))
243
+ .sort((left, right) => {
244
+ if (left.candidate.runway && right.candidate.runway) {
245
+ return (compareQuotaRunwayUrgency(left.candidate.runway, right.candidate.runway) ||
246
+ left.index - right.index);
247
+ }
248
+ if (left.candidate.runway)
249
+ return -1;
250
+ if (right.candidate.runway)
251
+ return 1;
252
+ return left.index - right.index;
253
+ })
254
+ .map(({ candidate }) => candidate);
255
+ for (const candidate of ordered) {
256
+ const separatorWidth = admitted.length > 0 ? COMPACT_SEGMENT_SEPARATOR.length : 0;
257
+ const usedWidth = admitted.reduce((total, item, index) => total + item.segment.length + (index > 0 ? COMPACT_SEGMENT_SEPARATOR.length : 0), 0);
258
+ const available = maxWidth - usedWidth - separatorWidth;
259
+ if (available <= 0)
260
+ continue;
261
+ if (candidate.segment.length <= available) {
262
+ admitted.push({ ...candidate });
263
+ continue;
264
+ }
265
+ if (candidate.fallbackSegment) {
266
+ if (candidate.fallbackSegment.length <= available) {
267
+ admitted.push({ ...candidate, segment: candidate.fallbackSegment });
268
+ continue;
269
+ }
270
+ if (admitted.length > 0)
271
+ continue;
272
+ if (candidate.fallbackAtomic) {
273
+ const fitted = fitAtomicCandidate(candidate.fallbackAtomic, available);
274
+ if (fitted) {
275
+ admitted.push({ ...candidate, segment: fitted });
276
+ continue;
277
+ }
278
+ }
279
+ const truncated = truncateSingleLine(candidate.fallbackSegment, available);
280
+ if (truncated)
281
+ admitted.push({ ...candidate, segment: truncated });
282
+ continue;
283
+ }
284
+ if (admitted.length > 0)
285
+ continue;
286
+ if (candidate.atomic) {
287
+ const fitted = fitAtomicCandidate(candidate.atomic, available);
288
+ if (fitted)
289
+ admitted.push({ ...candidate, segment: fitted });
290
+ continue;
291
+ }
292
+ const truncated = truncateSingleLine(candidate.segment, available);
293
+ if (truncated)
294
+ admitted.push({ ...candidate, segment: truncated });
295
+ }
296
+ return admitted;
297
+ }
298
+ function admitBasisDetails(candidates, maxWidth) {
299
+ for (const candidate of candidates) {
300
+ if (!candidate.detail)
301
+ continue;
302
+ const original = candidate.segment;
303
+ candidate.segment = `${original} (${candidate.detail})`;
304
+ const line = candidates.map((item) => item.segment).join(COMPACT_SEGMENT_SEPARATOR);
305
+ if (line.length > maxWidth)
306
+ candidate.segment = original;
307
+ }
125
308
  }
126
309
  function formatCompactTokenCount(count) {
127
310
  if (!Number.isFinite(count))
@@ -168,26 +351,36 @@ export function buildCompactQuotaStatusLine(params) {
168
351
  return "";
169
352
  const data = sanitizeQuotaRenderData(params.data);
170
353
  const percentDisplayMode = params.percentDisplayMode ?? "remaining";
171
- const segments = formatCompactEntrySegments({ entries: data.entries, percentDisplayMode });
172
- const issues = data.errors.filter((error) => error.kind !== "intentional-filter");
354
+ const accountingDetail = params.accountingDetail ?? "summary";
355
+ const candidates = formatCompactEntryCandidates({
356
+ entries: data.entries,
357
+ percentDisplayMode,
358
+ accountingDetail,
359
+ resetTimeSpaced: params.resetTimeSpaced,
360
+ });
173
361
  const sessionTokensSegment = formatCompactSessionTokensSegment(data);
174
362
  if (sessionTokensSegment) {
175
- segments.push(sessionTokensSegment);
363
+ candidates.push({ segment: sessionTokensSegment, prominence: 0 });
176
364
  }
365
+ const admitted = admitCompactCandidates(candidates, maxWidth);
366
+ const issues = data.errors.filter((error) => error.kind !== "intentional-filter");
177
367
  if (issues.length > 0) {
178
- if (segments.length === 0) {
368
+ if (admitted.length === 0) {
179
369
  const errorSegment = formatFirstErrorSegment(issues);
180
- if (errorSegment)
181
- segments.push(errorSegment);
370
+ if (errorSegment) {
371
+ return truncateSingleLine(errorSegment, maxWidth);
372
+ }
182
373
  }
183
374
  else {
184
375
  const issueSegment = formatIssueCount(issues.length);
185
- const candidate = [...segments, issueSegment].join(COMPACT_SEGMENT_SEPARATOR);
186
- if (compactText(candidate).length <= maxWidth) {
187
- segments.push(issueSegment);
376
+ const candidate = [...admitted.map((item) => item.segment), issueSegment].join(COMPACT_SEGMENT_SEPARATOR);
377
+ if (candidate.length <= maxWidth) {
378
+ admitted.push({ segment: issueSegment, prominence: 0 });
188
379
  }
189
380
  }
190
381
  }
191
- return truncateSingleLine(segments.join(COMPACT_SEGMENT_SEPARATOR), maxWidth);
382
+ if (accountingDetail === "detailed")
383
+ admitBasisDetails(admitted, maxWidth);
384
+ return admitted.map((candidate) => candidate.segment).join(COMPACT_SEGMENT_SEPARATOR);
192
385
  }
193
386
  //# sourceMappingURL=tui-compact-format.js.map