@gaunt-sloth/core 2.0.0-alpha.8 → 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.
- package/.gsloth.review.md +2 -0
- package/README.md +71 -20
- package/dist/config/colour.d.ts +38 -0
- package/dist/config/colour.js +36 -0
- package/dist/config/colour.js.map +1 -0
- package/dist/config/configDiscovery.d.ts +79 -0
- package/dist/config/configDiscovery.js +80 -0
- package/dist/config/configDiscovery.js.map +1 -0
- package/dist/config/defaults.d.ts +20 -20
- package/dist/config/defaults.js +10 -8
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/filesystem-tools.d.ts +41 -0
- package/dist/config/filesystem-tools.js +56 -0
- package/dist/config/filesystem-tools.js.map +1 -0
- package/dist/config/loader.d.ts +171 -19
- package/dist/config/loader.js +1054 -144
- package/dist/config/loader.js.map +1 -1
- package/dist/config/mouse.d.ts +50 -0
- package/dist/config/mouse.js +44 -0
- package/dist/config/mouse.js.map +1 -0
- package/dist/config/profiles.d.ts +68 -0
- package/dist/config/profiles.js +93 -0
- package/dist/config/profiles.js.map +1 -0
- package/dist/config/providerKeys.d.ts +69 -0
- package/dist/config/providerKeys.js +69 -0
- package/dist/config/providerKeys.js.map +1 -0
- package/dist/config/schema.d.ts +2671 -138
- package/dist/config/schema.js +1361 -85
- package/dist/config/schema.js.map +1 -1
- package/dist/config/shell-policy.d.ts +899 -111
- package/dist/config/shell-policy.js +800 -70
- package/dist/config/shell-policy.js.map +1 -1
- package/dist/config/tool-descriptions.d.ts +211 -0
- package/dist/config/tool-descriptions.js +272 -0
- package/dist/config/tool-descriptions.js.map +1 -0
- package/dist/config/types.d.ts +352 -41
- package/dist/config/types.js +1 -0
- package/dist/config/types.js.map +1 -1
- package/dist/config.d.ts +35 -1
- package/dist/config.js +16 -1
- package/dist/config.js.map +1 -1
- package/dist/constants.d.ts +28 -1
- package/dist/constants.js +28 -1
- package/dist/constants.js.map +1 -1
- package/dist/core/GthAbstractAgent.d.ts +166 -11
- package/dist/core/GthAbstractAgent.js +484 -45
- package/dist/core/GthAbstractAgent.js.map +1 -1
- package/dist/core/GthAgentRunner.d.ts +543 -57
- package/dist/core/GthAgentRunner.js +1494 -140
- package/dist/core/GthAgentRunner.js.map +1 -1
- package/dist/core/GthLangChainAgent.d.ts +117 -2
- package/dist/core/GthLangChainAgent.js +602 -29
- package/dist/core/GthLangChainAgent.js.map +1 -1
- package/dist/core/approvals/annotations.d.ts +122 -0
- package/dist/core/approvals/annotations.js +137 -0
- package/dist/core/approvals/annotations.js.map +1 -0
- package/dist/core/approvals/grants.d.ts +216 -0
- package/dist/core/approvals/grants.js +469 -0
- package/dist/core/approvals/grants.js.map +1 -0
- package/dist/core/approvals/matcher.d.ts +202 -0
- package/dist/core/approvals/matcher.js +267 -0
- package/dist/core/approvals/matcher.js.map +1 -0
- package/dist/core/approvals/mcpSubjects.d.ts +40 -0
- package/dist/core/approvals/mcpSubjects.js +99 -0
- package/dist/core/approvals/mcpSubjects.js.map +1 -0
- package/dist/core/approvals/promptHeader.d.ts +28 -0
- package/dist/core/approvals/promptHeader.js +62 -0
- package/dist/core/approvals/promptHeader.js.map +1 -0
- package/dist/core/approvals/toolAnnotationSources.d.ts +105 -0
- package/dist/core/approvals/toolAnnotationSources.js +277 -0
- package/dist/core/approvals/toolAnnotationSources.js.map +1 -0
- package/dist/core/approvals/toolHost.d.ts +46 -0
- package/dist/core/approvals/toolHost.js +108 -0
- package/dist/core/approvals/toolHost.js.map +1 -0
- package/dist/core/debugCapture.d.ts +74 -0
- package/dist/core/debugCapture.js +100 -0
- package/dist/core/debugCapture.js.map +1 -0
- package/dist/core/gthLeanAgentFactory.d.ts +4 -4
- package/dist/core/gthLeanAgentFactory.js +4 -4
- package/dist/core/launchBanner.d.ts +127 -0
- package/dist/core/launchBanner.js +414 -0
- package/dist/core/launchBanner.js.map +1 -0
- package/dist/core/modelLabel.d.ts +19 -0
- package/dist/core/modelLabel.js +26 -0
- package/dist/core/modelLabel.js.map +1 -0
- package/dist/core/plainToolIndication.d.ts +15 -0
- package/dist/core/plainToolIndication.js +174 -0
- package/dist/core/plainToolIndication.js.map +1 -0
- package/dist/core/reasoningBlocks.d.ts +65 -0
- package/dist/core/reasoningBlocks.js +103 -0
- package/dist/core/reasoningBlocks.js.map +1 -0
- package/dist/core/refusal.d.ts +53 -0
- package/dist/core/refusal.js +133 -0
- package/dist/core/refusal.js.map +1 -0
- package/dist/core/runHeader.d.ts +38 -0
- package/dist/core/runHeader.js +42 -0
- package/dist/core/runHeader.js.map +1 -0
- package/dist/core/runStats.d.ts +14 -3
- package/dist/core/runStats.js +48 -3
- package/dist/core/runStats.js.map +1 -1
- package/dist/core/shell/ShellCommandFailedError.d.ts +3 -4
- package/dist/core/shell/ShellCommandFailedError.js +3 -4
- package/dist/core/shell/ShellCommandFailedError.js.map +1 -1
- package/dist/core/shell/abstention.d.ts +88 -0
- package/dist/core/shell/abstention.js +184 -0
- package/dist/core/shell/abstention.js.map +1 -0
- package/dist/core/shell/approvalCapture.d.ts +271 -0
- package/dist/core/shell/approvalCapture.js +108 -0
- package/dist/core/shell/approvalCapture.js.map +1 -0
- package/dist/core/shell/approvalStop.d.ts +123 -0
- package/dist/core/shell/approvalStop.js +269 -0
- package/dist/core/shell/approvalStop.js.map +1 -0
- package/dist/core/shell/arity.d.ts +6 -0
- package/dist/core/shell/arity.js +20 -6
- package/dist/core/shell/arity.js.map +1 -1
- package/dist/core/shell/denylist.d.ts +11 -0
- package/dist/core/shell/denylist.js +37 -0
- package/dist/core/shell/denylist.js.map +1 -0
- package/dist/core/shell/escalationSeverity.d.ts +141 -0
- package/dist/core/shell/escalationSeverity.js +89 -0
- package/dist/core/shell/escalationSeverity.js.map +1 -0
- package/dist/core/shell/framing.d.ts +190 -0
- package/dist/core/shell/framing.js +633 -0
- package/dist/core/shell/framing.js.map +1 -0
- package/dist/core/shell/hardline.d.ts +103 -0
- package/dist/core/shell/hardline.js +780 -0
- package/dist/core/shell/hardline.js.map +1 -0
- package/dist/core/shell/negotiation.d.ts +328 -0
- package/dist/core/shell/negotiation.js +488 -0
- package/dist/core/shell/negotiation.js.map +1 -0
- package/dist/core/shell/normalize.d.ts +44 -4
- package/dist/core/shell/normalize.js +61 -7
- package/dist/core/shell/normalize.js.map +1 -1
- package/dist/core/shell/openWorld.d.ts +263 -0
- package/dist/core/shell/openWorld.js +1188 -0
- package/dist/core/shell/openWorld.js.map +1 -0
- package/dist/core/shell/rater.d.ts +873 -0
- package/dist/core/shell/rater.js +1454 -0
- package/dist/core/shell/rater.js.map +1 -0
- package/dist/core/shell/raterModel.d.ts +41 -0
- package/dist/core/shell/raterModel.js +51 -0
- package/dist/core/shell/raterModel.js.map +1 -0
- package/dist/core/shell/raterVocabulary.d.ts +121 -0
- package/dist/core/shell/raterVocabulary.js +116 -0
- package/dist/core/shell/raterVocabulary.js.map +1 -0
- package/dist/core/shell/rejection.d.ts +69 -0
- package/dist/core/shell/rejection.js +38 -0
- package/dist/core/shell/rejection.js.map +1 -0
- package/dist/core/toolCallRepair/grammar.d.ts +41 -0
- package/dist/core/toolCallRepair/grammar.js +116 -0
- package/dist/core/toolCallRepair/grammar.js.map +1 -0
- package/dist/core/toolCallRepair/index.d.ts +2 -0
- package/dist/core/toolCallRepair/index.js +7 -0
- package/dist/core/toolCallRepair/index.js.map +1 -0
- package/dist/core/toolCallRepair/payload.d.ts +36 -0
- package/dist/core/toolCallRepair/payload.js +341 -0
- package/dist/core/toolCallRepair/payload.js.map +1 -0
- package/dist/core/toolCallRepair/promote.d.ts +45 -0
- package/dist/core/toolCallRepair/promote.js +90 -0
- package/dist/core/toolCallRepair/promote.js.map +1 -0
- package/dist/core/toolDisplay.d.ts +123 -0
- package/dist/core/toolDisplay.js +451 -0
- package/dist/core/toolDisplay.js.map +1 -0
- package/dist/core/toolOutputChannel.d.ts +95 -0
- package/dist/core/toolOutputChannel.js +165 -0
- package/dist/core/toolOutputChannel.js.map +1 -0
- package/dist/core/types.d.ts +349 -16
- package/dist/core/types.js.map +1 -1
- package/dist/history/historyFormat.d.ts +12 -3
- package/dist/history/historyFormat.js +50 -8
- package/dist/history/historyFormat.js.map +1 -1
- package/dist/history/historyStore.d.ts +77 -0
- package/dist/history/historyStore.js +173 -6
- package/dist/history/historyStore.js.map +1 -1
- package/dist/history/recordSession.d.ts +10 -1
- package/dist/history/recordSession.js +27 -0
- package/dist/history/recordSession.js.map +1 -1
- package/dist/providers/anthropic.js +12 -0
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/configurationPassthrough.d.ts +107 -0
- package/dist/providers/configurationPassthrough.js +148 -0
- package/dist/providers/configurationPassthrough.js.map +1 -0
- package/dist/providers/geminiSchemaSanitizer.d.ts +55 -0
- package/dist/providers/geminiSchemaSanitizer.js +347 -0
- package/dist/providers/geminiSchemaSanitizer.js.map +1 -0
- package/dist/providers/geminiThinking.d.ts +60 -0
- package/dist/providers/geminiThinking.js +92 -0
- package/dist/providers/geminiThinking.js.map +1 -0
- package/dist/providers/google-genai.js +18 -1
- package/dist/providers/google-genai.js.map +1 -1
- package/dist/providers/groq.js +12 -0
- package/dist/providers/groq.js.map +1 -1
- package/dist/providers/huggingface.d.ts +25 -0
- package/dist/providers/huggingface.js +69 -0
- package/dist/providers/huggingface.js.map +1 -0
- package/dist/providers/modelCatalog.d.ts +109 -0
- package/dist/providers/modelCatalog.js +245 -0
- package/dist/providers/modelCatalog.js.map +1 -0
- package/dist/providers/modelDiscovery.d.ts +99 -5
- package/dist/providers/modelDiscovery.js +191 -35
- package/dist/providers/modelDiscovery.js.map +1 -1
- package/dist/providers/ollama.d.ts +18 -4
- package/dist/providers/ollama.js +67 -37
- package/dist/providers/ollama.js.map +1 -1
- package/dist/providers/openai.js +34 -0
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/openrouter.d.ts +26 -4
- package/dist/providers/openrouter.js +83 -26
- package/dist/providers/openrouter.js.map +1 -1
- package/dist/providers/vertexai.js +19 -1
- package/dist/providers/vertexai.js.map +1 -1
- package/dist/providers/xai.js +20 -0
- package/dist/providers/xai.js.map +1 -1
- package/dist/runtime/askStructured.d.ts +105 -0
- package/dist/runtime/askStructured.js +120 -0
- package/dist/runtime/askStructured.js.map +1 -0
- package/dist/runtime/conversation.d.ts +64 -0
- package/dist/runtime/conversation.js +171 -0
- package/dist/runtime/conversation.js.map +1 -0
- package/dist/runtime/singleShot.d.ts +37 -6
- package/dist/runtime/singleShot.js +113 -67
- package/dist/runtime/singleShot.js.map +1 -1
- package/dist/runtime/structuredOutput.d.ts +104 -0
- package/dist/runtime/structuredOutput.js +393 -0
- package/dist/runtime/structuredOutput.js.map +1 -0
- package/dist/utils/ProgressIndicator.d.ts +21 -0
- package/dist/utils/ProgressIndicator.js +30 -3
- package/dist/utils/ProgressIndicator.js.map +1 -1
- package/dist/utils/aiignoreUtils.js.map +1 -1
- package/dist/utils/binaryOutputUtils.js.map +1 -1
- package/dist/utils/consoleUtils.d.ts +95 -0
- package/dist/utils/consoleUtils.js +112 -2
- package/dist/utils/consoleUtils.js.map +1 -1
- package/dist/utils/crashHandler.d.ts +87 -0
- package/dist/utils/crashHandler.js +128 -0
- package/dist/utils/crashHandler.js.map +1 -0
- package/dist/utils/debugDump.d.ts +134 -0
- package/dist/utils/debugDump.js +381 -0
- package/dist/utils/debugDump.js.map +1 -0
- package/dist/utils/debugUtils.d.ts +13 -4
- package/dist/utils/debugUtils.js +36 -13
- package/dist/utils/debugUtils.js.map +1 -1
- package/dist/utils/displayWidth.d.ts +53 -0
- package/dist/utils/displayWidth.js +195 -0
- package/dist/utils/displayWidth.js.map +1 -0
- package/dist/utils/fileUtils.js.map +1 -1
- package/dist/utils/globalConfigUtils.d.ts +14 -2
- package/dist/utils/globalConfigUtils.js +22 -4
- package/dist/utils/globalConfigUtils.js.map +1 -1
- package/dist/utils/llmUtils.d.ts +39 -8
- package/dist/utils/llmUtils.js +76 -8
- package/dist/utils/llmUtils.js.map +1 -1
- package/dist/utils/redactSecrets.d.ts +63 -0
- package/dist/utils/redactSecrets.js +286 -0
- package/dist/utils/redactSecrets.js.map +1 -0
- package/dist/utils/systemPromptNotes.d.ts +222 -0
- package/dist/utils/systemPromptNotes.js +338 -0
- package/dist/utils/systemPromptNotes.js.map +1 -0
- package/dist/utils/systemUtils.d.ts +18 -1
- package/dist/utils/systemUtils.js +38 -3
- package/dist/utils/systemUtils.js.map +1 -1
- package/dist/utils/toolMatching.d.ts +30 -0
- package/dist/utils/toolMatching.js +44 -0
- package/dist/utils/toolMatching.js.map +1 -0
- package/dist/utils/untrustedText.d.ts +86 -0
- package/dist/utils/untrustedText.js +101 -0
- package/dist/utils/untrustedText.js.map +1 -0
- package/package.json +21 -7
- package/schema/gsloth-config.schema.json +1921 -326
- package/dist/core/shell/allowlist.d.ts +0 -75
- package/dist/core/shell/allowlist.js +0 -187
- package/dist/core/shell/allowlist.js.map +0 -1
- package/dist/core/shell/judge.d.ts +0 -161
- package/dist/core/shell/judge.js +0 -261
- 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[];
|