@gaunt-sloth/core 2.0.0-alpha.4 → 2.0.0-alpha.40

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 (289) hide show
  1. package/README.md +71 -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/configDiscovery.d.ts +79 -0
  6. package/dist/config/configDiscovery.js +80 -0
  7. package/dist/config/configDiscovery.js.map +1 -0
  8. package/dist/config/defaults.d.ts +21 -21
  9. package/dist/config/defaults.js +11 -9
  10. package/dist/config/defaults.js.map +1 -1
  11. package/dist/config/filesystem-tools.d.ts +41 -0
  12. package/dist/config/filesystem-tools.js +56 -0
  13. package/dist/config/filesystem-tools.js.map +1 -0
  14. package/dist/config/jsonc.d.ts +12 -0
  15. package/dist/config/jsonc.js +41 -0
  16. package/dist/config/jsonc.js.map +1 -0
  17. package/dist/config/loader.d.ts +165 -6
  18. package/dist/config/loader.js +963 -109
  19. package/dist/config/loader.js.map +1 -1
  20. package/dist/config/mouse.d.ts +50 -0
  21. package/dist/config/mouse.js +44 -0
  22. package/dist/config/mouse.js.map +1 -0
  23. package/dist/config/profiles.d.ts +68 -0
  24. package/dist/config/profiles.js +93 -0
  25. package/dist/config/profiles.js.map +1 -0
  26. package/dist/config/providerKeys.d.ts +69 -0
  27. package/dist/config/providerKeys.js +69 -0
  28. package/dist/config/providerKeys.js.map +1 -0
  29. package/dist/config/schema.d.ts +2695 -130
  30. package/dist/config/schema.js +1385 -68
  31. package/dist/config/schema.js.map +1 -1
  32. package/dist/config/shell-policy.d.ts +899 -111
  33. package/dist/config/shell-policy.js +800 -70
  34. package/dist/config/shell-policy.js.map +1 -1
  35. package/dist/config/tool-descriptions.d.ts +211 -0
  36. package/dist/config/tool-descriptions.js +272 -0
  37. package/dist/config/tool-descriptions.js.map +1 -0
  38. package/dist/config/types.d.ts +372 -34
  39. package/dist/config/types.js +1 -0
  40. package/dist/config/types.js.map +1 -1
  41. package/dist/config.d.ts +35 -1
  42. package/dist/config.js +16 -1
  43. package/dist/config.js.map +1 -1
  44. package/dist/constants.d.ts +45 -0
  45. package/dist/constants.js +45 -0
  46. package/dist/constants.js.map +1 -1
  47. package/dist/core/GthAbstractAgent.d.ts +190 -11
  48. package/dist/core/GthAbstractAgent.js +551 -35
  49. package/dist/core/GthAbstractAgent.js.map +1 -1
  50. package/dist/core/GthAgentRunner.d.ts +565 -57
  51. package/dist/core/GthAgentRunner.js +1546 -140
  52. package/dist/core/GthAgentRunner.js.map +1 -1
  53. package/dist/core/GthLangChainAgent.d.ts +117 -2
  54. package/dist/core/GthLangChainAgent.js +644 -18
  55. package/dist/core/GthLangChainAgent.js.map +1 -1
  56. package/dist/core/approvals/annotations.d.ts +122 -0
  57. package/dist/core/approvals/annotations.js +137 -0
  58. package/dist/core/approvals/annotations.js.map +1 -0
  59. package/dist/core/approvals/grants.d.ts +216 -0
  60. package/dist/core/approvals/grants.js +469 -0
  61. package/dist/core/approvals/grants.js.map +1 -0
  62. package/dist/core/approvals/matcher.d.ts +202 -0
  63. package/dist/core/approvals/matcher.js +267 -0
  64. package/dist/core/approvals/matcher.js.map +1 -0
  65. package/dist/core/approvals/mcpSubjects.d.ts +40 -0
  66. package/dist/core/approvals/mcpSubjects.js +99 -0
  67. package/dist/core/approvals/mcpSubjects.js.map +1 -0
  68. package/dist/core/approvals/promptHeader.d.ts +28 -0
  69. package/dist/core/approvals/promptHeader.js +62 -0
  70. package/dist/core/approvals/promptHeader.js.map +1 -0
  71. package/dist/core/approvals/toolAnnotationSources.d.ts +105 -0
  72. package/dist/core/approvals/toolAnnotationSources.js +277 -0
  73. package/dist/core/approvals/toolAnnotationSources.js.map +1 -0
  74. package/dist/core/approvals/toolHost.d.ts +46 -0
  75. package/dist/core/approvals/toolHost.js +108 -0
  76. package/dist/core/approvals/toolHost.js.map +1 -0
  77. package/dist/core/debugCapture.d.ts +74 -0
  78. package/dist/core/debugCapture.js +100 -0
  79. package/dist/core/debugCapture.js.map +1 -0
  80. package/dist/core/gthLeanAgentFactory.d.ts +9 -0
  81. package/dist/core/gthLeanAgentFactory.js +10 -0
  82. package/dist/core/gthLeanAgentFactory.js.map +1 -0
  83. package/dist/core/launchBanner.d.ts +127 -0
  84. package/dist/core/launchBanner.js +414 -0
  85. package/dist/core/launchBanner.js.map +1 -0
  86. package/dist/core/modelLabel.d.ts +19 -0
  87. package/dist/core/modelLabel.js +26 -0
  88. package/dist/core/modelLabel.js.map +1 -0
  89. package/dist/core/plainToolIndication.d.ts +15 -0
  90. package/dist/core/plainToolIndication.js +174 -0
  91. package/dist/core/plainToolIndication.js.map +1 -0
  92. package/dist/core/reasoningBlocks.d.ts +65 -0
  93. package/dist/core/reasoningBlocks.js +103 -0
  94. package/dist/core/reasoningBlocks.js.map +1 -0
  95. package/dist/core/refusal.d.ts +53 -0
  96. package/dist/core/refusal.js +133 -0
  97. package/dist/core/refusal.js.map +1 -0
  98. package/dist/core/runHeader.d.ts +38 -0
  99. package/dist/core/runHeader.js +42 -0
  100. package/dist/core/runHeader.js.map +1 -0
  101. package/dist/core/runStats.d.ts +52 -0
  102. package/dist/core/runStats.js +118 -0
  103. package/dist/core/runStats.js.map +1 -0
  104. package/dist/core/shell/ShellCommandFailedError.d.ts +53 -0
  105. package/dist/core/shell/ShellCommandFailedError.js +67 -0
  106. package/dist/core/shell/ShellCommandFailedError.js.map +1 -0
  107. package/dist/core/shell/abstention.d.ts +88 -0
  108. package/dist/core/shell/abstention.js +184 -0
  109. package/dist/core/shell/abstention.js.map +1 -0
  110. package/dist/core/shell/approvalCapture.d.ts +271 -0
  111. package/dist/core/shell/approvalCapture.js +108 -0
  112. package/dist/core/shell/approvalCapture.js.map +1 -0
  113. package/dist/core/shell/approvalStop.d.ts +123 -0
  114. package/dist/core/shell/approvalStop.js +269 -0
  115. package/dist/core/shell/approvalStop.js.map +1 -0
  116. package/dist/core/shell/arity.d.ts +6 -0
  117. package/dist/core/shell/arity.js +20 -6
  118. package/dist/core/shell/arity.js.map +1 -1
  119. package/dist/core/shell/denylist.d.ts +11 -0
  120. package/dist/core/shell/denylist.js +37 -0
  121. package/dist/core/shell/denylist.js.map +1 -0
  122. package/dist/core/shell/escalationSeverity.d.ts +141 -0
  123. package/dist/core/shell/escalationSeverity.js +89 -0
  124. package/dist/core/shell/escalationSeverity.js.map +1 -0
  125. package/dist/core/shell/framing.d.ts +190 -0
  126. package/dist/core/shell/framing.js +633 -0
  127. package/dist/core/shell/framing.js.map +1 -0
  128. package/dist/core/shell/hardline.d.ts +103 -0
  129. package/dist/core/shell/hardline.js +780 -0
  130. package/dist/core/shell/hardline.js.map +1 -0
  131. package/dist/core/shell/negotiation.d.ts +328 -0
  132. package/dist/core/shell/negotiation.js +488 -0
  133. package/dist/core/shell/negotiation.js.map +1 -0
  134. package/dist/core/shell/normalize.d.ts +44 -4
  135. package/dist/core/shell/normalize.js +61 -7
  136. package/dist/core/shell/normalize.js.map +1 -1
  137. package/dist/core/shell/openWorld.d.ts +263 -0
  138. package/dist/core/shell/openWorld.js +1188 -0
  139. package/dist/core/shell/openWorld.js.map +1 -0
  140. package/dist/core/shell/rater.d.ts +873 -0
  141. package/dist/core/shell/rater.js +1454 -0
  142. package/dist/core/shell/rater.js.map +1 -0
  143. package/dist/core/shell/raterModel.d.ts +41 -0
  144. package/dist/core/shell/raterModel.js +51 -0
  145. package/dist/core/shell/raterModel.js.map +1 -0
  146. package/dist/core/shell/raterVocabulary.d.ts +121 -0
  147. package/dist/core/shell/raterVocabulary.js +116 -0
  148. package/dist/core/shell/raterVocabulary.js.map +1 -0
  149. package/dist/core/shell/rejection.d.ts +69 -0
  150. package/dist/core/shell/rejection.js +38 -0
  151. package/dist/core/shell/rejection.js.map +1 -0
  152. package/dist/core/toolCallRepair/grammar.d.ts +41 -0
  153. package/dist/core/toolCallRepair/grammar.js +116 -0
  154. package/dist/core/toolCallRepair/grammar.js.map +1 -0
  155. package/dist/core/toolCallRepair/index.d.ts +2 -0
  156. package/dist/core/toolCallRepair/index.js +7 -0
  157. package/dist/core/toolCallRepair/index.js.map +1 -0
  158. package/dist/core/toolCallRepair/payload.d.ts +36 -0
  159. package/dist/core/toolCallRepair/payload.js +341 -0
  160. package/dist/core/toolCallRepair/payload.js.map +1 -0
  161. package/dist/core/toolCallRepair/promote.d.ts +45 -0
  162. package/dist/core/toolCallRepair/promote.js +90 -0
  163. package/dist/core/toolCallRepair/promote.js.map +1 -0
  164. package/dist/core/toolDisplay.d.ts +123 -0
  165. package/dist/core/toolDisplay.js +451 -0
  166. package/dist/core/toolDisplay.js.map +1 -0
  167. package/dist/core/toolOutputChannel.d.ts +95 -0
  168. package/dist/core/toolOutputChannel.js +165 -0
  169. package/dist/core/toolOutputChannel.js.map +1 -0
  170. package/dist/core/types.d.ts +378 -16
  171. package/dist/core/types.js.map +1 -1
  172. package/dist/history/historyFormat.d.ts +28 -0
  173. package/dist/history/historyFormat.js +127 -0
  174. package/dist/history/historyFormat.js.map +1 -0
  175. package/dist/history/historyStore.d.ts +198 -0
  176. package/dist/history/historyStore.js +482 -0
  177. package/dist/history/historyStore.js.map +1 -0
  178. package/dist/history/recordSession.d.ts +37 -0
  179. package/dist/history/recordSession.js +56 -0
  180. package/dist/history/recordSession.js.map +1 -0
  181. package/dist/index.d.ts +4 -0
  182. package/dist/index.js +4 -0
  183. package/dist/index.js.map +1 -1
  184. package/dist/providers/anthropic.d.ts +1 -1
  185. package/dist/providers/anthropic.js +17 -10
  186. package/dist/providers/anthropic.js.map +1 -1
  187. package/dist/providers/configurationPassthrough.d.ts +107 -0
  188. package/dist/providers/configurationPassthrough.js +148 -0
  189. package/dist/providers/configurationPassthrough.js.map +1 -0
  190. package/dist/providers/deepseek.d.ts +1 -1
  191. package/dist/providers/deepseek.js +5 -10
  192. package/dist/providers/deepseek.js.map +1 -1
  193. package/dist/providers/geminiSchemaSanitizer.d.ts +55 -0
  194. package/dist/providers/geminiSchemaSanitizer.js +347 -0
  195. package/dist/providers/geminiSchemaSanitizer.js.map +1 -0
  196. package/dist/providers/geminiThinking.d.ts +60 -0
  197. package/dist/providers/geminiThinking.js +92 -0
  198. package/dist/providers/geminiThinking.js.map +1 -0
  199. package/dist/providers/google-genai.d.ts +1 -1
  200. package/dist/providers/google-genai.js +23 -11
  201. package/dist/providers/google-genai.js.map +1 -1
  202. package/dist/providers/groq.d.ts +1 -1
  203. package/dist/providers/groq.js +17 -10
  204. package/dist/providers/groq.js.map +1 -1
  205. package/dist/providers/huggingface.d.ts +25 -0
  206. package/dist/providers/huggingface.js +69 -0
  207. package/dist/providers/huggingface.js.map +1 -0
  208. package/dist/providers/modelCatalog.d.ts +109 -0
  209. package/dist/providers/modelCatalog.js +245 -0
  210. package/dist/providers/modelCatalog.js.map +1 -0
  211. package/dist/providers/modelDiscovery.d.ts +153 -6
  212. package/dist/providers/modelDiscovery.js +295 -41
  213. package/dist/providers/modelDiscovery.js.map +1 -1
  214. package/dist/providers/ollama.d.ts +19 -5
  215. package/dist/providers/ollama.js +72 -52
  216. package/dist/providers/ollama.js.map +1 -1
  217. package/dist/providers/openai.d.ts +1 -1
  218. package/dist/providers/openai.js +39 -10
  219. package/dist/providers/openai.js.map +1 -1
  220. package/dist/providers/openrouter.d.ts +27 -5
  221. package/dist/providers/openrouter.js +88 -36
  222. package/dist/providers/openrouter.js.map +1 -1
  223. package/dist/providers/vertexai.d.ts +1 -1
  224. package/dist/providers/vertexai.js +24 -11
  225. package/dist/providers/vertexai.js.map +1 -1
  226. package/dist/providers/xai.d.ts +1 -1
  227. package/dist/providers/xai.js +25 -10
  228. package/dist/providers/xai.js.map +1 -1
  229. package/dist/runtime/askStructured.d.ts +105 -0
  230. package/dist/runtime/askStructured.js +120 -0
  231. package/dist/runtime/askStructured.js.map +1 -0
  232. package/dist/runtime/conversation.d.ts +64 -0
  233. package/dist/runtime/conversation.js +171 -0
  234. package/dist/runtime/conversation.js.map +1 -0
  235. package/dist/runtime/singleShot.d.ts +39 -5
  236. package/dist/runtime/singleShot.js +115 -36
  237. package/dist/runtime/singleShot.js.map +1 -1
  238. package/dist/runtime/structuredOutput.d.ts +104 -0
  239. package/dist/runtime/structuredOutput.js +393 -0
  240. package/dist/runtime/structuredOutput.js.map +1 -0
  241. package/dist/utils/ProgressIndicator.d.ts +21 -0
  242. package/dist/utils/ProgressIndicator.js +30 -3
  243. package/dist/utils/ProgressIndicator.js.map +1 -1
  244. package/dist/utils/aiignoreUtils.js.map +1 -1
  245. package/dist/utils/binaryOutputUtils.js.map +1 -1
  246. package/dist/utils/consoleUtils.d.ts +95 -0
  247. package/dist/utils/consoleUtils.js +112 -2
  248. package/dist/utils/consoleUtils.js.map +1 -1
  249. package/dist/utils/crashHandler.d.ts +87 -0
  250. package/dist/utils/crashHandler.js +128 -0
  251. package/dist/utils/crashHandler.js.map +1 -0
  252. package/dist/utils/debugDump.d.ts +134 -0
  253. package/dist/utils/debugDump.js +381 -0
  254. package/dist/utils/debugDump.js.map +1 -0
  255. package/dist/utils/debugUtils.d.ts +13 -4
  256. package/dist/utils/debugUtils.js +36 -13
  257. package/dist/utils/debugUtils.js.map +1 -1
  258. package/dist/utils/displayWidth.d.ts +53 -0
  259. package/dist/utils/displayWidth.js +195 -0
  260. package/dist/utils/displayWidth.js.map +1 -0
  261. package/dist/utils/fileUtils.d.ts +20 -1
  262. package/dist/utils/fileUtils.js +35 -2
  263. package/dist/utils/fileUtils.js.map +1 -1
  264. package/dist/utils/llmUtils.d.ts +39 -8
  265. package/dist/utils/llmUtils.js +76 -8
  266. package/dist/utils/llmUtils.js.map +1 -1
  267. package/dist/utils/redactSecrets.d.ts +63 -0
  268. package/dist/utils/redactSecrets.js +286 -0
  269. package/dist/utils/redactSecrets.js.map +1 -0
  270. package/dist/utils/systemPromptNotes.d.ts +222 -0
  271. package/dist/utils/systemPromptNotes.js +338 -0
  272. package/dist/utils/systemPromptNotes.js.map +1 -0
  273. package/dist/utils/systemUtils.d.ts +18 -1
  274. package/dist/utils/systemUtils.js +38 -3
  275. package/dist/utils/systemUtils.js.map +1 -1
  276. package/dist/utils/toolMatching.d.ts +30 -0
  277. package/dist/utils/toolMatching.js +44 -0
  278. package/dist/utils/toolMatching.js.map +1 -0
  279. package/dist/utils/untrustedText.d.ts +86 -0
  280. package/dist/utils/untrustedText.js +101 -0
  281. package/dist/utils/untrustedText.js.map +1 -0
  282. package/package.json +21 -6
  283. package/schema/gsloth-config.schema.json +1979 -353
  284. package/dist/core/shell/allowlist.d.ts +0 -75
  285. package/dist/core/shell/allowlist.js +0 -187
  286. package/dist/core/shell/allowlist.js.map +0 -1
  287. package/dist/core/shell/judge.d.ts +0 -161
  288. package/dist/core/shell/judge.js +0 -261
  289. package/dist/core/shell/judge.js.map +0 -1
@@ -0,0 +1,41 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * JSONC (JSON-with-comments) parsing for on-disk `.gsloth.config.json` files.
4
+ *
5
+ * The loader historically `JSON.parse`d config files, which rejects the two things
6
+ * hand-edited config files most want: `//` / `/* … *​/` comments and trailing commas.
7
+ * This wraps Microsoft's zero-dependency `jsonc-parser` so a plain `.json` config may
8
+ * carry both, while a genuinely malformed file still fails with a clear, located error
9
+ * (rather than silently returning `undefined`).
10
+ *
11
+ * `jsonc-parser` is used over a hand-rolled comment-stripper because stripping comments
12
+ * with a regex mishandles `//` / `/*` sequences that appear *inside* string values and
13
+ * escaped quotes; the tokenizer here respects string boundaries correctly. It has no
14
+ * transitive dependencies and is the same parser VS Code uses for its settings files.
15
+ */
16
+ import { parse as parseJsoncTree, printParseErrorCode } from 'jsonc-parser';
17
+ /**
18
+ * Parse a JSONC string (JSON + comments + trailing commas) into a value.
19
+ *
20
+ * On success returns the parsed value. On a structural error (anything `JSON.parse`
21
+ * would also reject, e.g. a missing brace or a dangling property) it throws a `SyntaxError`
22
+ * whose message names the first problem and its 0-based character offset, so the loader's
23
+ * existing "Failed to read config …" diagnostics stay actionable.
24
+ *
25
+ * @param text The file contents.
26
+ * @param sourceLabel Optional human-readable source name, included in the error message.
27
+ */
28
+ export function parseJsonc(text, sourceLabel) {
29
+ const errors = [];
30
+ const value = parseJsoncTree(text, errors, {
31
+ allowTrailingComma: true,
32
+ disallowComments: false,
33
+ });
34
+ if (errors.length > 0) {
35
+ const first = errors[0];
36
+ const where = sourceLabel ? ` in ${sourceLabel}` : '';
37
+ throw new SyntaxError(`Invalid JSON/JSONC${where}: ${printParseErrorCode(first.error)} at offset ${first.offset}.`);
38
+ }
39
+ return value;
40
+ }
41
+ //# sourceMappingURL=jsonc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsonc.js","sourceRoot":"","sources":["../../src/config/jsonc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,KAAK,IAAI,cAAc,EAAmB,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAE7F;;;;;;;;;;GAUG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,WAAoB;IAC3D,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE;QACzC,kBAAkB,EAAE,IAAI;QACxB,gBAAgB,EAAE,KAAK;KACxB,CAAC,CAAC;IACH,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACxB,MAAM,KAAK,GAAG,WAAW,CAAC,CAAC,CAAC,OAAO,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtD,MAAM,IAAI,WAAW,CACnB,qBAAqB,KAAK,KAAK,mBAAmB,CAAC,KAAK,CAAC,KAAK,CAAC,cAAc,KAAK,CAAC,MAAM,GAAG,CAC7F,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -1,3 +1,4 @@
1
+ import { type RawConfigValidationResult } from '#src/config/schema.js';
1
2
  import type { CommandLineConfigOverrides, ConsoleLevelInput, GthConfig, RawGthConfig } from '#src/config/types.js';
2
3
  /**
3
4
  * Find THE project config by walking up from cwd toward a stop boundary, returning the FIRST
@@ -11,6 +12,12 @@ import type { CommandLineConfigOverrides, ConsoleLevelInput, GthConfig, RawGthCo
11
12
  *
12
13
  * A `customConfigPath` override wins outright (no walking).
13
14
  *
15
+ * NOTE (identity profile): with an `identityProfile` set, each dir's per-format resolver
16
+ * ({@link resolveConfigPath}) tries the profile path `.gsloth/.gsloth-settings/<profile>/<file>`
17
+ * but FALLS BACK to the plain `<dir>/<file>` when the profile file is absent. So a match here does
18
+ * NOT prove the named profile itself has a config — it may be a plain (non-profile) config. Use
19
+ * {@link resolveIdentityProfileConfigPath} when you need to know a profile specifically resolved.
20
+ *
14
21
  * @returns the matched `{ dir, path }`, or `undefined` when no project config exists within the
15
22
  * boundary.
16
23
  */
@@ -18,6 +25,30 @@ export declare function findProjectConfigPath(commandLineConfigOverrides: Comman
18
25
  dir: string;
19
26
  path: string;
20
27
  } | undefined;
28
+ /**
29
+ * STRICT existence check for an EXPLICITLY-named identity profile: does
30
+ * `.gsloth/.gsloth-settings/<identityProfile>/<config>` resolve to a real config file anywhere in
31
+ * the same up-tree search {@link findProjectConfigPath} walks? Returns the resolved profile config
32
+ * path (nearest dir, then format precedence) when the profile has its OWN config, `undefined`
33
+ * otherwise.
34
+ *
35
+ * Unlike {@link findProjectConfigPath}, it matches ONLY the profile-specific path — it NEVER falls
36
+ * through to a plain `<dir>/<config>` and NEVER falls back to the global config. That strictness is
37
+ * the whole point: it lets a caller distinguish "this named profile really exists" from "a bare
38
+ * config happens to be present / a global config exists," a distinction the loader's fall-through
39
+ * deliberately blurs.
40
+ *
41
+ * PURE PREDICATE — never throws, never calls `exit`, so it can be asked the question without
42
+ * committing to an outcome. {@link initConfig} uses it to enforce that an explicitly-named profile
43
+ * really exists (raising a catchable {@link ConfigDiscoveryError} when it does not), and callers
44
+ * that want to CLASSIFY rather than fail — BATCH-12's identity matrix checks every declared identity
45
+ * up front so one message can name them all — ask it directly. A blank/whitespace-only name counts
46
+ * as "no profile" → `undefined`.
47
+ *
48
+ * @param identityProfile The explicitly-requested identity profile name.
49
+ * @returns The resolved profile config path, or `undefined` when the profile has no config.
50
+ */
51
+ export declare function resolveIdentityProfileConfigPath(identityProfile: string): string | undefined;
21
52
  /**
22
53
  * Loads the global gsloth config (if present) from the global `~/.gsloth` folder.
23
54
  *
@@ -26,7 +57,7 @@ export declare function findProjectConfigPath(commandLineConfigOverrides: Comman
26
57
  * user-controlled layer (still above {@link DEFAULT_CONFIG}).
27
58
  *
28
59
  * Lookup order within the global folder, first match wins:
29
- * `.gsloth.config.json` -> `.gsloth.config.js` -> `.gsloth.config.mjs`
60
+ * `.gsloth.config.json` -> `.gsloth.config.jsonc` -> `.gsloth.config.js` -> `.gsloth.config.mjs`
30
61
  *
31
62
  * Absence of every variant is a no-op: returns `undefined` so behaviour is unchanged.
32
63
  *
@@ -36,6 +67,40 @@ export declare function findProjectConfigPath(commandLineConfigOverrides: Comman
36
67
  * @returns The raw global config object, or `undefined` when no global config exists.
37
68
  */
38
69
  export declare function loadGlobalRawConfig(): Promise<Partial<RawGthConfig> | undefined>;
70
+ /**
71
+ * GS2-41 — resolve a named profile's `extends` inheritance into a single composed raw config,
72
+ * riding the SAME GS2-1 deep-merge the config LAYERS use (NO second merge engine). When the given
73
+ * profile config declares `extends: "<base>"`, the base profile's config resolves FIRST
74
+ * (recursively — a base may itself extend another, so base-of-base resolves first), then this
75
+ * profile's own fields merge on top with last-wins semantics: the child overrides the base, nested
76
+ * objects merge, arrays REPLACE except the additive-array fields (`allowDirs`, `aiignore.patterns`
77
+ * and the three `approvals` rule lists, see {@link isAdditiveArrayField}) which accumulate
78
+ * base+child. The `extends` key itself is consumed and never leaks into the composed output.
79
+ *
80
+ * A config WITHOUT `extends` is returned UNCHANGED — every non-inheriting config (the vast
81
+ * majority) is untouched and behaves exactly as before.
82
+ *
83
+ * Composition is CONFINED to the profile-dir layer: it produces the single raw config that then
84
+ * acts as the project-file layer the global config underlays and CLI flags overlay, preserving
85
+ * GS2-33's outer precedence `CLI flags > profile (base+child composed) > global > defaults`. It is
86
+ * therefore invoked in {@link initConfig} on the loaded project/profile config BEFORE
87
+ * {@link applyGlobalConfigBase}.
88
+ *
89
+ * The base profile is discovered with {@link resolveIdentityProfileConfigPath} (the SAME strict
90
+ * up-tree profile walk `--profile` uses), so `extends` names a profile exactly as a user selects
91
+ * one; a name with no config dir is a hard, clearly-named error.
92
+ *
93
+ * CYCLE GUARD: the chain of profile NAMES is tracked (seeded with the selected profile's own name);
94
+ * because `extends` is single-valued the chain is linear, so a repeated name — `A extends B extends
95
+ * A`, or a self-extend — is an unambiguous cycle and fails fast with a clear error NAMING the cycle,
96
+ * never infinite-looping / stack-overflowing. A hard {@link MAX_EXTENDS_CHAIN_DEPTH} cap backstops
97
+ * it regardless of how the base path was derived.
98
+ *
99
+ * @param rawConfig the just-loaded, schema-validated raw config that MAY declare `extends`.
100
+ * @param profileLabel the selected profile's own name (for cycle detection + messages); undefined
101
+ * for a plain (non-profile) project config.
102
+ */
103
+ export declare function resolveConfigExtends(rawConfig: Record<string, unknown>, profileLabel: string | undefined): Promise<Record<string, unknown>>;
39
104
  /**
40
105
  * ORDERING INVARIANT (GS2-11): detection ({@link hasProjectConfig}/{@link hasAnyConfig}) MUST run
41
106
  * before {@link initConfig} in a given process. Both resolve cwd-level candidates via
@@ -47,7 +112,7 @@ export declare function loadGlobalRawConfig(): Promise<Partial<RawGthConfig> | u
47
112
  * order is ever introduced, decouple discovery's cwd-branch from `getProjectDir()`.
48
113
  */
49
114
  /**
50
- * Returns true when a project-level config file (json/js/mjs) exists for the given
115
+ * Returns true when a project-level config file (json/jsonc/js/mjs) exists for the given
51
116
  * overrides. Honours `customConfigPath` and the active identity profile so the check
52
117
  * matches exactly what {@link initConfig} would attempt to load.
53
118
  *
@@ -57,12 +122,42 @@ export declare function loadGlobalRawConfig(): Promise<Partial<RawGthConfig> | u
57
122
  export declare function hasProjectConfig(commandLineConfigOverrides: CommandLineConfigOverrides): boolean;
58
123
  /**
59
124
  * CFG-10 — true when ANY usable configuration is present, either a project config file
60
- * (json/js/mjs) or a standalone global config (`~/.gsloth/.gsloth.config.*`). When this
125
+ * (json/jsonc/js/mjs) or a standalone global config (`~/.gsloth/.gsloth.config.*`). When this
61
126
  * returns false the caller should run the first-run dialog instead of erroring.
62
127
  *
63
128
  * Reuses CFG-8's project + global detection so the two paths can never disagree.
64
129
  */
65
130
  export declare function hasAnyConfig(commandLineConfigOverrides: CommandLineConfigOverrides): Promise<boolean>;
131
+ /**
132
+ * CFG-37 — the layered value of the top-level `tui` config key, read BEFORE a session picks its
133
+ * surface. `chat`/`code` choose between the Ink TUI and the readline session in the app's
134
+ * `startSession` dispatcher, and each surface then loads its own config via {@link initConfig} — so
135
+ * at the moment of the choice there is no resolved {@link GthConfig} to consult, and this is the
136
+ * seam that supplies the one key the choice needs.
137
+ *
138
+ * Layering matches a run: the discovered PROJECT layer wins over the GLOBAL one, and a layer that
139
+ * does not set `tui` defers to the next rather than overriding it with `undefined`. A scalar needs
140
+ * no deep merge, so this reads the two layers and picks — it does not fork the merge engine.
141
+ *
142
+ * QUIET and fail-soft for the layers it reads ITSELF: it does not validate them and does not
143
+ * `exit` on a malformed one, because the caller runs moments before {@link initConfig}, which
144
+ * validates every layer and reports the very same problem — warning twice about one file is worse
145
+ * than not warning here. A failed read resolves to `undefined`, i.e. "nobody set it", and the
146
+ * surface auto-detects exactly as it does for a run with no config.
147
+ *
148
+ * ONE EXCEPTION, and it is deliberate: a `tui` may be INHERITED through a GS2-41 profile `extends`
149
+ * chain, so this walks that chain via the SHARED {@link resolveConfigExtends} rather than forking
150
+ * it — and that traversal owns its own reporting. It validates each base layer (so a base's own
151
+ * unknown-key warning can appear here as well as from `initConfig`) and hard-`exit`s on a cycle, a
152
+ * missing base or a malformed base. What the user sees is unchanged — `initConfig` exits on the
153
+ * same chain with the same message a moment later — but it now happens EARLIER, at surface
154
+ * selection rather than at config load. Forking the walk to silence it would mean a second
155
+ * inheritance engine; ignoring `extends` would mean silently dropping an inherited `tui`.
156
+ *
157
+ * Ordering: this is DETECTION, so per the GS2-11 invariant above it must run before any
158
+ * {@link initConfig} in the process — as it does, alongside {@link hasAnyConfig} in `startSession`.
159
+ */
160
+ export declare function loadConfiguredTui(commandLineConfigOverrides: CommandLineConfigOverrides): Promise<boolean | undefined>;
66
161
  /**
67
162
  * Initialize configuration by loading from available config files
68
163
  * @returns The loaded GthConfig
@@ -77,12 +172,76 @@ export declare function initConfig(commandLineConfigOverrides: CommandLineConfig
77
172
  export declare function tryJsonConfig(jsonConfig: RawGthConfig, commandLineConfigOverrides: CommandLineConfigOverrides): Promise<GthConfig>;
78
173
  /**
79
174
  * Resolve a fully-merged {@link GthConfig} from a partial config + CLI overrides WITHOUT
80
- * any global side effects (a pure transform). It deep-merges defaults, applies CLI overrides,
81
- * resolves the numeric `consoleLevel` (warning + defaulting to INFO on an invalid value), and
82
- * computes `canInterruptInferenceWithEsc`. The process-global setters (`setUseColour` /
175
+ * any global side effects. It deep-merges defaults, applies CLI overrides, resolves the numeric
176
+ * `consoleLevel` (warning + defaulting to INFO on an invalid value), and computes
177
+ * `canInterruptInferenceWithEsc` and `useColour`. The process-global setters (`setUseColour` /
83
178
  * `setConsoleLevel`) are applied separately by {@link mergeConfig}, so this function can be
84
179
  * reasoned about and reused without touching global state.
180
+ *
181
+ * It WRITES nothing globally, but it does READ the environment: `canInterruptInferenceWithEsc`
182
+ * consults stdin's TTY status, and (CFG-30) `useColour` consults `FORCE_COLOR`, `NO_COLOR` and
183
+ * stdout's TTY status. So it is deterministic for a given environment rather than a pure function
184
+ * of its arguments — a test that pins a resolved config should declare the terminal and the colour
185
+ * environment it expects in its setup. The ladder itself is a pure helper
186
+ * ({@link resolveUseColour}) so it can be tested rung by rung without process globals.
85
187
  */
86
188
  export declare function resolveConfig(partialConfig: Omit<Partial<GthConfig>, 'consoleLevel'> & {
87
189
  consoleLevel?: ConsoleLevelInput;
88
190
  }, commandLineConfigOverrides: CommandLineConfigOverrides): GthConfig;
191
+ /**
192
+ * One config LAYER's validation outcome inside a {@link ConfigValidationReport}: the pure
193
+ * read-side result ({@link validateRawGthConfig}) plus the source label so a consumer can name
194
+ * WHICH file carried a warning/error (the project path, or `"<name> (global)"`).
195
+ */
196
+ export interface ConfigLayerValidationReport extends RawConfigValidationResult {
197
+ /** The resolved config path (project layer) or `"<name> (global)"` (global layer). */
198
+ sourceLabel: string;
199
+ }
200
+ /**
201
+ * The outcome of `gth config validate`: whether any config was found, and the per-layer verdict
202
+ * for EVERY layer a run would validate. Pure/read-side — it neither builds an LLM nor mutates
203
+ * process globals, so it can report a verdict without the run-path's side effects. The command
204
+ * layer turns this into console output + an exit code.
205
+ *
206
+ * GS2-29 — `validateConfig` mirrors the layer set `initConfig` validates: the discovered PROJECT
207
+ * layer (if any) AND the GLOBAL layer (if any). A run validates both and exits(1) if EITHER
208
+ * carries a problem, so a removed shape in the global config (with a clean project config) shows
209
+ * up here exactly as the run would reject it. Both layers are kept in {@link layers} (in run
210
+ * order) so the offending file is always identifiable.
211
+ */
212
+ export interface ConfigValidationReport {
213
+ /** False when neither a project nor a global config exists within the discovery boundary. */
214
+ found: boolean;
215
+ /** True only when a config was found AND every present layer validates OK. */
216
+ ok: boolean;
217
+ /**
218
+ * Each config layer a run would load + validate, in run order: the discovered PROJECT layer
219
+ * (if any) first, then the GLOBAL layer (if any). Empty when `found` is false.
220
+ */
221
+ layers: ConfigLayerValidationReport[];
222
+ }
223
+ /**
224
+ * Locate and validate the effective raw config against the schema WITHOUT building the LLM
225
+ * or merging defaults (the read-side of GS2-1). Honours `--config`, up-tree discovery, and the
226
+ * identity profile via {@link findProjectConfigPath}.
227
+ *
228
+ * GS2-29 — validates the SAME layer set a real run does: the discovered PROJECT layer (if any)
229
+ * AND the GLOBAL layer (if any), mirroring `initConfig`'s `validateRawConfigLayer(project)` +
230
+ * `applyGlobalConfigBase` → `loadGlobalRawConfig(global)`. Each present layer is validated
231
+ * independently ({@link validateRawGthConfig}) and its outcome recorded in {@link
232
+ * ConfigValidationReport.layers}, so a removed shape in EITHER file is reported (labelled with
233
+ * its source) rather than under-reported.
234
+ *
235
+ * A PROJECT-layer JSONC/module parse failure is thrown to the caller (surfaced as a clear
236
+ * "invalid config" error + non-zero exit). A GLOBAL-layer parse failure is treated as an absent
237
+ * global (no layer added) but is surfaced with a `displayWarning` — exactly as a run does (it
238
+ * warns the user while ignoring the broken global's value) — see {@link
239
+ * loadGlobalRawConfigUnvalidated}.
240
+ *
241
+ * GS2-73 — for the PROJECT layer it also walks the GS2-41 profile `extends` chain (via the SAME
242
+ * {@link composeExtends}/{@link resolveExtendsChain} the run path uses), so a cycle or a missing
243
+ * base — which fail a real run — is reported here as a not-ok layer instead of passing OK and only
244
+ * failing at run time. The GLOBAL layer is NOT walked, mirroring the run (`resolveConfigExtends`
245
+ * runs on the project/profile layer only).
246
+ */
247
+ export declare function validateConfig(commandLineConfigOverrides: CommandLineConfigOverrides): Promise<ConfigValidationReport>;