@gaunt-sloth/core 2.0.0-alpha.9 → 2.0.0-beta.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 (275) hide show
  1. package/.gsloth.review.md +2 -0
  2. package/README.md +71 -20
  3. package/dist/config/colour.d.ts +38 -0
  4. package/dist/config/colour.js +36 -0
  5. package/dist/config/colour.js.map +1 -0
  6. package/dist/config/configDiscovery.d.ts +79 -0
  7. package/dist/config/configDiscovery.js +80 -0
  8. package/dist/config/configDiscovery.js.map +1 -0
  9. package/dist/config/defaults.d.ts +20 -20
  10. package/dist/config/defaults.js +10 -8
  11. package/dist/config/defaults.js.map +1 -1
  12. package/dist/config/filesystem-tools.d.ts +41 -0
  13. package/dist/config/filesystem-tools.js +56 -0
  14. package/dist/config/filesystem-tools.js.map +1 -0
  15. package/dist/config/loader.d.ts +171 -19
  16. package/dist/config/loader.js +1054 -144
  17. package/dist/config/loader.js.map +1 -1
  18. package/dist/config/mouse.d.ts +50 -0
  19. package/dist/config/mouse.js +44 -0
  20. package/dist/config/mouse.js.map +1 -0
  21. package/dist/config/profiles.d.ts +68 -0
  22. package/dist/config/profiles.js +93 -0
  23. package/dist/config/profiles.js.map +1 -0
  24. package/dist/config/providerKeys.d.ts +69 -0
  25. package/dist/config/providerKeys.js +69 -0
  26. package/dist/config/providerKeys.js.map +1 -0
  27. package/dist/config/schema.d.ts +2671 -138
  28. package/dist/config/schema.js +1361 -85
  29. package/dist/config/schema.js.map +1 -1
  30. package/dist/config/shell-policy.d.ts +899 -111
  31. package/dist/config/shell-policy.js +800 -70
  32. package/dist/config/shell-policy.js.map +1 -1
  33. package/dist/config/tool-descriptions.d.ts +211 -0
  34. package/dist/config/tool-descriptions.js +272 -0
  35. package/dist/config/tool-descriptions.js.map +1 -0
  36. package/dist/config/types.d.ts +352 -41
  37. package/dist/config/types.js +1 -0
  38. package/dist/config/types.js.map +1 -1
  39. package/dist/config.d.ts +35 -1
  40. package/dist/config.js +16 -1
  41. package/dist/config.js.map +1 -1
  42. package/dist/constants.d.ts +28 -1
  43. package/dist/constants.js +28 -1
  44. package/dist/constants.js.map +1 -1
  45. package/dist/core/GthAbstractAgent.d.ts +166 -11
  46. package/dist/core/GthAbstractAgent.js +484 -45
  47. package/dist/core/GthAbstractAgent.js.map +1 -1
  48. package/dist/core/GthAgentRunner.d.ts +543 -57
  49. package/dist/core/GthAgentRunner.js +1494 -140
  50. package/dist/core/GthAgentRunner.js.map +1 -1
  51. package/dist/core/GthLangChainAgent.d.ts +117 -2
  52. package/dist/core/GthLangChainAgent.js +602 -29
  53. package/dist/core/GthLangChainAgent.js.map +1 -1
  54. package/dist/core/approvals/annotations.d.ts +122 -0
  55. package/dist/core/approvals/annotations.js +137 -0
  56. package/dist/core/approvals/annotations.js.map +1 -0
  57. package/dist/core/approvals/grants.d.ts +216 -0
  58. package/dist/core/approvals/grants.js +469 -0
  59. package/dist/core/approvals/grants.js.map +1 -0
  60. package/dist/core/approvals/matcher.d.ts +202 -0
  61. package/dist/core/approvals/matcher.js +267 -0
  62. package/dist/core/approvals/matcher.js.map +1 -0
  63. package/dist/core/approvals/mcpSubjects.d.ts +40 -0
  64. package/dist/core/approvals/mcpSubjects.js +99 -0
  65. package/dist/core/approvals/mcpSubjects.js.map +1 -0
  66. package/dist/core/approvals/promptHeader.d.ts +28 -0
  67. package/dist/core/approvals/promptHeader.js +62 -0
  68. package/dist/core/approvals/promptHeader.js.map +1 -0
  69. package/dist/core/approvals/toolAnnotationSources.d.ts +105 -0
  70. package/dist/core/approvals/toolAnnotationSources.js +277 -0
  71. package/dist/core/approvals/toolAnnotationSources.js.map +1 -0
  72. package/dist/core/approvals/toolHost.d.ts +46 -0
  73. package/dist/core/approvals/toolHost.js +108 -0
  74. package/dist/core/approvals/toolHost.js.map +1 -0
  75. package/dist/core/debugCapture.d.ts +74 -0
  76. package/dist/core/debugCapture.js +100 -0
  77. package/dist/core/debugCapture.js.map +1 -0
  78. package/dist/core/gthLeanAgentFactory.d.ts +4 -4
  79. package/dist/core/gthLeanAgentFactory.js +4 -4
  80. package/dist/core/launchBanner.d.ts +127 -0
  81. package/dist/core/launchBanner.js +414 -0
  82. package/dist/core/launchBanner.js.map +1 -0
  83. package/dist/core/modelLabel.d.ts +19 -0
  84. package/dist/core/modelLabel.js +26 -0
  85. package/dist/core/modelLabel.js.map +1 -0
  86. package/dist/core/plainToolIndication.d.ts +15 -0
  87. package/dist/core/plainToolIndication.js +174 -0
  88. package/dist/core/plainToolIndication.js.map +1 -0
  89. package/dist/core/reasoningBlocks.d.ts +65 -0
  90. package/dist/core/reasoningBlocks.js +103 -0
  91. package/dist/core/reasoningBlocks.js.map +1 -0
  92. package/dist/core/refusal.d.ts +53 -0
  93. package/dist/core/refusal.js +133 -0
  94. package/dist/core/refusal.js.map +1 -0
  95. package/dist/core/runHeader.d.ts +38 -0
  96. package/dist/core/runHeader.js +42 -0
  97. package/dist/core/runHeader.js.map +1 -0
  98. package/dist/core/runStats.d.ts +14 -3
  99. package/dist/core/runStats.js +48 -3
  100. package/dist/core/runStats.js.map +1 -1
  101. package/dist/core/shell/ShellCommandFailedError.d.ts +3 -4
  102. package/dist/core/shell/ShellCommandFailedError.js +3 -4
  103. package/dist/core/shell/ShellCommandFailedError.js.map +1 -1
  104. package/dist/core/shell/abstention.d.ts +88 -0
  105. package/dist/core/shell/abstention.js +184 -0
  106. package/dist/core/shell/abstention.js.map +1 -0
  107. package/dist/core/shell/approvalCapture.d.ts +271 -0
  108. package/dist/core/shell/approvalCapture.js +108 -0
  109. package/dist/core/shell/approvalCapture.js.map +1 -0
  110. package/dist/core/shell/approvalStop.d.ts +123 -0
  111. package/dist/core/shell/approvalStop.js +269 -0
  112. package/dist/core/shell/approvalStop.js.map +1 -0
  113. package/dist/core/shell/arity.d.ts +6 -0
  114. package/dist/core/shell/arity.js +20 -6
  115. package/dist/core/shell/arity.js.map +1 -1
  116. package/dist/core/shell/denylist.d.ts +11 -0
  117. package/dist/core/shell/denylist.js +37 -0
  118. package/dist/core/shell/denylist.js.map +1 -0
  119. package/dist/core/shell/escalationSeverity.d.ts +141 -0
  120. package/dist/core/shell/escalationSeverity.js +89 -0
  121. package/dist/core/shell/escalationSeverity.js.map +1 -0
  122. package/dist/core/shell/framing.d.ts +190 -0
  123. package/dist/core/shell/framing.js +633 -0
  124. package/dist/core/shell/framing.js.map +1 -0
  125. package/dist/core/shell/hardline.d.ts +103 -0
  126. package/dist/core/shell/hardline.js +780 -0
  127. package/dist/core/shell/hardline.js.map +1 -0
  128. package/dist/core/shell/negotiation.d.ts +328 -0
  129. package/dist/core/shell/negotiation.js +488 -0
  130. package/dist/core/shell/negotiation.js.map +1 -0
  131. package/dist/core/shell/normalize.d.ts +44 -4
  132. package/dist/core/shell/normalize.js +61 -7
  133. package/dist/core/shell/normalize.js.map +1 -1
  134. package/dist/core/shell/openWorld.d.ts +263 -0
  135. package/dist/core/shell/openWorld.js +1188 -0
  136. package/dist/core/shell/openWorld.js.map +1 -0
  137. package/dist/core/shell/rater.d.ts +873 -0
  138. package/dist/core/shell/rater.js +1454 -0
  139. package/dist/core/shell/rater.js.map +1 -0
  140. package/dist/core/shell/raterModel.d.ts +41 -0
  141. package/dist/core/shell/raterModel.js +51 -0
  142. package/dist/core/shell/raterModel.js.map +1 -0
  143. package/dist/core/shell/raterVocabulary.d.ts +121 -0
  144. package/dist/core/shell/raterVocabulary.js +116 -0
  145. package/dist/core/shell/raterVocabulary.js.map +1 -0
  146. package/dist/core/shell/rejection.d.ts +69 -0
  147. package/dist/core/shell/rejection.js +38 -0
  148. package/dist/core/shell/rejection.js.map +1 -0
  149. package/dist/core/toolCallRepair/grammar.d.ts +41 -0
  150. package/dist/core/toolCallRepair/grammar.js +116 -0
  151. package/dist/core/toolCallRepair/grammar.js.map +1 -0
  152. package/dist/core/toolCallRepair/index.d.ts +2 -0
  153. package/dist/core/toolCallRepair/index.js +7 -0
  154. package/dist/core/toolCallRepair/index.js.map +1 -0
  155. package/dist/core/toolCallRepair/payload.d.ts +36 -0
  156. package/dist/core/toolCallRepair/payload.js +341 -0
  157. package/dist/core/toolCallRepair/payload.js.map +1 -0
  158. package/dist/core/toolCallRepair/promote.d.ts +45 -0
  159. package/dist/core/toolCallRepair/promote.js +90 -0
  160. package/dist/core/toolCallRepair/promote.js.map +1 -0
  161. package/dist/core/toolDisplay.d.ts +123 -0
  162. package/dist/core/toolDisplay.js +451 -0
  163. package/dist/core/toolDisplay.js.map +1 -0
  164. package/dist/core/toolOutputChannel.d.ts +95 -0
  165. package/dist/core/toolOutputChannel.js +165 -0
  166. package/dist/core/toolOutputChannel.js.map +1 -0
  167. package/dist/core/types.d.ts +349 -16
  168. package/dist/core/types.js.map +1 -1
  169. package/dist/history/historyFormat.d.ts +12 -3
  170. package/dist/history/historyFormat.js +50 -8
  171. package/dist/history/historyFormat.js.map +1 -1
  172. package/dist/history/historyStore.d.ts +77 -0
  173. package/dist/history/historyStore.js +173 -6
  174. package/dist/history/historyStore.js.map +1 -1
  175. package/dist/history/recordSession.d.ts +10 -1
  176. package/dist/history/recordSession.js +27 -0
  177. package/dist/history/recordSession.js.map +1 -1
  178. package/dist/providers/anthropic.js +12 -0
  179. package/dist/providers/anthropic.js.map +1 -1
  180. package/dist/providers/configurationPassthrough.d.ts +107 -0
  181. package/dist/providers/configurationPassthrough.js +148 -0
  182. package/dist/providers/configurationPassthrough.js.map +1 -0
  183. package/dist/providers/geminiSchemaSanitizer.d.ts +55 -0
  184. package/dist/providers/geminiSchemaSanitizer.js +347 -0
  185. package/dist/providers/geminiSchemaSanitizer.js.map +1 -0
  186. package/dist/providers/geminiThinking.d.ts +60 -0
  187. package/dist/providers/geminiThinking.js +92 -0
  188. package/dist/providers/geminiThinking.js.map +1 -0
  189. package/dist/providers/google-genai.js +18 -1
  190. package/dist/providers/google-genai.js.map +1 -1
  191. package/dist/providers/groq.js +12 -0
  192. package/dist/providers/groq.js.map +1 -1
  193. package/dist/providers/huggingface.d.ts +25 -0
  194. package/dist/providers/huggingface.js +69 -0
  195. package/dist/providers/huggingface.js.map +1 -0
  196. package/dist/providers/modelCatalog.d.ts +109 -0
  197. package/dist/providers/modelCatalog.js +245 -0
  198. package/dist/providers/modelCatalog.js.map +1 -0
  199. package/dist/providers/modelDiscovery.d.ts +99 -5
  200. package/dist/providers/modelDiscovery.js +191 -35
  201. package/dist/providers/modelDiscovery.js.map +1 -1
  202. package/dist/providers/ollama.d.ts +18 -4
  203. package/dist/providers/ollama.js +67 -37
  204. package/dist/providers/ollama.js.map +1 -1
  205. package/dist/providers/openai.js +34 -0
  206. package/dist/providers/openai.js.map +1 -1
  207. package/dist/providers/openrouter.d.ts +26 -4
  208. package/dist/providers/openrouter.js +83 -26
  209. package/dist/providers/openrouter.js.map +1 -1
  210. package/dist/providers/vertexai.js +19 -1
  211. package/dist/providers/vertexai.js.map +1 -1
  212. package/dist/providers/xai.js +20 -0
  213. package/dist/providers/xai.js.map +1 -1
  214. package/dist/runtime/askStructured.d.ts +105 -0
  215. package/dist/runtime/askStructured.js +120 -0
  216. package/dist/runtime/askStructured.js.map +1 -0
  217. package/dist/runtime/conversation.d.ts +64 -0
  218. package/dist/runtime/conversation.js +171 -0
  219. package/dist/runtime/conversation.js.map +1 -0
  220. package/dist/runtime/singleShot.d.ts +37 -6
  221. package/dist/runtime/singleShot.js +113 -67
  222. package/dist/runtime/singleShot.js.map +1 -1
  223. package/dist/runtime/structuredOutput.d.ts +104 -0
  224. package/dist/runtime/structuredOutput.js +393 -0
  225. package/dist/runtime/structuredOutput.js.map +1 -0
  226. package/dist/utils/ProgressIndicator.d.ts +21 -0
  227. package/dist/utils/ProgressIndicator.js +30 -3
  228. package/dist/utils/ProgressIndicator.js.map +1 -1
  229. package/dist/utils/aiignoreUtils.js.map +1 -1
  230. package/dist/utils/binaryOutputUtils.js.map +1 -1
  231. package/dist/utils/consoleUtils.d.ts +95 -0
  232. package/dist/utils/consoleUtils.js +112 -2
  233. package/dist/utils/consoleUtils.js.map +1 -1
  234. package/dist/utils/crashHandler.d.ts +87 -0
  235. package/dist/utils/crashHandler.js +128 -0
  236. package/dist/utils/crashHandler.js.map +1 -0
  237. package/dist/utils/debugDump.d.ts +134 -0
  238. package/dist/utils/debugDump.js +381 -0
  239. package/dist/utils/debugDump.js.map +1 -0
  240. package/dist/utils/debugUtils.d.ts +13 -4
  241. package/dist/utils/debugUtils.js +36 -13
  242. package/dist/utils/debugUtils.js.map +1 -1
  243. package/dist/utils/displayWidth.d.ts +53 -0
  244. package/dist/utils/displayWidth.js +195 -0
  245. package/dist/utils/displayWidth.js.map +1 -0
  246. package/dist/utils/fileUtils.js.map +1 -1
  247. package/dist/utils/globalConfigUtils.d.ts +14 -2
  248. package/dist/utils/globalConfigUtils.js +22 -4
  249. package/dist/utils/globalConfigUtils.js.map +1 -1
  250. package/dist/utils/llmUtils.d.ts +39 -8
  251. package/dist/utils/llmUtils.js +76 -8
  252. package/dist/utils/llmUtils.js.map +1 -1
  253. package/dist/utils/redactSecrets.d.ts +63 -0
  254. package/dist/utils/redactSecrets.js +286 -0
  255. package/dist/utils/redactSecrets.js.map +1 -0
  256. package/dist/utils/systemPromptNotes.d.ts +222 -0
  257. package/dist/utils/systemPromptNotes.js +338 -0
  258. package/dist/utils/systemPromptNotes.js.map +1 -0
  259. package/dist/utils/systemUtils.d.ts +18 -1
  260. package/dist/utils/systemUtils.js +38 -3
  261. package/dist/utils/systemUtils.js.map +1 -1
  262. package/dist/utils/toolMatching.d.ts +30 -0
  263. package/dist/utils/toolMatching.js +44 -0
  264. package/dist/utils/toolMatching.js.map +1 -0
  265. package/dist/utils/untrustedText.d.ts +86 -0
  266. package/dist/utils/untrustedText.js +101 -0
  267. package/dist/utils/untrustedText.js.map +1 -0
  268. package/package.json +21 -7
  269. package/schema/gsloth-config.schema.json +1921 -326
  270. package/dist/core/shell/allowlist.d.ts +0 -75
  271. package/dist/core/shell/allowlist.js +0 -187
  272. package/dist/core/shell/allowlist.js.map +0 -1
  273. package/dist/core/shell/judge.d.ts +0 -161
  274. package/dist/core/shell/judge.js +0 -261
  275. package/dist/core/shell/judge.js.map +0 -1
@@ -0,0 +1,89 @@
1
+ /**
2
+ * The label above the framed reason.
3
+ *
4
+ * The heading now carries a sentence of the gate's own, so without this the model-authored prose
5
+ * beneath it could be read as a continuation of what the gate said. §6 wants the opposite: the
6
+ * reason is the rater's, quoted, and it is framed exactly like the command for the same reason.
7
+ */
8
+ export const RATER_REASON_LABEL = " the rater's own words:";
9
+ const OUTCOME_DISPLAY = {
10
+ safe: {
11
+ heading: '✓ Auto-rater (safe): no harmful effect found — you are being asked for another reason.',
12
+ tone: 'notice',
13
+ },
14
+ destructive: {
15
+ heading: '⚠ Auto-rater (destructive): this can destroy work or data, but undoing it is possible from ' +
16
+ 'inside this session.',
17
+ tone: 'warn',
18
+ },
19
+ catastrophic: {
20
+ heading: '⛔ Auto-rater (catastrophic): undoing this would need something OUTSIDE this session — ' +
21
+ 'rescue media, a backup, a re-provision, or a restore from someone else.',
22
+ tone: 'danger',
23
+ },
24
+ attack: {
25
+ heading: "⛔ Auto-rater (attack): this command's own STRUCTURE looks hostile — it is shaped to " +
26
+ 'deceive you, take credentials, weaken permissions or persist itself.',
27
+ tone: 'danger',
28
+ },
29
+ };
30
+ /** How to render {@link RaterOutcome} on an approval dialog. */
31
+ export function describeRaterOutcome(outcome) {
32
+ return OUTCOME_DISPLAY[outcome];
33
+ }
34
+ /**
35
+ * [[TUI-C68]] §6.1 — **the phrase that runs an `attack`-rated command anyway.** The only string on
36
+ * the banner that is not a refusal.
37
+ *
38
+ * A typed phrase rather than a key, because an irreversible decision must not be reachable by the
39
+ * muscle memory built answering routine prompts. A key merely *disjoint from today's menu* stops
40
+ * being disjoint the moment someone binds one; a phrase is immune to any future binding. `run`
41
+ * alone was considered and rejected as the leading token of half of what anyone types into a
42
+ * terminal.
43
+ *
44
+ * The label is never `bypass`: that is a rung (§2.5) and a far broader thing — it turns off the
45
+ * rater, the escalation and the halt together, for every command, for the whole run — and a user
46
+ * must never read this banner as switching to it.
47
+ */
48
+ export const RUN_ANYWAY_PHRASE = 'run anyway';
49
+ /**
50
+ * §6.1 — does what the human typed grant this one command?
51
+ *
52
+ * **The whole matching rule, in one place both surfaces call**, so what the banner *says* is
53
+ * answerable and what a surface *accepts* cannot drift. Trimmed, lower-cased, compared whole:
54
+ * `RUN ANYWAY` and a phrase with surrounding spaces grant; `run`, `runanyway`, `run anyway please`
55
+ * and the phrase with a doubled inner space do not. No prefix, no initial, no `y`, no alias.
56
+ *
57
+ * **Everything that is not the phrase is a refusal, and that is the property the banner rests on.**
58
+ * An approval prompt grants only on an offered key and treats every other keystroke as a rejection;
59
+ * a text buffer inverts that by accumulating keystrokes instead of rejecting them, and a matcher
60
+ * this narrow is what puts it back — the buffer may hold anything at all, and only one value of it
61
+ * runs the command.
62
+ *
63
+ * Deliberately NOT whitespace-normalising the middle: a rule that repairs what the user typed is a
64
+ * rule that grants on something they did not type, and retyping a phrase costs nothing next to
65
+ * running this command by accident.
66
+ */
67
+ export function grantsRunAnyway(typed) {
68
+ return typed.trim().toLowerCase() === RUN_ANYWAY_PHRASE;
69
+ }
70
+ /**
71
+ * §6.1 — the banner copy. A function rather than an exported object so one surface cannot mutate
72
+ * the strings another is about to paint.
73
+ */
74
+ export function attackBannerCopy() {
75
+ return {
76
+ title: '⛔ RUN HALTED — the auto-rater rated this command an ATTACK',
77
+ heading: OUTCOME_DISPLAY.attack.heading,
78
+ irreversible: 'If you run it anyway, the consequences may be IRREVERSIBLE.',
79
+ controls: [
80
+ `To run this ONE command: type ${RUN_ANYWAY_PHRASE} and press Enter.`,
81
+ 'Anything else stops the run: any other text, or Enter on its own.',
82
+ 'Nothing is remembered either way — this command is rated again next time.',
83
+ ],
84
+ prompt: 'Your answer: ',
85
+ granted: 'Running this ONE command. The rung is unchanged, nothing was added to the allow-list, ' +
86
+ 'and the next identical command is rated and halted again.',
87
+ };
88
+ }
89
+ //# sourceMappingURL=escalationSeverity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"escalationSeverity.js","sourceRoot":"","sources":["../../../src/core/shell/escalationSeverity.ts"],"names":[],"mappings":"AA6DA;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,4BAA4B,CAAC;AAE/D,MAAM,eAAe,GAA8C;IACjE,IAAI,EAAE;QACJ,OAAO,EACL,wFAAwF;QAC1F,IAAI,EAAE,QAAQ;KACf;IACD,WAAW,EAAE;QACX,OAAO,EACL,6FAA6F;YAC7F,sBAAsB;QACxB,IAAI,EAAE,MAAM;KACb;IACD,YAAY,EAAE;QACZ,OAAO,EACL,wFAAwF;YACxF,yEAAyE;QAC3E,IAAI,EAAE,QAAQ;KACf;IACD,MAAM,EAAE;QACN,OAAO,EACL,sFAAsF;YACtF,sEAAsE;QACxE,IAAI,EAAE,QAAQ;KACf;CACF,CAAC;AAEF,gEAAgE;AAChE,MAAM,UAAU,oBAAoB,CAAC,OAAqB;IACxD,OAAO,eAAe,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,YAAY,CAAC;AAE9C;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,KAAK,iBAAiB,CAAC;AAC1D,CAAC;AAqCD;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO;QACL,KAAK,EAAE,4DAA4D;QACnE,OAAO,EAAE,eAAe,CAAC,MAAM,CAAC,OAAO;QACvC,YAAY,EAAE,6DAA6D;QAC3E,QAAQ,EAAE;YACR,mCAAmC,iBAAiB,qBAAqB;YACzE,mEAAmE;YACnE,2EAA2E;SAC5E;QACD,MAAM,EAAE,eAAe;QACvB,OAAO,EACL,wFAAwF;YACxF,2DAA2D;KAC9D,CAAC;AACJ,CAAC"}
@@ -0,0 +1,190 @@
1
+ /** Column count assumed when the surface cannot report one (not a TTY, a test, a pipe). */
2
+ export declare const DEFAULT_FRAME_WIDTH = 80;
3
+ /**
4
+ * Narrowest frame the gutter will produce, however small the terminal claims to be.
5
+ *
6
+ * Below it the gutter eats the row and the command becomes unreadable, which is its own way of
7
+ * hiding a payload — so a terminal narrower than this gets a frame it cannot fit rather than no
8
+ * frame at all. That trade costs the column-0 guarantee, and {@link narrowTerminalNotice} is what
9
+ * stops it costing it silently.
10
+ */
11
+ export declare const MIN_FRAME_WIDTH = 20;
12
+ /**
13
+ * The width to frame at on a terminal reporting `columns`.
14
+ *
15
+ * One column is held back because a row that fills the last cell wraps on some terminals, and the
16
+ * result is floored at {@link MIN_FRAME_WIDTH}. Both surfaces resolve their width here so they
17
+ * cannot come to disagree about how much of a command a human was shown.
18
+ */
19
+ export declare function frameWidthFor(columns: number | undefined): number;
20
+ /**
21
+ * The line a surface must paint when the terminal is too narrow for the frame to fit in it, or
22
+ * `undefined` when it fits.
23
+ *
24
+ * A guarantee that quietly stops holding is worse than one that says it stopped: below the floor
25
+ * {@link frameWidthFor} keeps the frame readable at the cost of rows wider than the terminal, the
26
+ * terminal wraps them, and a wrapped row puts untrusted text at column 0 — exactly what the gutter
27
+ * exists to prevent. The human is told rather than shown a dialog that still looks like it is
28
+ * guarding them.
29
+ *
30
+ * **Deliberately short, and only the consequence.** It is painted on a terminal of twenty columns
31
+ * or fewer, so it wraps to a few rows however it is worded and every word it does not need is
32
+ * another row of chrome between the reader and the command they are ruling on. It names what goes
33
+ * wrong rather than the width that caused it, because the width is not what the reader has to
34
+ * decide about; the reasoning belongs here, where it has room.
35
+ */
36
+ export declare function narrowTerminalNotice(columns: number | undefined): string | undefined;
37
+ /**
38
+ * Body lines shown before {@link frameUntrustedCommand} starts eliding.
39
+ *
40
+ * Sized so the extracted-site notices, the body and the menu are on screen **together** on a
41
+ * conventional 24-row terminal. That matters more than it looks: rule 3 puts the sites above the
42
+ * body specifically so the eye lands on them, and a body long enough to scroll them off the top
43
+ * defeats it. Bounding the body is safe here in a way the superseded single-line clamp was not,
44
+ * because what is elided is chosen *around the flagged sites* and the count of hidden lines is
45
+ * stated — the payload is what survives, not what is dropped.
46
+ */
47
+ export declare const DEFAULT_FRAME_MAX_LINES = 20;
48
+ /**
49
+ * Rows either of the escalation menu's sticky blocks may occupy — what *approve for this session /
50
+ * always* would remember, and what *always reject* would record.
51
+ *
52
+ * Exported so both surfaces bound them identically: two prompts that disagree about how much of a
53
+ * grant a human was shown is the drift one shared renderer exists to prevent.
54
+ *
55
+ * Four, because that is enough for the ordinary case — a one-line command is one row, its JSON
56
+ * entry two — while keeping an eighteen-line command from printing itself twice more underneath
57
+ * its own frame and pushing the menu off the screen. See {@link clampRows} for the measurement.
58
+ */
59
+ export declare const STICKY_PREVIEW_MAX_ROWS = 4;
60
+ /**
61
+ * Smallest content width the gutter will leave, whatever the terminal claims.
62
+ *
63
+ * Exported alongside {@link wrapToWidth}, so the tests that pin the wrap's floor can state this
64
+ * term rather than repeat the number and quietly drift from it.
65
+ */
66
+ export declare const MIN_CONTENT_WIDTH = 4;
67
+ /** What made the gate unable to resolve a command statically, at one position in it. */
68
+ export type UntrustedSiteKind = 'command substitution' | 'composition';
69
+ /** One extracted decision-relevant position in a command. */
70
+ export interface UntrustedSite {
71
+ /** 1-based line number, matching the gutter the body renders with. */
72
+ line: number;
73
+ /** 1-based display column within that line. */
74
+ column: number;
75
+ kind: UntrustedSiteKind;
76
+ /** The literal token that was found — `$(`, a backtick, `&&`, `||`, `;` or `|`. */
77
+ token: string;
78
+ /** Neutralised text from the site onward, clipped for the notice line. */
79
+ excerpt: string;
80
+ }
81
+ export interface FrameOptions {
82
+ /** Terminal columns available. Rows are wrapped to fit; defaults to {@link DEFAULT_FRAME_WIDTH}. */
83
+ width?: number;
84
+ /** Body lines before elision; defaults to {@link DEFAULT_FRAME_MAX_LINES}. */
85
+ maxLines?: number;
86
+ /**
87
+ * Terminal ROWS this block may occupy, after wrapping. Unbounded when absent.
88
+ *
89
+ * Different from {@link maxLines}, and the difference is the whole reason it exists: `maxLines`
90
+ * bounds the block's *logical* lines, so a single line long enough to wrap forty times is one
91
+ * line and passes the budget untouched. What a screen has is rows.
92
+ *
93
+ * **It bounds `lines` only — `notices` are outside it**, so a block with extracted sites occupies
94
+ * this many rows plus its notices. That is not a gap today: `maxRows` is reached through
95
+ * {@link frameUntrustedText}, which extracts no sites, so those blocks have no notices to bound.
96
+ * A caller passing it to {@link frameUntrustedCommand} instead would get a bound that does not
97
+ * bound the whole block, and needs to widen this rather than assume the name.
98
+ */
99
+ maxRows?: number;
100
+ }
101
+ /** A block of untrusted text, ready to paint. */
102
+ export interface FramedUntrustedText {
103
+ /**
104
+ * Renderer-owned lines to paint **above** the body — the extracted sites, and the statement of
105
+ * anything the elision hid. Empty when there is nothing to say.
106
+ */
107
+ notices: string[];
108
+ /**
109
+ * The body, one terminal row per element, each already carrying its gutter. A surface paints
110
+ * these verbatim and must not re-wrap them: the gutter is the column-0 guarantee, and a second
111
+ * wrap would put untrusted bytes back at column 0.
112
+ */
113
+ lines: string[];
114
+ /** Every site {@link findUnresolvableSites} found, whether or not its line survived elision. */
115
+ sites: UntrustedSite[];
116
+ }
117
+ /**
118
+ * Replace every control and format character with a visible, printable escape.
119
+ *
120
+ * Covers the C0 and C1 control ranges (`\p{Cc}` — which is NUL, BEL, BS, TAB, LF, CR, ESC, DEL and
121
+ * the 0x80–0x9F block including the one-byte CSI), the format characters (`\p{Cf}` — the bidi
122
+ * overrides that reorder what a reader sees, the zero-width joiners, the BOM), and the line and
123
+ * paragraph separators (`\p{Zl}`, `\p{Zp}`). Everything else is left exactly as written: this
124
+ * neutralises, it never sanitises, so the text a human rules on is the text that was proposed.
125
+ *
126
+ * The output alphabet is `\`, `x`, `u`, `{`, `}` and hex digits, none of which is a shell
127
+ * substitution or composition token — so escaping can neither create nor destroy a site that
128
+ * {@link findUnresolvableSites} would report.
129
+ */
130
+ export declare function neutralizeUntrustedText(text: string): string;
131
+ /**
132
+ * Collapse untrusted text to a single safe line, for the line-structured blocks that carry their
133
+ * meaning in their line breaks (the §5 negotiation transcript, the rating prompt's own transcript).
134
+ *
135
+ * Neutralisation runs **first**: JavaScript's `\s` covers LF, CR and TAB but not ESC, BEL, NUL, the
136
+ * C1 range or the bidi overrides, so collapsing whitespace alone leaves a screen-clearing sequence
137
+ * intact on a line that merely looks tidy.
138
+ */
139
+ export declare function neutralizeToOneLine(text: string): string;
140
+ /**
141
+ * Every position in `command` at which the gate could not statically resolve it: each command
142
+ * substitution (`$(` and a backtick) and each composition boundary (`;`, `&&`, `||`, `|`).
143
+ *
144
+ * **Deliberately not quote-aware.** A shell-accurate scanner would skip a `$(` inside single quotes
145
+ * — and the command that motivated this whole surface hid its payload in backticks inside *double*
146
+ * quotes, where the shell expands it. Over-reporting costs a line of notice; under-reporting is the
147
+ * incident. The scan is the same order of simplicity as the ambiguity preflight that actually caught
148
+ * that command, and for the same reason.
149
+ *
150
+ * Scanned over the neutralised lines so the reported line and column are the ones the reader can
151
+ * count to on the screen.
152
+ */
153
+ export declare function findUnresolvableSites(command: string): UntrustedSite[];
154
+ /**
155
+ * Frame the command the agent proposed: neutralised, gutter-numbered, wrapped to the terminal, its
156
+ * unresolvable sites listed above it, and elided around those sites if it is too long to show whole.
157
+ */
158
+ export declare function frameUntrustedCommand(command: string, options?: FrameOptions): FramedUntrustedText;
159
+ /**
160
+ * Frame a block of untrusted prose — the auto-rater's `reason`, or what a sticky choice will store.
161
+ *
162
+ * The same gutter and the same neutralisation as a command, and for the same reason: the rater's
163
+ * explanation is model-authored text on a dialog whose chrome it must not be able to forge. Site
164
+ * extraction does not run, because prose has no composition boundaries to point at; a block with no
165
+ * sites that overruns {@link FrameOptions.maxLines} keeps its head and states what it dropped.
166
+ */
167
+ export declare function frameUntrustedText(text: string, options?: FrameOptions): FramedUntrustedText;
168
+ /**
169
+ * Split one logical line into terminal rows of at most `width` columns.
170
+ *
171
+ * The wrap belongs here rather than to the terminal because a terminal's own wrap starts the
172
+ * continuation at column 0, which is the forgery this module exists to prevent: a single line long
173
+ * enough to wrap can otherwise lay attacker-chosen bytes flush-left, gutter and all bypassed.
174
+ *
175
+ * Measured and cut with the display-width helpers, never `.length` — a CJK ideograph or an emoji is
176
+ * one code point in two columns, and a row measured as fitting that does not fit is a row the
177
+ * terminal wraps back to column 0. Conservatively, so the same holds on a terminal that renders
178
+ * Ambiguous characters wide.
179
+ *
180
+ * The budget is floored at {@link MIN_CONTENT_WIDTH} here rather than taken on trust. The
181
+ * over-wide-cluster branch below escapes a cluster it cannot draw and re-measures it, which
182
+ * advances only if the budget can hold at least one escape character; at a budget of zero it
183
+ * re-escapes its own backslashes forever and the row never terminates. {@link frame} does pass a
184
+ * floored width, but a loop that terminates because of what its only caller happens to do is one
185
+ * the next caller silently breaks.
186
+ *
187
+ * Exported for tests, which pin that termination at a degenerate width — the one width the public
188
+ * entry points cannot produce.
189
+ */
190
+ export declare function wrapToWidth(text: string, width: number): string[];