@gaunt-sloth/core 2.0.0-alpha.2 → 2.0.0-alpha.20

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 (149) hide show
  1. package/.gsloth.code.md +10 -0
  2. package/README.md +6 -6
  3. package/dist/config/defaults.d.ts +85 -0
  4. package/dist/config/defaults.js +103 -0
  5. package/dist/config/defaults.js.map +1 -0
  6. package/dist/config/jsonc.d.ts +12 -0
  7. package/dist/config/jsonc.js +41 -0
  8. package/dist/config/jsonc.js.map +1 -0
  9. package/dist/config/loader.d.ts +169 -0
  10. package/dist/config/loader.js +872 -0
  11. package/dist/config/loader.js.map +1 -0
  12. package/dist/config/schema.d.ts +672 -0
  13. package/dist/config/schema.js +519 -0
  14. package/dist/config/schema.js.map +1 -0
  15. package/dist/config/shell-policy.d.ts +331 -0
  16. package/dist/config/shell-policy.js +238 -0
  17. package/dist/config/shell-policy.js.map +1 -0
  18. package/dist/config/types.d.ts +586 -0
  19. package/dist/config/types.js +13 -0
  20. package/dist/config/types.js.map +1 -0
  21. package/dist/config.d.ts +18 -647
  22. package/dist/config.js +15 -516
  23. package/dist/config.js.map +1 -1
  24. package/dist/constants.d.ts +42 -0
  25. package/dist/constants.js +42 -0
  26. package/dist/constants.js.map +1 -1
  27. package/dist/core/GthAbstractAgent.d.ts +85 -2
  28. package/dist/core/GthAbstractAgent.js +389 -28
  29. package/dist/core/GthAbstractAgent.js.map +1 -1
  30. package/dist/core/GthAgentRunner.d.ts +158 -1
  31. package/dist/core/GthAgentRunner.js +367 -4
  32. package/dist/core/GthAgentRunner.js.map +1 -1
  33. package/dist/core/GthLangChainAgent.js +193 -16
  34. package/dist/core/GthLangChainAgent.js.map +1 -1
  35. package/dist/core/debugCapture.d.ts +59 -0
  36. package/dist/core/debugCapture.js +101 -0
  37. package/dist/core/debugCapture.js.map +1 -0
  38. package/dist/core/gthLeanAgentFactory.d.ts +9 -0
  39. package/dist/core/gthLeanAgentFactory.js +10 -0
  40. package/dist/core/gthLeanAgentFactory.js.map +1 -0
  41. package/dist/core/runStats.d.ts +41 -0
  42. package/dist/core/runStats.js +73 -0
  43. package/dist/core/runStats.js.map +1 -0
  44. package/dist/core/shell/ShellCommandFailedError.d.ts +54 -0
  45. package/dist/core/shell/ShellCommandFailedError.js +68 -0
  46. package/dist/core/shell/ShellCommandFailedError.js.map +1 -0
  47. package/dist/core/shell/allowlist.d.ts +75 -0
  48. package/dist/core/shell/allowlist.js +187 -0
  49. package/dist/core/shell/allowlist.js.map +1 -0
  50. package/dist/core/shell/arity.d.ts +75 -0
  51. package/dist/core/shell/arity.js +313 -0
  52. package/dist/core/shell/arity.js.map +1 -0
  53. package/dist/core/shell/judge.d.ts +161 -0
  54. package/dist/core/shell/judge.js +261 -0
  55. package/dist/core/shell/judge.js.map +1 -0
  56. package/dist/core/shell/normalize.d.ts +27 -0
  57. package/dist/core/shell/normalize.js +53 -0
  58. package/dist/core/shell/normalize.js.map +1 -0
  59. package/dist/core/types.d.ts +145 -0
  60. package/dist/core/types.js.map +1 -1
  61. package/dist/history/historyFormat.d.ts +28 -0
  62. package/dist/history/historyFormat.js +127 -0
  63. package/dist/history/historyFormat.js.map +1 -0
  64. package/dist/history/historyStore.d.ts +198 -0
  65. package/dist/history/historyStore.js +482 -0
  66. package/dist/history/historyStore.js.map +1 -0
  67. package/dist/history/recordSession.d.ts +37 -0
  68. package/dist/history/recordSession.js +56 -0
  69. package/dist/history/recordSession.js.map +1 -0
  70. package/dist/index.d.ts +4 -0
  71. package/dist/index.js +4 -0
  72. package/dist/index.js.map +1 -1
  73. package/dist/providers/anthropic.d.ts +1 -1
  74. package/dist/providers/anthropic.js +5 -10
  75. package/dist/providers/anthropic.js.map +1 -1
  76. package/dist/providers/deepseek.d.ts +1 -1
  77. package/dist/providers/deepseek.js +5 -10
  78. package/dist/providers/deepseek.js.map +1 -1
  79. package/dist/providers/geminiSchemaSanitizer.d.ts +52 -0
  80. package/dist/providers/geminiSchemaSanitizer.js +201 -0
  81. package/dist/providers/geminiSchemaSanitizer.js.map +1 -0
  82. package/dist/providers/google-genai.d.ts +1 -1
  83. package/dist/providers/google-genai.js +9 -11
  84. package/dist/providers/google-genai.js.map +1 -1
  85. package/dist/providers/groq.d.ts +1 -1
  86. package/dist/providers/groq.js +5 -10
  87. package/dist/providers/groq.js.map +1 -1
  88. package/dist/providers/huggingface.d.ts +25 -0
  89. package/dist/providers/huggingface.js +69 -0
  90. package/dist/providers/huggingface.js.map +1 -0
  91. package/dist/providers/modelCatalog.d.ts +109 -0
  92. package/dist/providers/modelCatalog.js +245 -0
  93. package/dist/providers/modelCatalog.js.map +1 -0
  94. package/dist/providers/modelDiscovery.d.ts +111 -3
  95. package/dist/providers/modelDiscovery.js +183 -27
  96. package/dist/providers/modelDiscovery.js.map +1 -1
  97. package/dist/providers/ollama.d.ts +19 -5
  98. package/dist/providers/ollama.js +60 -52
  99. package/dist/providers/ollama.js.map +1 -1
  100. package/dist/providers/openai.d.ts +1 -1
  101. package/dist/providers/openai.js +5 -10
  102. package/dist/providers/openai.js.map +1 -1
  103. package/dist/providers/openrouter.d.ts +1 -1
  104. package/dist/providers/openrouter.js +12 -12
  105. package/dist/providers/openrouter.js.map +1 -1
  106. package/dist/providers/vertexai.d.ts +1 -1
  107. package/dist/providers/vertexai.js +9 -11
  108. package/dist/providers/vertexai.js.map +1 -1
  109. package/dist/providers/xai.d.ts +1 -1
  110. package/dist/providers/xai.js +5 -10
  111. package/dist/providers/xai.js.map +1 -1
  112. package/dist/runtime/askStructured.d.ts +62 -0
  113. package/dist/runtime/askStructured.js +76 -0
  114. package/dist/runtime/askStructured.js.map +1 -0
  115. package/dist/runtime/conversation.d.ts +59 -0
  116. package/dist/runtime/conversation.js +137 -0
  117. package/dist/runtime/conversation.js.map +1 -0
  118. package/dist/runtime/singleShot.d.ts +24 -5
  119. package/dist/runtime/singleShot.js +56 -9
  120. package/dist/runtime/singleShot.js.map +1 -1
  121. package/dist/utils/aiignoreUtils.js.map +1 -1
  122. package/dist/utils/binaryOutputUtils.js.map +1 -1
  123. package/dist/utils/consoleUtils.d.ts +13 -0
  124. package/dist/utils/consoleUtils.js +31 -0
  125. package/dist/utils/consoleUtils.js.map +1 -1
  126. package/dist/utils/debugDump.d.ts +57 -0
  127. package/dist/utils/debugDump.js +236 -0
  128. package/dist/utils/debugDump.js.map +1 -0
  129. package/dist/utils/debugUtils.d.ts +13 -4
  130. package/dist/utils/debugUtils.js +36 -13
  131. package/dist/utils/debugUtils.js.map +1 -1
  132. package/dist/utils/fileUtils.d.ts +24 -2
  133. package/dist/utils/fileUtils.js +54 -12
  134. package/dist/utils/fileUtils.js.map +1 -1
  135. package/dist/utils/llmUtils.js.map +1 -1
  136. package/dist/utils/redactSecrets.d.ts +63 -0
  137. package/dist/utils/redactSecrets.js +238 -0
  138. package/dist/utils/redactSecrets.js.map +1 -0
  139. package/dist/utils/systemPromptNotes.d.ts +181 -0
  140. package/dist/utils/systemPromptNotes.js +298 -0
  141. package/dist/utils/systemPromptNotes.js.map +1 -0
  142. package/dist/utils/systemUtils.d.ts +32 -1
  143. package/dist/utils/systemUtils.js +50 -3
  144. package/dist/utils/systemUtils.js.map +1 -1
  145. package/dist/utils/toolMatching.d.ts +30 -0
  146. package/dist/utils/toolMatching.js +44 -0
  147. package/dist/utils/toolMatching.js.map +1 -0
  148. package/package.json +17 -8
  149. package/schema/gsloth-config.schema.json +2102 -0
package/.gsloth.code.md CHANGED
@@ -16,6 +16,16 @@ You have access to the entire project directory and can:
16
16
  - Create new files and directories as needed
17
17
  - Execute commands to run tests, build the project or run static analysis (lint)
18
18
 
19
+ ## File paths
20
+
21
+ - Paths are real absolute filesystem paths — there is no virtual root. The current
22
+ working directory is provided to you separately; do NOT assume it is `/`.
23
+ - The filesystem tools (`ls`/`glob`/`read_file`/`write_file`/`edit_file`/`grep`) and
24
+ `run_shell_command` share the same real paths. A path that works in the shell works
25
+ in the filesystem tools and vice versa.
26
+ - Relative paths resolve against the working directory. Check the current directory
27
+ before filesystem operations and prefer absolute paths when unsure.
28
+
19
29
  Focus on writing clean, maintainable code that follows the project's established patterns and conventions. Always test your changes when possible and explain what you're doing and why.
20
30
 
21
31
  ## Running tests
package/README.md CHANGED
@@ -11,7 +11,7 @@ Core utilities and types for Gaunt Sloth.
11
11
  - State and artifact storage: `artifactStore`
12
12
  - Shared constants and types
13
13
 
14
- AI vendor packages are not direct dependencies. Each vendor package is an optional peer dependency, resolved at runtime by whichever consumer (e.g. `gaunt-sloth-assistant`) pulls them in.
14
+ AI vendor packages are not direct dependencies. Each vendor package is an optional peer dependency, resolved at runtime by whichever consumer (e.g. `gaunt-sloth`) pulls them in.
15
15
 
16
16
  ## Dependencies
17
17
 
@@ -28,8 +28,8 @@ import { display } from '@gaunt-sloth/core/utils/consoleUtils.js';
28
28
 
29
29
  ## Related packages
30
30
 
31
- - [`@gaunt-sloth/core`](../core) — Core utilities, config, and agent infrastructure (this package)
32
- - [`@gaunt-sloth/tools`](../tools) — Built-in tools, filesystem toolkit, and middleware registry
33
- - [`@gaunt-sloth/api`](../api) — API server, AG-UI, MCP, and A2A integration
34
- - [`@gaunt-sloth/review`](../review) — Review and Q&A modules with standalone CLI
35
- - [`gaunt-sloth-assistant`](../assistant) — Main CLI application
31
+ - [`@gaunt-sloth/core`](https://www.npmjs.com/package/@gaunt-sloth/core) — Core utilities, config, and agent infrastructure (this package) ([source](https://github.com/pukeko-robotics/gaunt-sloth/tree/main/packages/core))
32
+ - [`@gaunt-sloth/agent`](https://www.npmjs.com/package/@gaunt-sloth/agent) — Agent runtime: built-in tools, filesystem toolkit, middleware registry, API server, AG-UI, MCP, and A2A integration ([source](https://github.com/pukeko-robotics/gaunt-sloth/tree/main/packages/agent))
33
+ - [`@gaunt-sloth/review`](https://www.npmjs.com/package/@gaunt-sloth/review) — Review and Q&A modules with standalone CLI ([source](https://github.com/pukeko-robotics/gaunt-sloth/tree/main/packages/review))
34
+ - [`@gaunt-sloth/batch`](https://www.npmjs.com/package/@gaunt-sloth/batch) — Batch / eval / workflow runtime ([source](https://github.com/pukeko-robotics/gaunt-sloth/tree/main/packages/batch))
35
+ - [`gaunt-sloth`](https://www.npmjs.com/package/gaunt-sloth) — Main CLI application ([source](https://github.com/pukeko-robotics/gaunt-sloth/tree/main/packages/app))
@@ -0,0 +1,85 @@
1
+ import { StatusLevel } from '#src/core/types.js';
2
+ /**
3
+ * Default config
4
+ */
5
+ export declare const DEFAULT_CONFIG: {
6
+ readonly contentSource: 'file';
7
+ readonly requirementSource: 'file';
8
+ /**
9
+ * Path to project-specific guidelines.
10
+ * The default is `.gsloth.guidelines.md`; this config may be used to point Gaunt Sloth to a different file,
11
+ * for example, to AGENTS.md
12
+ */
13
+ readonly projectGuidelines: ".gsloth.guidelines.md";
14
+ /**
15
+ * Whether to include the current date in the project review instructions or not.
16
+ */
17
+ readonly includeCurrentDateAfterGuidelines: false;
18
+ readonly projectReviewInstructions: ".gsloth.review.md";
19
+ readonly filesystem: 'none';
20
+ readonly builtInTools: string[];
21
+ readonly debugLog: false;
22
+ readonly consoleLevel: StatusLevel.INFO;
23
+ /**
24
+ * Default source for both requirements and content is GitHub.
25
+ * It needs GitHub CLI (gh).
26
+ *
27
+ * `github` content source uses `gh pr diff NN` internally. {@link src/sources/ghPrDiffSource.ts!}
28
+ *
29
+ *
30
+ * `github` requirement source uses `gh issue view NN` internally
31
+ */
32
+ readonly commands: {
33
+ readonly pr: {
34
+ readonly contentSource: 'github';
35
+ readonly requirementSource: 'github';
36
+ readonly rating: {
37
+ readonly enabled: true;
38
+ readonly passThreshold: 6;
39
+ readonly minRating: 0;
40
+ readonly maxRating: 10;
41
+ readonly errorOnReviewFail: true;
42
+ };
43
+ };
44
+ readonly review: {
45
+ readonly rating: {
46
+ readonly enabled: true;
47
+ readonly passThreshold: 6;
48
+ readonly minRating: 0;
49
+ readonly maxRating: 10;
50
+ readonly errorOnReviewFail: true;
51
+ };
52
+ };
53
+ readonly ask: {
54
+ readonly filesystem: 'read';
55
+ };
56
+ readonly chat: {
57
+ readonly filesystem: 'read';
58
+ };
59
+ readonly code: {
60
+ readonly filesystem: 'all';
61
+ };
62
+ readonly exec: {
63
+ readonly filesystem: 'all';
64
+ };
65
+ readonly api: {
66
+ readonly filesystem: 'read';
67
+ readonly port: 3000;
68
+ readonly cors: {
69
+ readonly allowOrigin: 'http://localhost:3000';
70
+ readonly allowMethods: 'POST, GET, OPTIONS';
71
+ readonly allowHeaders: 'Content-Type, Accept';
72
+ };
73
+ };
74
+ };
75
+ readonly streamOutput: true;
76
+ readonly writeOutputToFile: false;
77
+ readonly writeBinaryOutputsToFile: true;
78
+ readonly useColour: true;
79
+ readonly streamSessionInferenceLog: true;
80
+ readonly canInterruptInferenceWithEsc: true;
81
+ readonly aiignore: {
82
+ readonly enabled: true;
83
+ readonly patterns: undefined;
84
+ };
85
+ };
@@ -0,0 +1,103 @@
1
+ /**
2
+ * @packageDocumentation
3
+ * Default Gaunt Sloth configuration ({@link DEFAULT_CONFIG}). Extracted verbatim from
4
+ * the former `config.ts` god-file; values are unchanged.
5
+ */
6
+ import { PROJECT_GUIDELINES, PROJECT_REVIEW_INSTRUCTIONS } from '#src/constants.js';
7
+ import { StatusLevel } from '#src/core/types.js';
8
+ /**
9
+ * Default config
10
+ */
11
+ export const DEFAULT_CONFIG = {
12
+ contentSource: 'file',
13
+ requirementSource: 'file',
14
+ /**
15
+ * Path to project-specific guidelines.
16
+ * The default is `.gsloth.guidelines.md`; this config may be used to point Gaunt Sloth to a different file,
17
+ * for example, to AGENTS.md
18
+ */
19
+ projectGuidelines: PROJECT_GUIDELINES,
20
+ /**
21
+ * Whether to include the current date in the project review instructions or not.
22
+ */
23
+ includeCurrentDateAfterGuidelines: false,
24
+ projectReviewInstructions: PROJECT_REVIEW_INSTRUCTIONS,
25
+ filesystem: 'none',
26
+ // Enabled built-in tools. `gth_checklist` (the lean agent's planning/todo tool) and `gth_grep`
27
+ // (the permission-light content-search tool, GS2-51) are on by default across commands; a user
28
+ // `builtInTools` setting replaces this set entirely. Both are named to coexist with the deep
29
+ // backend's own `write_todos`/`grep` built-ins. Cast keeps it a mutable `string[]` under the
30
+ // surrounding `as const`.
31
+ builtInTools: ['gth_checklist', 'gth_grep'],
32
+ debugLog: false,
33
+ consoleLevel: StatusLevel.INFO, // Default to INFO level, not debug
34
+ /**
35
+ * Default source for both requirements and content is GitHub.
36
+ * It needs GitHub CLI (gh).
37
+ *
38
+ * `github` content source uses `gh pr diff NN` internally. {@link src/sources/ghPrDiffSource.ts!}
39
+ *
40
+ *
41
+ * `github` requirement source uses `gh issue view NN` internally
42
+ */
43
+ commands: {
44
+ pr: {
45
+ contentSource: 'github',
46
+ requirementSource: 'github',
47
+ rating: {
48
+ enabled: true,
49
+ passThreshold: 6,
50
+ minRating: 0,
51
+ maxRating: 10,
52
+ errorOnReviewFail: true,
53
+ },
54
+ },
55
+ review: {
56
+ rating: {
57
+ enabled: true,
58
+ passThreshold: 6,
59
+ minRating: 0,
60
+ maxRating: 10,
61
+ errorOnReviewFail: true,
62
+ },
63
+ },
64
+ ask: {
65
+ filesystem: 'read',
66
+ },
67
+ chat: {
68
+ filesystem: 'read',
69
+ },
70
+ code: {
71
+ filesystem: 'all',
72
+ },
73
+ exec: {
74
+ filesystem: 'all',
75
+ },
76
+ api: {
77
+ filesystem: 'read',
78
+ port: 3000,
79
+ cors: {
80
+ allowOrigin: 'http://localhost:3000',
81
+ allowMethods: 'POST, GET, OPTIONS',
82
+ allowHeaders: 'Content-Type, Accept',
83
+ },
84
+ },
85
+ },
86
+ streamOutput: true,
87
+ writeOutputToFile: false,
88
+ writeBinaryOutputsToFile: true,
89
+ useColour: true,
90
+ streamSessionInferenceLog: true,
91
+ canInterruptInferenceWithEsc: true,
92
+ aiignore: {
93
+ enabled: true,
94
+ patterns: undefined,
95
+ },
96
+ };
97
+ /**
98
+ * Needed DEFAULT_CONFIG to be plain const to be picked up by typedoc,
99
+ * this cast here is just for typecheck.
100
+ */
101
+ // eslint-disable-next-line @typescript-eslint/no-unused-expressions
102
+ DEFAULT_CONFIG;
103
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,kBAAkB,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGjD;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,aAAa,EAAE,MAAM;IACrB,iBAAiB,EAAE,MAAM;IACzB;;;;OAIG;IACH,iBAAiB,EAAE,kBAAkB;IACrC;;OAEG;IACH,iCAAiC,EAAE,KAAK;IACxC,yBAAyB,EAAE,2BAA2B;IACtD,UAAU,EAAE,MAAM;IAClB,+FAA+F;IAC/F,+FAA+F;IAC/F,6FAA6F;IAC7F,6FAA6F;IAC7F,0BAA0B;IAC1B,YAAY,EAAE,CAAC,eAAe,EAAE,UAAU,CAAa;IACvD,QAAQ,EAAE,KAAK;IACf,YAAY,EAAE,WAAW,CAAC,IAAI,EAAE,mCAAmC;IACnE;;;;;;;;OAQG;IACH,QAAQ,EAAE;QACR,EAAE,EAAE;YACF,aAAa,EAAE,QAAQ;YACvB,iBAAiB,EAAE,QAAQ;YAC3B,MAAM,EAAE;gBACN,OAAO,EAAE,IAAI;gBACb,aAAa,EAAE,CAAC;gBAChB,SAAS,EAAE,CAAC;gBACZ,SAAS,EAAE,EAAE;gBACb,iBAAiB,EAAE,IAAI;aACxB;SACF;QACD,MAAM,EAAE;YACN,MAAM,EAAE;gBACN,OAAO,EAAE,IAAI;gBACb,aAAa,EAAE,CAAC;gBAChB,SAAS,EAAE,CAAC;gBACZ,SAAS,EAAE,EAAE;gBACb,iBAAiB,EAAE,IAAI;aACxB;SACF;QACD,GAAG,EAAE;YACH,UAAU,EAAE,MAAM;SACnB;QACD,IAAI,EAAE;YACJ,UAAU,EAAE,MAAM;SACnB;QACD,IAAI,EAAE;YACJ,UAAU,EAAE,KAAK;SAClB;QACD,IAAI,EAAE;YACJ,UAAU,EAAE,KAAK;SAClB;QACD,GAAG,EAAE;YACH,UAAU,EAAE,MAAM;YAClB,IAAI,EAAE,IAAI;YACV,IAAI,EAAE;gBACJ,WAAW,EAAE,uBAAuB;gBACpC,YAAY,EAAE,oBAAoB;gBAClC,YAAY,EAAE,sBAAsB;aACrC;SACF;KACF;IACD,YAAY,EAAE,IAAI;IAClB,iBAAiB,EAAE,KAAK;IACxB,wBAAwB,EAAE,IAAI;IAC9B,SAAS,EAAE,IAAI;IACf,yBAAyB,EAAE,IAAI;IAC/B,4BAA4B,EAAE,IAAI;IAClC,QAAQ,EAAE;QACR,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,SAAS;KACpB;CACO,CAAC;AAEX;;;GAGG;AACH,oEAAoE;AACpE,cAA2B,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Parse a JSONC string (JSON + comments + trailing commas) into a value.
3
+ *
4
+ * On success returns the parsed value. On a structural error (anything `JSON.parse`
5
+ * would also reject, e.g. a missing brace or a dangling property) it throws a `SyntaxError`
6
+ * whose message names the first problem and its 0-based character offset, so the loader's
7
+ * existing "Failed to read config …" diagnostics stay actionable.
8
+ *
9
+ * @param text The file contents.
10
+ * @param sourceLabel Optional human-readable source name, included in the error message.
11
+ */
12
+ export declare function parseJsonc(text: string, sourceLabel?: string): unknown;
@@ -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"}
@@ -0,0 +1,169 @@
1
+ import { type RawConfigValidationResult } from '#src/config/schema.js';
2
+ import type { CommandLineConfigOverrides, ConsoleLevelInput, GthConfig, RawGthConfig } from '#src/config/types.js';
3
+ /**
4
+ * Find THE project config by walking up from cwd toward a stop boundary, returning the FIRST
5
+ * match (first-match-win: nearest dir, then format precedence within that dir — NOT a merged
6
+ * stack). Detection ({@link hasProjectConfig}/{@link hasAnyConfig}) and loading ({@link initConfig})
7
+ * both go through this, so they can never disagree.
8
+ *
9
+ * Stop boundary — the dir is SEARCHED, then ascent stops at: a dir containing `.git` (the git
10
+ * root), the user's home dir, or the filesystem root — whichever comes first. So a config IN the
11
+ * git root (or home) is found; a config ABOVE it is not.
12
+ *
13
+ * A `customConfigPath` override wins outright (no walking).
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
+ *
21
+ * @returns the matched `{ dir, path }`, or `undefined` when no project config exists within the
22
+ * boundary.
23
+ */
24
+ export declare function findProjectConfigPath(commandLineConfigOverrides: CommandLineConfigOverrides): {
25
+ dir: string;
26
+ path: string;
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` (contrast the loader's interactive-CLI
42
+ * `exit(1)` safety net in {@link initConfig}). So batch/eval code (e.g. `gth eval --judge <profile>`
43
+ * and BATCH-12's identity matrix) can pre-check an explicitly-requested profile and raise its OWN
44
+ * catchable error / graceful exit code instead of dying on an uncatchable `process.exit`. A
45
+ * blank/whitespace-only name counts as "no profile" → `undefined`.
46
+ *
47
+ * @param identityProfile The explicitly-requested identity profile name.
48
+ * @returns The resolved profile config path, or `undefined` when the profile has no config.
49
+ */
50
+ export declare function resolveIdentityProfileConfigPath(identityProfile: string): string | undefined;
51
+ /**
52
+ * Loads the global gsloth config (if present) from the global `~/.gsloth` folder.
53
+ *
54
+ * Precedence support: the returned raw config is intended to act as the BASE that the
55
+ * project config (and CLI overrides) merge on top of, so any value here is the lowest
56
+ * user-controlled layer (still above {@link DEFAULT_CONFIG}).
57
+ *
58
+ * Lookup order within the global folder, first match wins:
59
+ * `.gsloth.config.json` -> `.gsloth.config.js` -> `.gsloth.config.mjs`
60
+ *
61
+ * Absence of every variant is a no-op: returns `undefined` so behaviour is unchanged.
62
+ *
63
+ * NOTE: secrets (API keys) may live in this file; this function must never log its
64
+ * contents. Only non-sensitive diagnostics (the resolved path / parse failure) are emitted.
65
+ *
66
+ * @returns The raw global config object, or `undefined` when no global config exists.
67
+ */
68
+ export declare function loadGlobalRawConfig(): Promise<Partial<RawGthConfig> | undefined>;
69
+ /**
70
+ * ORDERING INVARIANT (GS2-11): detection ({@link hasProjectConfig}/{@link hasAnyConfig}) MUST run
71
+ * before {@link initConfig} in a given process. Both resolve cwd-level candidates via
72
+ * `getGslothConfigReadPath`, which reads `getProjectDir()`; {@link initConfig} clears `projectDir`
73
+ * at the start of its run, so detection stays cwd-correct as long as it precedes initConfig (it
74
+ * does: startSession calls hasAnyConfig before any initConfig, and the ACP/agent path calls
75
+ * initConfig directly without detection). Calling detection AFTER an initConfig with a changed cwd
76
+ * in a long-lived process would read a stale projectDir (currently unreachable). If that call
77
+ * order is ever introduced, decouple discovery's cwd-branch from `getProjectDir()`.
78
+ */
79
+ /**
80
+ * Returns true when a project-level config file (json/js/mjs) exists for the given
81
+ * overrides. Honours `customConfigPath` and the active identity profile so the check
82
+ * matches exactly what {@link initConfig} would attempt to load.
83
+ *
84
+ * This is the project half of CFG-10's "is any config present?" detection; the global
85
+ * half is {@link loadGlobalRawConfig} (used by {@link hasAnyConfig}).
86
+ */
87
+ export declare function hasProjectConfig(commandLineConfigOverrides: CommandLineConfigOverrides): boolean;
88
+ /**
89
+ * CFG-10 — true when ANY usable configuration is present, either a project config file
90
+ * (json/js/mjs) or a standalone global config (`~/.gsloth/.gsloth.config.*`). When this
91
+ * returns false the caller should run the first-run dialog instead of erroring.
92
+ *
93
+ * Reuses CFG-8's project + global detection so the two paths can never disagree.
94
+ */
95
+ export declare function hasAnyConfig(commandLineConfigOverrides: CommandLineConfigOverrides): Promise<boolean>;
96
+ /**
97
+ * Initialize configuration by loading from available config files
98
+ * @returns The loaded GthConfig
99
+ */
100
+ export declare function initConfig(commandLineConfigOverrides: CommandLineConfigOverrides): Promise<GthConfig>;
101
+ /**
102
+ * Process JSON LLM config by creating the appropriate LLM instance
103
+ * @param jsonConfig - The parsed JSON config
104
+ * @param commandLineConfigOverrides - command line config overrides
105
+ * @returns Promise<GthConfig>
106
+ */
107
+ export declare function tryJsonConfig(jsonConfig: RawGthConfig, commandLineConfigOverrides: CommandLineConfigOverrides): Promise<GthConfig>;
108
+ /**
109
+ * Resolve a fully-merged {@link GthConfig} from a partial config + CLI overrides WITHOUT
110
+ * any global side effects (a pure transform). It deep-merges defaults, applies CLI overrides,
111
+ * resolves the numeric `consoleLevel` (warning + defaulting to INFO on an invalid value), and
112
+ * computes `canInterruptInferenceWithEsc`. The process-global setters (`setUseColour` /
113
+ * `setConsoleLevel`) are applied separately by {@link mergeConfig}, so this function can be
114
+ * reasoned about and reused without touching global state.
115
+ */
116
+ export declare function resolveConfig(partialConfig: Omit<Partial<GthConfig>, 'consoleLevel'> & {
117
+ consoleLevel?: ConsoleLevelInput;
118
+ }, commandLineConfigOverrides: CommandLineConfigOverrides): GthConfig;
119
+ /**
120
+ * One config LAYER's validation outcome inside a {@link ConfigValidationReport}: the pure
121
+ * read-side result ({@link validateRawGthConfig}) plus the source label so a consumer can name
122
+ * WHICH file carried a warning/error (the project path, or `"<name> (global)"`).
123
+ */
124
+ export interface ConfigLayerValidationReport extends RawConfigValidationResult {
125
+ /** The resolved config path (project layer) or `"<name> (global)"` (global layer). */
126
+ sourceLabel: string;
127
+ }
128
+ /**
129
+ * The outcome of `gth config validate`: whether any config was found, and the per-layer verdict
130
+ * for EVERY layer a run would validate. Pure/read-side — it neither builds an LLM nor mutates
131
+ * process globals, so it can report a verdict without the run-path's side effects. The command
132
+ * layer turns this into console output + an exit code.
133
+ *
134
+ * GS2-29 — `validateConfig` mirrors the layer set `initConfig` validates: the discovered PROJECT
135
+ * layer (if any) AND the GLOBAL layer (if any). A run validates both and exits(1) if EITHER
136
+ * carries a problem, so a removed shape in the global config (with a clean project config) shows
137
+ * up here exactly as the run would reject it. Both layers are kept in {@link layers} (in run
138
+ * order) so the offending file is always identifiable.
139
+ */
140
+ export interface ConfigValidationReport {
141
+ /** False when neither a project nor a global config exists within the discovery boundary. */
142
+ found: boolean;
143
+ /** True only when a config was found AND every present layer validates OK. */
144
+ ok: boolean;
145
+ /**
146
+ * Each config layer a run would load + validate, in run order: the discovered PROJECT layer
147
+ * (if any) first, then the GLOBAL layer (if any). Empty when `found` is false.
148
+ */
149
+ layers: ConfigLayerValidationReport[];
150
+ }
151
+ /**
152
+ * Locate and validate the effective raw config against the schema WITHOUT building the LLM
153
+ * or merging defaults (the read-side of GS2-1). Honours `--config`, up-tree discovery, and the
154
+ * identity profile via {@link findProjectConfigPath}.
155
+ *
156
+ * GS2-29 — validates the SAME layer set a real run does: the discovered PROJECT layer (if any)
157
+ * AND the GLOBAL layer (if any), mirroring `initConfig`'s `validateRawConfigLayer(project)` +
158
+ * `applyGlobalConfigBase` → `loadGlobalRawConfig(global)`. Each present layer is validated
159
+ * independently ({@link validateRawGthConfig}) and its outcome recorded in {@link
160
+ * ConfigValidationReport.layers}, so a removed shape in EITHER file is reported (labelled with
161
+ * its source) rather than under-reported.
162
+ *
163
+ * A PROJECT-layer JSONC/module parse failure is thrown to the caller (surfaced as a clear
164
+ * "invalid config" error + non-zero exit). A GLOBAL-layer parse failure is treated as an absent
165
+ * global (no layer added) but is surfaced with a `displayWarning` — exactly as a run does (it
166
+ * warns the user while ignoring the broken global's value) — see {@link
167
+ * loadGlobalRawConfigUnvalidated}.
168
+ */
169
+ export declare function validateConfig(commandLineConfigOverrides: CommandLineConfigOverrides): Promise<ConfigValidationReport>;