@gaunt-sloth/core 2.0.0-alpha.3 → 2.0.0-alpha.31

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 (271) hide show
  1. package/README.md +52 -20
  2. package/dist/config/colour.d.ts +38 -0
  3. package/dist/config/colour.js +36 -0
  4. package/dist/config/colour.js.map +1 -0
  5. package/dist/config/defaults.d.ts +84 -0
  6. package/dist/config/defaults.js +99 -0
  7. package/dist/config/defaults.js.map +1 -0
  8. package/dist/config/filesystem-tools.d.ts +41 -0
  9. package/dist/config/filesystem-tools.js +56 -0
  10. package/dist/config/filesystem-tools.js.map +1 -0
  11. package/dist/config/jsonc.d.ts +12 -0
  12. package/dist/config/jsonc.js +41 -0
  13. package/dist/config/jsonc.js.map +1 -0
  14. package/dist/config/loader.d.ts +246 -0
  15. package/dist/config/loader.js +1321 -0
  16. package/dist/config/loader.js.map +1 -0
  17. package/dist/config/mouse.d.ts +50 -0
  18. package/dist/config/mouse.js +44 -0
  19. package/dist/config/mouse.js.map +1 -0
  20. package/dist/config/profiles.d.ts +68 -0
  21. package/dist/config/profiles.js +93 -0
  22. package/dist/config/profiles.js.map +1 -0
  23. package/dist/config/providerKeys.d.ts +69 -0
  24. package/dist/config/providerKeys.js +69 -0
  25. package/dist/config/providerKeys.js.map +1 -0
  26. package/dist/config/schema.d.ts +2999 -0
  27. package/dist/config/schema.js +1519 -0
  28. package/dist/config/schema.js.map +1 -0
  29. package/dist/config/shell-policy.d.ts +896 -0
  30. package/dist/config/shell-policy.js +750 -0
  31. package/dist/config/shell-policy.js.map +1 -0
  32. package/dist/config/tool-descriptions.d.ts +211 -0
  33. package/dist/config/tool-descriptions.js +272 -0
  34. package/dist/config/tool-descriptions.js.map +1 -0
  35. package/dist/config/types.d.ts +760 -0
  36. package/dist/config/types.js +13 -0
  37. package/dist/config/types.js.map +1 -0
  38. package/dist/config.d.ts +34 -827
  39. package/dist/config.js +25 -657
  40. package/dist/config.js.map +1 -1
  41. package/dist/constants.d.ts +46 -0
  42. package/dist/constants.js +46 -0
  43. package/dist/constants.js.map +1 -1
  44. package/dist/core/GthAbstractAgent.d.ts +135 -2
  45. package/dist/core/GthAbstractAgent.js +496 -30
  46. package/dist/core/GthAbstractAgent.js.map +1 -1
  47. package/dist/core/GthAgentRunner.d.ts +568 -54
  48. package/dist/core/GthAgentRunner.js +1537 -136
  49. package/dist/core/GthAgentRunner.js.map +1 -1
  50. package/dist/core/GthLangChainAgent.d.ts +115 -0
  51. package/dist/core/GthLangChainAgent.js +644 -17
  52. package/dist/core/GthLangChainAgent.js.map +1 -1
  53. package/dist/core/approvals/annotations.d.ts +122 -0
  54. package/dist/core/approvals/annotations.js +137 -0
  55. package/dist/core/approvals/annotations.js.map +1 -0
  56. package/dist/core/approvals/grants.d.ts +216 -0
  57. package/dist/core/approvals/grants.js +469 -0
  58. package/dist/core/approvals/grants.js.map +1 -0
  59. package/dist/core/approvals/matcher.d.ts +202 -0
  60. package/dist/core/approvals/matcher.js +267 -0
  61. package/dist/core/approvals/matcher.js.map +1 -0
  62. package/dist/core/approvals/mcpSubjects.d.ts +40 -0
  63. package/dist/core/approvals/mcpSubjects.js +99 -0
  64. package/dist/core/approvals/mcpSubjects.js.map +1 -0
  65. package/dist/core/approvals/toolAnnotationSources.d.ts +105 -0
  66. package/dist/core/approvals/toolAnnotationSources.js +277 -0
  67. package/dist/core/approvals/toolAnnotationSources.js.map +1 -0
  68. package/dist/core/approvals/toolHost.d.ts +46 -0
  69. package/dist/core/approvals/toolHost.js +108 -0
  70. package/dist/core/approvals/toolHost.js.map +1 -0
  71. package/dist/core/debugCapture.d.ts +75 -0
  72. package/dist/core/debugCapture.js +101 -0
  73. package/dist/core/debugCapture.js.map +1 -0
  74. package/dist/core/gthLeanAgentFactory.d.ts +9 -0
  75. package/dist/core/gthLeanAgentFactory.js +10 -0
  76. package/dist/core/gthLeanAgentFactory.js.map +1 -0
  77. package/dist/core/launchBanner.d.ts +120 -0
  78. package/dist/core/launchBanner.js +418 -0
  79. package/dist/core/launchBanner.js.map +1 -0
  80. package/dist/core/plainToolIndication.d.ts +15 -0
  81. package/dist/core/plainToolIndication.js +174 -0
  82. package/dist/core/plainToolIndication.js.map +1 -0
  83. package/dist/core/reasoningBlocks.d.ts +60 -0
  84. package/dist/core/reasoningBlocks.js +98 -0
  85. package/dist/core/reasoningBlocks.js.map +1 -0
  86. package/dist/core/refusal.d.ts +53 -0
  87. package/dist/core/refusal.js +133 -0
  88. package/dist/core/refusal.js.map +1 -0
  89. package/dist/core/runStats.d.ts +52 -0
  90. package/dist/core/runStats.js +118 -0
  91. package/dist/core/runStats.js.map +1 -0
  92. package/dist/core/shell/ShellCommandFailedError.d.ts +54 -0
  93. package/dist/core/shell/ShellCommandFailedError.js +68 -0
  94. package/dist/core/shell/ShellCommandFailedError.js.map +1 -0
  95. package/dist/core/shell/abstention.d.ts +88 -0
  96. package/dist/core/shell/abstention.js +184 -0
  97. package/dist/core/shell/abstention.js.map +1 -0
  98. package/dist/core/shell/approvalCapture.d.ts +271 -0
  99. package/dist/core/shell/approvalCapture.js +108 -0
  100. package/dist/core/shell/approvalCapture.js.map +1 -0
  101. package/dist/core/shell/approvalStop.d.ts +84 -0
  102. package/dist/core/shell/approvalStop.js +119 -0
  103. package/dist/core/shell/approvalStop.js.map +1 -0
  104. package/dist/core/shell/arity.d.ts +6 -0
  105. package/dist/core/shell/arity.js +20 -6
  106. package/dist/core/shell/arity.js.map +1 -1
  107. package/dist/core/shell/denylist.d.ts +11 -0
  108. package/dist/core/shell/denylist.js +37 -0
  109. package/dist/core/shell/denylist.js.map +1 -0
  110. package/dist/core/shell/escalationSeverity.d.ts +141 -0
  111. package/dist/core/shell/escalationSeverity.js +89 -0
  112. package/dist/core/shell/escalationSeverity.js.map +1 -0
  113. package/dist/core/shell/framing.d.ts +190 -0
  114. package/dist/core/shell/framing.js +633 -0
  115. package/dist/core/shell/framing.js.map +1 -0
  116. package/dist/core/shell/hardline.d.ts +81 -0
  117. package/dist/core/shell/hardline.js +607 -0
  118. package/dist/core/shell/hardline.js.map +1 -0
  119. package/dist/core/shell/negotiation.d.ts +249 -0
  120. package/dist/core/shell/negotiation.js +355 -0
  121. package/dist/core/shell/negotiation.js.map +1 -0
  122. package/dist/core/shell/normalize.d.ts +44 -4
  123. package/dist/core/shell/normalize.js +61 -7
  124. package/dist/core/shell/normalize.js.map +1 -1
  125. package/dist/core/shell/openWorld.d.ts +263 -0
  126. package/dist/core/shell/openWorld.js +1188 -0
  127. package/dist/core/shell/openWorld.js.map +1 -0
  128. package/dist/core/shell/rater.d.ts +935 -0
  129. package/dist/core/shell/rater.js +1473 -0
  130. package/dist/core/shell/rater.js.map +1 -0
  131. package/dist/core/shell/raterModel.d.ts +41 -0
  132. package/dist/core/shell/raterModel.js +51 -0
  133. package/dist/core/shell/raterModel.js.map +1 -0
  134. package/dist/core/shell/rejection.d.ts +69 -0
  135. package/dist/core/shell/rejection.js +38 -0
  136. package/dist/core/shell/rejection.js.map +1 -0
  137. package/dist/core/toolCallRepair/grammar.d.ts +41 -0
  138. package/dist/core/toolCallRepair/grammar.js +116 -0
  139. package/dist/core/toolCallRepair/grammar.js.map +1 -0
  140. package/dist/core/toolCallRepair/index.d.ts +2 -0
  141. package/dist/core/toolCallRepair/index.js +7 -0
  142. package/dist/core/toolCallRepair/index.js.map +1 -0
  143. package/dist/core/toolCallRepair/payload.d.ts +36 -0
  144. package/dist/core/toolCallRepair/payload.js +341 -0
  145. package/dist/core/toolCallRepair/payload.js.map +1 -0
  146. package/dist/core/toolCallRepair/promote.d.ts +45 -0
  147. package/dist/core/toolCallRepair/promote.js +90 -0
  148. package/dist/core/toolCallRepair/promote.js.map +1 -0
  149. package/dist/core/toolDisplay.d.ts +123 -0
  150. package/dist/core/toolDisplay.js +451 -0
  151. package/dist/core/toolDisplay.js.map +1 -0
  152. package/dist/core/toolOutputChannel.d.ts +95 -0
  153. package/dist/core/toolOutputChannel.js +165 -0
  154. package/dist/core/toolOutputChannel.js.map +1 -0
  155. package/dist/core/types.d.ts +294 -12
  156. package/dist/core/types.js.map +1 -1
  157. package/dist/history/historyFormat.d.ts +28 -0
  158. package/dist/history/historyFormat.js +127 -0
  159. package/dist/history/historyFormat.js.map +1 -0
  160. package/dist/history/historyStore.d.ts +198 -0
  161. package/dist/history/historyStore.js +482 -0
  162. package/dist/history/historyStore.js.map +1 -0
  163. package/dist/history/recordSession.d.ts +37 -0
  164. package/dist/history/recordSession.js +56 -0
  165. package/dist/history/recordSession.js.map +1 -0
  166. package/dist/index.d.ts +4 -0
  167. package/dist/index.js +4 -0
  168. package/dist/index.js.map +1 -1
  169. package/dist/providers/anthropic.d.ts +1 -1
  170. package/dist/providers/anthropic.js +5 -10
  171. package/dist/providers/anthropic.js.map +1 -1
  172. package/dist/providers/deepseek.d.ts +1 -1
  173. package/dist/providers/deepseek.js +5 -10
  174. package/dist/providers/deepseek.js.map +1 -1
  175. package/dist/providers/geminiSchemaSanitizer.d.ts +55 -0
  176. package/dist/providers/geminiSchemaSanitizer.js +347 -0
  177. package/dist/providers/geminiSchemaSanitizer.js.map +1 -0
  178. package/dist/providers/geminiThinking.d.ts +52 -0
  179. package/dist/providers/geminiThinking.js +72 -0
  180. package/dist/providers/geminiThinking.js.map +1 -0
  181. package/dist/providers/google-genai.d.ts +1 -1
  182. package/dist/providers/google-genai.js +12 -11
  183. package/dist/providers/google-genai.js.map +1 -1
  184. package/dist/providers/groq.d.ts +1 -1
  185. package/dist/providers/groq.js +5 -10
  186. package/dist/providers/groq.js.map +1 -1
  187. package/dist/providers/huggingface.d.ts +25 -0
  188. package/dist/providers/huggingface.js +69 -0
  189. package/dist/providers/huggingface.js.map +1 -0
  190. package/dist/providers/modelCatalog.d.ts +109 -0
  191. package/dist/providers/modelCatalog.js +245 -0
  192. package/dist/providers/modelCatalog.js.map +1 -0
  193. package/dist/providers/modelDiscovery.d.ts +153 -6
  194. package/dist/providers/modelDiscovery.js +295 -41
  195. package/dist/providers/modelDiscovery.js.map +1 -1
  196. package/dist/providers/ollama.d.ts +19 -5
  197. package/dist/providers/ollama.js +60 -52
  198. package/dist/providers/ollama.js.map +1 -1
  199. package/dist/providers/openai.d.ts +1 -1
  200. package/dist/providers/openai.js +39 -10
  201. package/dist/providers/openai.js.map +1 -1
  202. package/dist/providers/openrouter.d.ts +4 -5
  203. package/dist/providers/openrouter.js +20 -35
  204. package/dist/providers/openrouter.js.map +1 -1
  205. package/dist/providers/vertexai.d.ts +1 -1
  206. package/dist/providers/vertexai.js +12 -11
  207. package/dist/providers/vertexai.js.map +1 -1
  208. package/dist/providers/xai.d.ts +1 -1
  209. package/dist/providers/xai.js +5 -10
  210. package/dist/providers/xai.js.map +1 -1
  211. package/dist/runtime/askStructured.d.ts +105 -0
  212. package/dist/runtime/askStructured.js +120 -0
  213. package/dist/runtime/askStructured.js.map +1 -0
  214. package/dist/runtime/conversation.d.ts +60 -0
  215. package/dist/runtime/conversation.js +151 -0
  216. package/dist/runtime/conversation.js.map +1 -0
  217. package/dist/runtime/singleShot.d.ts +25 -5
  218. package/dist/runtime/singleShot.js +95 -36
  219. package/dist/runtime/singleShot.js.map +1 -1
  220. package/dist/runtime/structuredOutput.d.ts +104 -0
  221. package/dist/runtime/structuredOutput.js +393 -0
  222. package/dist/runtime/structuredOutput.js.map +1 -0
  223. package/dist/utils/ProgressIndicator.d.ts +21 -0
  224. package/dist/utils/ProgressIndicator.js +30 -3
  225. package/dist/utils/ProgressIndicator.js.map +1 -1
  226. package/dist/utils/aiignoreUtils.js.map +1 -1
  227. package/dist/utils/binaryOutputUtils.js.map +1 -1
  228. package/dist/utils/consoleUtils.d.ts +52 -0
  229. package/dist/utils/consoleUtils.js +72 -2
  230. package/dist/utils/consoleUtils.js.map +1 -1
  231. package/dist/utils/crashHandler.d.ts +87 -0
  232. package/dist/utils/crashHandler.js +128 -0
  233. package/dist/utils/crashHandler.js.map +1 -0
  234. package/dist/utils/debugDump.d.ts +134 -0
  235. package/dist/utils/debugDump.js +381 -0
  236. package/dist/utils/debugDump.js.map +1 -0
  237. package/dist/utils/debugUtils.d.ts +13 -4
  238. package/dist/utils/debugUtils.js +36 -13
  239. package/dist/utils/debugUtils.js.map +1 -1
  240. package/dist/utils/displayWidth.d.ts +53 -0
  241. package/dist/utils/displayWidth.js +195 -0
  242. package/dist/utils/displayWidth.js.map +1 -0
  243. package/dist/utils/fileUtils.d.ts +24 -2
  244. package/dist/utils/fileUtils.js +54 -12
  245. package/dist/utils/fileUtils.js.map +1 -1
  246. package/dist/utils/llmUtils.d.ts +39 -8
  247. package/dist/utils/llmUtils.js +76 -8
  248. package/dist/utils/llmUtils.js.map +1 -1
  249. package/dist/utils/redactSecrets.d.ts +63 -0
  250. package/dist/utils/redactSecrets.js +286 -0
  251. package/dist/utils/redactSecrets.js.map +1 -0
  252. package/dist/utils/systemPromptNotes.d.ts +225 -0
  253. package/dist/utils/systemPromptNotes.js +340 -0
  254. package/dist/utils/systemPromptNotes.js.map +1 -0
  255. package/dist/utils/systemUtils.d.ts +49 -1
  256. package/dist/utils/systemUtils.js +67 -3
  257. package/dist/utils/systemUtils.js.map +1 -1
  258. package/dist/utils/toolMatching.d.ts +30 -0
  259. package/dist/utils/toolMatching.js +44 -0
  260. package/dist/utils/toolMatching.js.map +1 -0
  261. package/dist/utils/untrustedText.d.ts +66 -0
  262. package/dist/utils/untrustedText.js +80 -0
  263. package/dist/utils/untrustedText.js.map +1 -0
  264. package/package.json +22 -6
  265. package/schema/gsloth-config.schema.json +3134 -0
  266. package/dist/core/shell/allowlist.d.ts +0 -75
  267. package/dist/core/shell/allowlist.js +0 -187
  268. package/dist/core/shell/allowlist.js.map +0 -1
  269. package/dist/core/shell/judge.d.ts +0 -161
  270. package/dist/core/shell/judge.js +0 -261
  271. package/dist/core/shell/judge.js.map +0 -1
@@ -0,0 +1,451 @@
1
+ /**
2
+ * @module toolDisplay
3
+ * TUI-C30 — the surface-agnostic tool-display registry: how a tool CALL is summarised
4
+ * (`name(arg=val, …)`) and how its OUTPUT is previewed (up to {@link TOOL_OUTPUT_PREVIEW_LINES}
5
+ * greyed lines, diff-coloured for `write_file`/`edit_file`), shared by BOTH render surfaces:
6
+ *
7
+ * - the Ink TUI's `ToolCallPanel` (`packages/app/src/tui/components/LiveTurn.tsx`), and
8
+ * - the plain/readline (`--no-tui`, piped, single-shot) surface
9
+ * (`core/plainToolIndication.ts`).
10
+ *
11
+ * Everything here is PURE STRINGS plus a style tag per line ({@link ToolDisplayLine}), so the
12
+ * module knows nothing about Ink or ANSI: the TUI maps styles to `<Text>` props and the plain
13
+ * surface maps them to raw ANSI via {@link renderToolLineAnsi}. The shape mirrors vue-ui's
14
+ * PLAT-17 `toolDisplay.ts` (name → glyph + which args to summarise + optional result formatter,
15
+ * with a generic fallback — cf. openclaw's `TOOL_DISPLAY_CONFIG` and opencode's
16
+ * `collapseToolOutput`) so the surfaces stay analogous without sharing code.
17
+ *
18
+ * Design rules (from the node spec):
19
+ * - **One canonical output cap: {@link TOOL_OUTPUT_PREVIEW_LINES} lines** (and a per-line char
20
+ * cap), applied by {@link capToolDisplayLines} with a `… (+N more lines)` overflow marker.
21
+ * This is a RENDER-time cap only — the model-facing `OutputBuffer`/EXT-9 head-tail caps are a
22
+ * separate layer beneath it and are never touched here.
23
+ * - **Secret redaction reuses the GS2-47 `redactSecrets` lineage** (literal env/config secrets +
24
+ * provider key patterns) — no new redactor. Applied to the params summary and every
25
+ * preview/body line, fail-safe (redact MORE on any error, never leak).
26
+ * - **`write_file`/`edit_file` render the change as a diff derived from the tool's ARGS**
27
+ * (added = `added` style/green, removed = `removed` style/red); monochrome keeps the `+`/`-`
28
+ * prefixes so the diff still reads without colour (DL-7 graceful degradation).
29
+ */
30
+ import { displayWidth, sliceToWidth } from '#src/utils/displayWidth.js';
31
+ import { collectSecretValues, redactText } from '#src/utils/redactSecrets.js';
32
+ import { env } from '#src/utils/systemUtils.js';
33
+ /** The single canonical output-preview cap (lines). No other preview length exists anywhere. */
34
+ export const TOOL_OUTPUT_PREVIEW_LINES = 10;
35
+ /**
36
+ * Per-line cap for preview lines, in terminal COLUMNS (a one-line minified bundle must not flood a
37
+ * row). The `CHARS` in the name is historical; every cap here is a column budget, because a
38
+ * character count is not a width — see `#src/utils/displayWidth.js`.
39
+ */
40
+ export const TOOL_PREVIEW_LINE_MAX_CHARS = 200;
41
+ /** Per-value cap inside a params summary, in terminal COLUMNS. */
42
+ export const TOOL_PARAM_VALUE_MAX_CHARS = 48;
43
+ /** Whole params-summary cap (everything inside the parentheses), in terminal COLUMNS. */
44
+ export const TOOL_SUMMARY_MAX_CHARS = 120;
45
+ /** The overflow/truncation marker used everywhere in this module. */
46
+ export const ELLIPSIS = '…';
47
+ /**
48
+ * Columns {@link ELLIPSIS} itself occupies, which every truncator has to reserve out of its budget
49
+ * before slicing. Derived rather than written as `1` so it stays true of whatever marker is used.
50
+ */
51
+ export const ELLIPSIS_WIDTH = displayWidth(ELLIPSIS);
52
+ const FALLBACK_GLYPH = '⚙';
53
+ const FILE_GLYPH = '📁';
54
+ const SHELL_GLYPH = '🔧';
55
+ /* ------------------------------------------------------------------------- *
56
+ * Small shared helpers *
57
+ * ------------------------------------------------------------------------- */
58
+ /**
59
+ * Tolerant parse of a (possibly partial) streamed args JSON. Mirrors the view-model's
60
+ * defensive posture: a half-streamed or malformed buffer never throws — it returns `null`.
61
+ */
62
+ export function parseToolArgsSafe(argsText) {
63
+ if (!argsText || !argsText.trim())
64
+ return null;
65
+ try {
66
+ const parsed = JSON.parse(argsText);
67
+ if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {
68
+ return parsed;
69
+ }
70
+ return null;
71
+ }
72
+ catch {
73
+ return null;
74
+ }
75
+ }
76
+ /**
77
+ * The live gth config, registered once per run so {@link getDefaultSecrets} can harvest INLINE
78
+ * config secrets (a pasted `apiKey`/`token` value) via the GS2-47 config walk — not only the
79
+ * env-derived literals. `GthAgentRunner.init` sets this next to the crash-context hand-off, so
80
+ * both render surfaces (the plain observer and the Ink TUI) see it. `undefined` (no config yet)
81
+ * degrades to env-only collection + the provider patterns, exactly as before.
82
+ */
83
+ let displayConfig = undefined;
84
+ /**
85
+ * Register the live config for inline-secret collection (TUI-C32 residual a). Resets the secret
86
+ * cache so the next {@link getDefaultSecrets} recomputes with the config's inline literals folded
87
+ * in. Idempotent; a later call with a fresh config supersedes the previous one.
88
+ */
89
+ export function setToolDisplayConfig(config) {
90
+ displayConfig = config;
91
+ cachedSecrets = null;
92
+ }
93
+ /**
94
+ * Lazily-computed default secret literals for redaction (GS2-47 technique 1), harvested from the
95
+ * process env AND the registered config (inline `apiKey`/`token` values) the same way
96
+ * `/debug-dump` does. Cached because `collectSecretValues` walks the whole env + config; the set
97
+ * cannot change mid-process in any way this render path must react to (a new config resets it via
98
+ * {@link setToolDisplayConfig}). `redactText` additionally always applies the provider-key
99
+ * patterns (technique 2).
100
+ */
101
+ let cachedSecrets = null;
102
+ function getDefaultSecrets() {
103
+ if (cachedSecrets === null) {
104
+ try {
105
+ cachedSecrets = collectSecretValues(displayConfig, env ?? {});
106
+ }
107
+ catch {
108
+ cachedSecrets = []; // patterns still apply via redactText
109
+ }
110
+ }
111
+ return cachedSecrets;
112
+ }
113
+ /** Test seam: drop the cached secret literals + registered config so specs can vary both. */
114
+ export function resetToolDisplaySecretsCacheForTests() {
115
+ cachedSecrets = null;
116
+ displayConfig = undefined;
117
+ }
118
+ /** Collapse whitespace runs (incl. newlines) so a value stays a one-line token. */
119
+ function inline(value) {
120
+ return value.replace(/\s+/g, ' ').trim();
121
+ }
122
+ /**
123
+ * Truncate to `max` terminal COLUMNS with the {@link ELLIPSIS} marker, reserving the marker's own
124
+ * width out of the budget. Slicing goes through the shared width primitive: a code-point count
125
+ * would read a CJK or emoji value as shorter than it renders and hand it back whole, over-running
126
+ * the row it is drawn on.
127
+ *
128
+ * Whether the value fits is put to the SLICE rather than to the ruler, because the slice stops at
129
+ * the budget: a value that over-runs is recognised from its first `max` columns, where measuring
130
+ * it reads all of it — and the values arriving here are whole tool-output lines, which
131
+ * {@link TOOL_PREVIEW_LINE_MAX_CHARS} exists precisely because they can be a megabyte long.
132
+ */
133
+ function truncate(value, max) {
134
+ const fitted = sliceToWidth(value, max);
135
+ if (fitted === value)
136
+ return value;
137
+ return sliceToWidth(value, max - ELLIPSIS_WIDTH) + ELLIPSIS;
138
+ }
139
+ /**
140
+ * Render one arg value for the summary: strings inline+truncated, the rest JSON-ish.
141
+ *
142
+ * ORDER MATTERS (fix-cycle-1 finding): redaction runs BEFORE any transformation. Truncating
143
+ * first would bisect a literal secret longer than the value cap so it no longer
144
+ * literal-matches — its head would render in the call summary on both surfaces (a partial
145
+ * leak); whitespace-collapsing first could likewise alter a literal out of matching. So:
146
+ * redact the RAW text, then inline, then truncate (`<redacted>` contains no whitespace and is
147
+ * shorter than the cap, so the later steps can never damage the marker).
148
+ */
149
+ function formatParamValue(value, secrets) {
150
+ let text;
151
+ if (typeof value === 'string') {
152
+ text = value;
153
+ }
154
+ else if (value === undefined) {
155
+ text = 'undefined';
156
+ }
157
+ else {
158
+ try {
159
+ text = JSON.stringify(value) ?? String(value);
160
+ }
161
+ catch {
162
+ text = String(value);
163
+ }
164
+ }
165
+ return truncate(inline(redactText(text, secrets)), TOOL_PARAM_VALUE_MAX_CHARS);
166
+ }
167
+ /** Split into lines, dropping a single trailing newline's phantom empty last element. */
168
+ function toLines(text) {
169
+ const lines = text.split('\n');
170
+ if (lines.length > 1 && lines[lines.length - 1] === '')
171
+ lines.pop();
172
+ return lines;
173
+ }
174
+ /** Map raw text lines to styled lines. */
175
+ function styled(lines, style) {
176
+ return lines.map((text) => ({ text, style }));
177
+ }
178
+ /* ------------------------------------------------------------------------- *
179
+ * Shell-shaped results (<COMMAND_OUTPUT>) — run_* / run_shell_command / *
180
+ * custom toolkit tools all share this body shape, so it is detected by *
181
+ * SHAPE, not by name (custom tool names are user-defined). *
182
+ * ------------------------------------------------------------------------- */
183
+ const COMMAND_OUTPUT_RE = /<COMMAND_OUTPUT>\n?([\s\S]*?)<\/COMMAND_OUTPUT>\n?([\s\S]*)$/;
184
+ /**
185
+ * Parse the shared shell-result shape (`Executing '…'…\n\n<COMMAND_OUTPUT>…</COMMAND_OUTPUT>\n\n
186
+ * <status line>`). Returns the captured output body and the trailing status text, or `null`
187
+ * when the result is not shell-shaped.
188
+ */
189
+ export function parseCommandOutputResult(result) {
190
+ if (!result)
191
+ return null;
192
+ const match = COMMAND_OUTPUT_RE.exec(result);
193
+ if (!match)
194
+ return null;
195
+ return { body: match[1] ?? '', tail: (match[2] ?? '').trim() };
196
+ }
197
+ /**
198
+ * TUI-C32 residual c — may this tool NAME be treated as shell-shaped at all? A registered entry
199
+ * must be explicitly {@link ToolDisplayEntry.shellShaped}; an unregistered/custom name falls back
200
+ * to shape-detection (custom toolkit tools own user-defined names yet share the result shape). A
201
+ * registered non-shell tool (`read_file`, `list_directory`, …) is therefore NEVER shell-parsed
202
+ * just because its result happens to contain the `<COMMAND_OUTPUT>` marker.
203
+ */
204
+ function nameAllowsShellShape(name) {
205
+ const entry = TOOL_DISPLAY_REGISTRY[name];
206
+ return entry ? entry.shellShaped === true : true;
207
+ }
208
+ /**
209
+ * TUI-C32 residual c — is THIS tool call genuinely a shell-shaped result (name allows it AND the
210
+ * result actually carries the `<COMMAND_OUTPUT>` shape)? Used by the plain surface to decide
211
+ * `liveOutputAlreadyShown` (the child streamed live via the tool-output channel's default sink),
212
+ * so a non-shell tool whose result merely quotes the marker no longer has its body suppressed.
213
+ */
214
+ export function isShellShapedResult(name, result) {
215
+ return nameAllowsShellShape(name) && parseCommandOutputResult(result) !== null;
216
+ }
217
+ /**
218
+ * Body formatter for shell-shaped calls: the child's output (preferring the LIVE streamed
219
+ * output — verbatim what the child printed — over the result's `<COMMAND_OUTPUT>` copy of it,
220
+ * which is the TUI-C17 dedupe) followed by the closing status line. When the live output
221
+ * already streamed raw to the terminal (plain surface), only the status tail is rendered so
222
+ * nothing the user just watched is repeated.
223
+ */
224
+ function formatShellBody(input) {
225
+ const parsed = parseCommandOutputResult(input.result);
226
+ // Not shell-shaped: only handle the still-running live-output case (a named run_* entry with
227
+ // no result yet). Anything with a non-shell result falls through to the generic rendering so
228
+ // e.g. a hardline refusal text is never dropped.
229
+ if (!parsed && (input.result || !input.output))
230
+ return null;
231
+ const lines = [];
232
+ if (!input.liveOutputAlreadyShown) {
233
+ // TUI-C32 residual d — the streamed live output is normally the verbatim, most-complete copy,
234
+ // so it is preferred (TUI-C17 dedupe). But if the live channel dropped straggler/tail chunks
235
+ // it can be a strict PREFIX of the result's `<COMMAND_OUTPUT>` copy (which the model always
236
+ // receives in full) — in that case fall back to the fuller copy so the expanded view can still
237
+ // recover what the stream missed. The common case (live === result, an independent/capped
238
+ // result, or an empty live output) is unchanged: only a genuine dropped-tail prefix overrides.
239
+ const live = input.output ?? '';
240
+ const resultBody = parsed?.body ?? '';
241
+ const body = resultBody.length > live.length && resultBody.startsWith(live) ? resultBody : live;
242
+ if (body.trim().length > 0)
243
+ lines.push(...styled(toLines(body), 'dim'));
244
+ }
245
+ if (parsed && parsed.tail.length > 0) {
246
+ lines.push(...styled(toLines(parsed.tail), 'dim'));
247
+ }
248
+ return lines.length > 0 ? lines : null;
249
+ }
250
+ /* ------------------------------------------------------------------------- *
251
+ * write_file / edit_file — diff-coloured rendering derived from the ARGS *
252
+ * ------------------------------------------------------------------------- */
253
+ /** `write_file` body: every content line is an ADDED diff line (there is no old content). */
254
+ function formatWriteFileBody(input, args) {
255
+ if (input.isError)
256
+ return null; // fall through: the error text is the story, not the diff
257
+ const content = args?.content;
258
+ if (typeof content !== 'string')
259
+ return null;
260
+ const lines = styled(toLines(content).map((l) => `+ ${l}`), 'added');
261
+ if (input.result && input.result.trim().length > 0) {
262
+ lines.push(...styled(toLines(input.result.trim()), 'dim'));
263
+ }
264
+ return lines;
265
+ }
266
+ /** `edit_file` body: per edit, the removed oldText lines then the added newText lines. */
267
+ function formatEditFileBody(input, args) {
268
+ if (input.isError)
269
+ return null; // fall through: show the recoverable error text instead
270
+ const edits = args?.edits;
271
+ if (!Array.isArray(edits) || edits.length === 0)
272
+ return null;
273
+ const lines = [];
274
+ let rendered = 0;
275
+ for (const raw of edits) {
276
+ const oldText = raw?.oldText;
277
+ const newText = raw?.newText;
278
+ if (typeof oldText !== 'string' || typeof newText !== 'string')
279
+ continue;
280
+ if (rendered > 0)
281
+ lines.push({ text: `${ELLIPSIS}`, style: 'dim' }); // hunk separator
282
+ rendered += 1;
283
+ lines.push(...styled(toLines(oldText).map((l) => `- ${l}`), 'removed'));
284
+ lines.push(...styled(toLines(newText).map((l) => `+ ${l}`), 'added'));
285
+ }
286
+ return rendered > 0 ? lines : null;
287
+ }
288
+ /* ------------------------------------------------------------------------- *
289
+ * The registry *
290
+ * ------------------------------------------------------------------------- */
291
+ /**
292
+ * Named entries. Anything not listed uses the generic fallback (all args summarised,
293
+ * output+result previewed dim) — plus the SHAPE-based shell formatter, which also covers
294
+ * user-named custom toolkit tools (they share the `<COMMAND_OUTPUT>` result shape).
295
+ */
296
+ const TOOL_DISPLAY_REGISTRY = {
297
+ read_file: { glyph: FILE_GLYPH, summariseArgs: ['path', 'offset', 'limit', 'head', 'tail'] },
298
+ read_multiple_files: { glyph: FILE_GLYPH, summariseArgs: ['paths'] },
299
+ gth_read_binary: { glyph: FILE_GLYPH, summariseArgs: ['path'] },
300
+ write_file: { glyph: FILE_GLYPH, summariseArgs: ['path'], formatBody: formatWriteFileBody },
301
+ edit_file: {
302
+ glyph: FILE_GLYPH,
303
+ summariseArgs: ['path', 'dryRun'],
304
+ formatBody: formatEditFileBody,
305
+ },
306
+ create_directory: { glyph: FILE_GLYPH },
307
+ list_directory: { glyph: FILE_GLYPH },
308
+ list_directory_with_sizes: { glyph: FILE_GLYPH },
309
+ directory_tree: { glyph: FILE_GLYPH },
310
+ move_file: { glyph: FILE_GLYPH },
311
+ search_files: { glyph: FILE_GLYPH },
312
+ get_file_info: { glyph: FILE_GLYPH },
313
+ delete_file: { glyph: FILE_GLYPH },
314
+ delete_directory: { glyph: FILE_GLYPH },
315
+ list_allowed_directories: { glyph: FILE_GLYPH },
316
+ run_shell_command: {
317
+ glyph: SHELL_GLYPH,
318
+ summariseArgs: ['command'],
319
+ formatBody: formatShellBody,
320
+ shellShaped: true,
321
+ },
322
+ run_tests: { glyph: SHELL_GLYPH, formatBody: formatShellBody, shellShaped: true },
323
+ run_single_test: {
324
+ glyph: SHELL_GLYPH,
325
+ summariseArgs: ['testPath'],
326
+ formatBody: formatShellBody,
327
+ shellShaped: true,
328
+ },
329
+ run_lint: { glyph: SHELL_GLYPH, formatBody: formatShellBody, shellShaped: true },
330
+ run_build: { glyph: SHELL_GLYPH, formatBody: formatShellBody, shellShaped: true },
331
+ task: { glyph: '🤖', summariseArgs: ['subagent_type', 'description'] },
332
+ };
333
+ /** The registry glyph for a tool name (generic `⚙` when unknown). */
334
+ export function getToolGlyph(name) {
335
+ return TOOL_DISPLAY_REGISTRY[name]?.glyph ?? FALLBACK_GLYPH;
336
+ }
337
+ /* ------------------------------------------------------------------------- *
338
+ * Params summary *
339
+ * ------------------------------------------------------------------------- */
340
+ /**
341
+ * One-line call summary: `name(arg=val, other=…)`. Key args only (per the registry entry, or
342
+ * all args for unknown tools), each value inlined + truncated, the whole parenthesised part
343
+ * capped at {@link TOOL_SUMMARY_MAX_CHARS}, and everything secret-redacted (literals +
344
+ * provider patterns). Unparsable (mid-stream/malformed) args render as `name(…)` — never a
345
+ * raw JSON dump. `secrets` defaults to the env-derived literals; pass explicitly for tests.
346
+ *
347
+ * Redaction runs BEFORE every truncation step (per value in {@link formatParamValue}, and again
348
+ * before the whole-summary cap): truncating first would bisect a literal secret longer than a
349
+ * cap so it no longer literal-matches, leaking its head into the rendered summary
350
+ * (fix-cycle-1 finding). The final pass over the assembled string is defense in depth only —
351
+ * `redactText` is idempotent, so re-redacting already-marked text is safe.
352
+ */
353
+ export function summariseToolCall(name, argsText, secrets = getDefaultSecrets()) {
354
+ const label = name || '(tool)';
355
+ const args = parseToolArgsSafe(argsText);
356
+ if (args === null) {
357
+ const hasRawArgs = !!argsText && argsText.trim().length > 0 && argsText.trim() !== '{}';
358
+ return hasRawArgs ? `${label}(${ELLIPSIS})` : `${label}()`;
359
+ }
360
+ const entry = TOOL_DISPLAY_REGISTRY[name];
361
+ const keys = entry?.summariseArgs !== undefined
362
+ ? entry.summariseArgs.filter((k) => args[k] !== undefined)
363
+ : Object.keys(args);
364
+ const parts = keys.map((k) => `${k}=${formatParamValue(args[k], secrets)}`);
365
+ // Anything parsed but not summarised (write_file's content, unlisted keys) is signalled with
366
+ // a trailing ellipsis so the summary never silently pretends to be the whole call.
367
+ const hasHiddenArgs = entry?.summariseArgs !== undefined && Object.keys(args).some((k) => !keys.includes(k));
368
+ if (hasHiddenArgs)
369
+ parts.push(ELLIPSIS);
370
+ // Redact before the whole-summary cap too, so this truncation can no more bisect a secret
371
+ // out of literal-matching than the per-value one can.
372
+ const inner = truncate(redactText(parts.join(', '), secrets), TOOL_SUMMARY_MAX_CHARS);
373
+ return redactText(`${label}(${inner})`, secrets);
374
+ }
375
+ /* ------------------------------------------------------------------------- *
376
+ * Body + preview *
377
+ * ------------------------------------------------------------------------- */
378
+ /**
379
+ * The FULL (uncapped) body lines for a call: the registry formatter when one applies, else the
380
+ * shape-based shell formatter, else the generic fallback (live output lines, then the final
381
+ * result — both dim). Every line is secret-redacted. Used by the TUI's EXPANDED panel; cap it
382
+ * with {@link capToolDisplayLines} for the collapsed preview.
383
+ */
384
+ export function buildToolBodyLines(input, secrets = getDefaultSecrets()) {
385
+ const args = parseToolArgsSafe(input.argsText);
386
+ const entry = TOOL_DISPLAY_REGISTRY[input.name];
387
+ let lines = entry?.formatBody?.(input, args) ?? null;
388
+ // TUI-C32 residual c — only fall back to the shape-based shell formatter for names that may be
389
+ // shell-shaped (flagged registry entries + unregistered custom tools), so a registered non-shell
390
+ // tool whose result merely contains `<COMMAND_OUTPUT>` is rendered generically, not shell-parsed.
391
+ if (lines === null && nameAllowsShellShape(input.name))
392
+ lines = formatShellBody(input);
393
+ if (lines === null) {
394
+ lines = [];
395
+ if (input.output && input.output.trim().length > 0 && !input.liveOutputAlreadyShown) {
396
+ lines.push(...styled(toLines(input.output), 'dim'));
397
+ }
398
+ if (input.result && input.result.trim().length > 0) {
399
+ lines.push(...styled(toLines(input.result), 'dim'));
400
+ }
401
+ }
402
+ return lines.map((l) => ({ ...l, text: redactText(l.text, secrets) }));
403
+ }
404
+ /**
405
+ * Apply the canonical render cap: at most `maxLines` lines (each char-capped at
406
+ * {@link TOOL_PREVIEW_LINE_MAX_CHARS} with `…`), plus a dim `… (+N more lines)` overflow
407
+ * marker when anything was cut. The marker line is IN ADDITION to the cap so exactly how much
408
+ * was hidden is always stated (DL-4 transparency).
409
+ */
410
+ export function capToolDisplayLines(lines, maxLines = TOOL_OUTPUT_PREVIEW_LINES) {
411
+ const capped = lines.slice(0, maxLines).map((l) => ({
412
+ ...l,
413
+ text: truncate(l.text, TOOL_PREVIEW_LINE_MAX_CHARS),
414
+ }));
415
+ const hidden = lines.length - capped.length;
416
+ if (hidden > 0) {
417
+ capped.push({
418
+ text: `${ELLIPSIS} (+${hidden} more line${hidden === 1 ? '' : 's'})`,
419
+ style: 'dim',
420
+ });
421
+ }
422
+ return capped;
423
+ }
424
+ /**
425
+ * The collapsed inline preview: {@link buildToolBodyLines} capped at the canonical
426
+ * {@link TOOL_OUTPUT_PREVIEW_LINES}.
427
+ */
428
+ export function buildToolPreviewLines(input, secrets = getDefaultSecrets()) {
429
+ return capToolDisplayLines(buildToolBodyLines(input, secrets));
430
+ }
431
+ /* ------------------------------------------------------------------------- *
432
+ * ANSI adapter (plain surface) *
433
+ * ------------------------------------------------------------------------- */
434
+ const ANSI_BY_STYLE = {
435
+ dim: '\x1b[2m',
436
+ added: '\x1b[32m',
437
+ removed: '\x1b[31m',
438
+ };
439
+ const ANSI_RESET = '\x1b[0m';
440
+ /**
441
+ * Render one styled line as a raw string for the plain surface. Each line is SELF-STYLED
442
+ * (its own SGR open + reset) so lines compose safely regardless of surrounding styling.
443
+ * With `colour` false the raw text is returned unchanged — the clean monochrome degradation
444
+ * for non-TTY/piped output (DL-7); diff lines still read via their `+`/`-` prefixes.
445
+ */
446
+ export function renderToolLineAnsi(line, colour) {
447
+ if (!colour)
448
+ return line.text;
449
+ return `${ANSI_BY_STYLE[line.style]}${line.text}${ANSI_RESET}`;
450
+ }
451
+ //# sourceMappingURL=toolDisplay.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"toolDisplay.js","sourceRoot":"","sources":["../../src/core/toolDisplay.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * @module toolOutputChannel
3
+ * TUI-C17 — the managed route for LIVE tool output (a custom/dev toolkit child process's
4
+ * stdout/stderr chunks and its "🔧 Executing …" announcement).
5
+ *
6
+ * The toolkits used to write child output straight to `process.stdout` and announce runs via
7
+ * `displayInfo`. Under the Ink TUI both bypass Ink's managed frame: the raw text prints out of
8
+ * order above the agent message, never reaches the `TurnViewModel`, and vanishes on the next
9
+ * re-render. The fix is an emit/subscribe seam:
10
+ *
11
+ * - The toolkits call {@link emitToolOutput} instead of writing to stdout/`displayInfo`.
12
+ * - With NO subscriber (every non-TUI surface: `--no-tui`, piped, `exec`, the AG-UI server),
13
+ * the DEFAULT SINK reproduces the historical behaviour byte-for-byte — `displayInfo` for the
14
+ * notice, `stdout.write` for chunks, `displayWarning`/`displayError` for a failure-path
15
+ * warning/error — so headless output is unchanged.
16
+ * - The Ink TUI subscribes for the duration of a turn via {@link mergeToolOutputIntoEvents},
17
+ * which converts each chunk into a typed `tool_output` {@link AgentStreamEvent} attributed to
18
+ * its tool call, merged live into the turn's event stream so it lands in `foldEvents`.
19
+ *
20
+ * Single-subscriber by design: one process hosts at most one interactive TUI session, and the
21
+ * non-TUI surfaces never subscribe. (Concurrent server sessions — AG-UI/ACP — stay on the
22
+ * default sink, exactly as before.)
23
+ *
24
+ * TUI-C31 hardens the seam's edge windows: failure-path warnings/errors now travel the channel
25
+ * too ({@link GthToolOutputChunk} `kind: 'warning' | 'error'`, residual a); the merge drains a
26
+ * straggler queued in the unsubscribe microwindow (residual b) and cleans up on early-`return()`
27
+ * (residual c); and {@link setToolOutputSuppressed} lets the mounted TUI suppress a
28
+ * post-unsubscribe straggler between turns instead of leaking it to raw stdout (residual d).
29
+ */
30
+ import type { AgentStreamEvent } from '#src/core/types.js';
31
+ /** One emitted piece of live tool output, attributed to the tool (and call) that produced it. */
32
+ export interface GthToolOutputChunk {
33
+ /**
34
+ * The LangChain tool call id this output belongs to (`ToolRunnableConfig.toolCall.id`),
35
+ * when the invoking framework supplied one. Lets a consumer nest output under the exact call.
36
+ */
37
+ toolCallId?: string;
38
+ /** The gth tool name (e.g. `run_shell_command`, a custom tool's name). Always known. */
39
+ toolName: string;
40
+ /**
41
+ * `notice` — the "🔧 Executing …" announcement (historically `displayInfo`);
42
+ * `output` — a verbatim child stdout/stderr chunk (historically `stdout.write`);
43
+ * `warning` / `error` — a failure-path advisory (historically `displayWarning`/`displayError`),
44
+ * e.g. a hardline refusal or a spawn-level failure. TUI-C31 (a): routing these through the
45
+ * channel keeps them out of raw stdout while the Ink frame is mounted; the default sink still
46
+ * renders them via `displayWarning`/`displayError` for every non-TUI surface, byte-for-byte.
47
+ */
48
+ kind: 'notice' | 'output' | 'warning' | 'error';
49
+ /**
50
+ * The text, verbatim. Notices carry NO leading newline — raw-console framing (the historical
51
+ * leading `\n`) is the default sink's concern, not the producer's. A `warning`/`error` DOES
52
+ * carry whatever leading framing its historical `displayWarning`/`displayError` call had (the
53
+ * default sink forwards it unchanged), so headless output stays byte-for-byte identical.
54
+ */
55
+ text: string;
56
+ }
57
+ export type GthToolOutputListener = (chunk: GthToolOutputChunk) => void;
58
+ /**
59
+ * Subscribe to live tool output, replacing the default stdout/`displayInfo` sink for as long
60
+ * as the subscription is active. Returns an unsubscribe function. Last subscriber wins; the
61
+ * returned unsubscribe only clears its OWN registration (a stale unsubscribe can never detach
62
+ * a newer subscriber).
63
+ */
64
+ export declare function subscribeToolOutput(listener: GthToolOutputListener): () => void;
65
+ /**
66
+ * TUI-C31 (d): mark whether a terminal-owning surface (the Ink TUI) is mounted. While mounted,
67
+ * the default sink SUPPRESSES output that has no per-turn subscriber (a post-turn straggler)
68
+ * rather than writing it raw over the managed frame. The TUI session sets this `true` around the
69
+ * whole session (`render()` … `waitUntilExit()`) and back to `false` on unmount, so once the TUI
70
+ * is gone the default (headless) stdout sink is fully restored. An active per-turn subscriber
71
+ * always takes precedence, so legitimate in-turn output is untouched.
72
+ */
73
+ export declare function setToolOutputSuppressed(value: boolean): void;
74
+ /**
75
+ * Emit one piece of live tool output. Routed to the active subscriber when present (the Ink
76
+ * TUI), otherwise to the DEFAULT SINK, which reproduces the pre-TUI-C17 behaviour exactly:
77
+ * the notice via `displayInfo` with its historical leading newline, chunks via `stdout.write`,
78
+ * a warning via `displayWarning` and an error via `displayError` (TUI-C31 a). While the TUI is
79
+ * mounted but no subscriber is attached (between turns), a no-subscriber emit is SUPPRESSED
80
+ * rather than written raw over the managed frame (TUI-C31 d).
81
+ */
82
+ export declare function emitToolOutput(chunk: GthToolOutputChunk): void;
83
+ /**
84
+ * Merge live tool output into an agent event stream: subscribes to the channel for the
85
+ * lifetime of `inner` and yields each emitted chunk as a `tool_output` event, interleaved
86
+ * with `inner`'s own events in arrival order. Because tool child output arrives WHILE the
87
+ * graph stream is awaiting its next message, the merge is push-based (a woken queue), so a
88
+ * long-running command's output streams into the consumer live rather than batching until
89
+ * the tool finishes.
90
+ *
91
+ * Used by the TUI session around `processMessagesWithEvents`; always unsubscribes (restoring
92
+ * the default stdout sink) when the inner stream completes, throws, or the consumer stops
93
+ * early. Errors from `inner` (including aborts) propagate unchanged after the queue drains.
94
+ */
95
+ export declare function mergeToolOutputIntoEvents(inner: AsyncGenerator<AgentStreamEvent>): AsyncGenerator<AgentStreamEvent>;