@gaunt-sloth/core 2.0.0-alpha.3 → 2.0.0-alpha.30
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/README.md +52 -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/defaults.d.ts +84 -0
- package/dist/config/defaults.js +99 -0
- package/dist/config/defaults.js.map +1 -0
- 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/jsonc.d.ts +12 -0
- package/dist/config/jsonc.js +41 -0
- package/dist/config/jsonc.js.map +1 -0
- package/dist/config/loader.d.ts +246 -0
- package/dist/config/loader.js +1321 -0
- package/dist/config/loader.js.map +1 -0
- 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 +2999 -0
- package/dist/config/schema.js +1519 -0
- package/dist/config/schema.js.map +1 -0
- package/dist/config/shell-policy.d.ts +896 -0
- package/dist/config/shell-policy.js +750 -0
- package/dist/config/shell-policy.js.map +1 -0
- 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 +760 -0
- package/dist/config/types.js +13 -0
- package/dist/config/types.js.map +1 -0
- package/dist/config.d.ts +34 -827
- package/dist/config.js +25 -657
- package/dist/config.js.map +1 -1
- package/dist/constants.d.ts +46 -0
- package/dist/constants.js +46 -0
- package/dist/constants.js.map +1 -1
- package/dist/core/GthAbstractAgent.d.ts +135 -2
- package/dist/core/GthAbstractAgent.js +496 -30
- package/dist/core/GthAbstractAgent.js.map +1 -1
- package/dist/core/GthAgentRunner.d.ts +568 -54
- package/dist/core/GthAgentRunner.js +1537 -136
- package/dist/core/GthAgentRunner.js.map +1 -1
- package/dist/core/GthLangChainAgent.d.ts +115 -0
- package/dist/core/GthLangChainAgent.js +644 -17
- 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/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 +75 -0
- package/dist/core/debugCapture.js +101 -0
- package/dist/core/debugCapture.js.map +1 -0
- package/dist/core/gthLeanAgentFactory.d.ts +9 -0
- package/dist/core/gthLeanAgentFactory.js +10 -0
- package/dist/core/gthLeanAgentFactory.js.map +1 -0
- package/dist/core/launchBanner.d.ts +120 -0
- package/dist/core/launchBanner.js +418 -0
- package/dist/core/launchBanner.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 +60 -0
- package/dist/core/reasoningBlocks.js +98 -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/runStats.d.ts +52 -0
- package/dist/core/runStats.js +118 -0
- package/dist/core/runStats.js.map +1 -0
- package/dist/core/shell/ShellCommandFailedError.d.ts +54 -0
- package/dist/core/shell/ShellCommandFailedError.js +68 -0
- package/dist/core/shell/ShellCommandFailedError.js.map +1 -0
- 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 +84 -0
- package/dist/core/shell/approvalStop.js +119 -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 +81 -0
- package/dist/core/shell/hardline.js +607 -0
- package/dist/core/shell/hardline.js.map +1 -0
- package/dist/core/shell/negotiation.d.ts +249 -0
- package/dist/core/shell/negotiation.js +355 -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 +935 -0
- package/dist/core/shell/rater.js +1473 -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/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 +294 -12
- package/dist/core/types.js.map +1 -1
- package/dist/history/historyFormat.d.ts +28 -0
- package/dist/history/historyFormat.js +127 -0
- package/dist/history/historyFormat.js.map +1 -0
- package/dist/history/historyStore.d.ts +198 -0
- package/dist/history/historyStore.js +482 -0
- package/dist/history/historyStore.js.map +1 -0
- package/dist/history/recordSession.d.ts +37 -0
- package/dist/history/recordSession.js +56 -0
- package/dist/history/recordSession.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/anthropic.js +5 -10
- package/dist/providers/anthropic.js.map +1 -1
- package/dist/providers/deepseek.d.ts +1 -1
- package/dist/providers/deepseek.js +5 -10
- package/dist/providers/deepseek.js.map +1 -1
- 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 +52 -0
- package/dist/providers/geminiThinking.js +72 -0
- package/dist/providers/geminiThinking.js.map +1 -0
- package/dist/providers/google-genai.d.ts +1 -1
- package/dist/providers/google-genai.js +12 -11
- package/dist/providers/google-genai.js.map +1 -1
- package/dist/providers/groq.d.ts +1 -1
- package/dist/providers/groq.js +5 -10
- 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 +153 -6
- package/dist/providers/modelDiscovery.js +295 -41
- package/dist/providers/modelDiscovery.js.map +1 -1
- package/dist/providers/ollama.d.ts +19 -5
- package/dist/providers/ollama.js +60 -52
- package/dist/providers/ollama.js.map +1 -1
- package/dist/providers/openai.d.ts +1 -1
- package/dist/providers/openai.js +39 -10
- package/dist/providers/openai.js.map +1 -1
- package/dist/providers/openrouter.d.ts +4 -5
- package/dist/providers/openrouter.js +20 -35
- package/dist/providers/openrouter.js.map +1 -1
- package/dist/providers/vertexai.d.ts +1 -1
- package/dist/providers/vertexai.js +12 -11
- package/dist/providers/vertexai.js.map +1 -1
- package/dist/providers/xai.d.ts +1 -1
- package/dist/providers/xai.js +5 -10
- 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 +60 -0
- package/dist/runtime/conversation.js +151 -0
- package/dist/runtime/conversation.js.map +1 -0
- package/dist/runtime/singleShot.d.ts +25 -5
- package/dist/runtime/singleShot.js +95 -36
- 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 +52 -0
- package/dist/utils/consoleUtils.js +72 -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.d.ts +24 -2
- package/dist/utils/fileUtils.js +54 -12
- package/dist/utils/fileUtils.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 +225 -0
- package/dist/utils/systemPromptNotes.js +340 -0
- package/dist/utils/systemPromptNotes.js.map +1 -0
- package/dist/utils/systemUtils.d.ts +49 -1
- package/dist/utils/systemUtils.js +67 -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 +66 -0
- package/dist/utils/untrustedText.js +80 -0
- package/dist/utils/untrustedText.js.map +1 -0
- package/package.json +22 -6
- package/schema/gsloth-config.schema.json +3134 -0
- 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
package/dist/providers/ollama.js
CHANGED
|
@@ -1,77 +1,85 @@
|
|
|
1
1
|
import { displayWarning } from '#src/utils/consoleUtils.js';
|
|
2
2
|
import { env } from '#src/utils/systemUtils.js';
|
|
3
|
-
import {
|
|
3
|
+
import { writeConfigFileWithMessages } from '#src/utils/fileUtils.js';
|
|
4
|
+
import { buildInitConfigContent, getCuratedFallbackModel } from '#src/providers/modelDiscovery.js';
|
|
4
5
|
/**
|
|
5
|
-
* Default Ollama daemon host, matching the Ollama CLI/library default.
|
|
6
|
-
*
|
|
7
|
-
*
|
|
6
|
+
* Default Ollama daemon host, matching the Ollama CLI/library default. GS2-59 — `ChatOllama` talks
|
|
7
|
+
* to the daemon's NATIVE endpoint (`/api/chat`), NOT the OpenAI-compatible `/v1` shim this provider
|
|
8
|
+
* used before. The same root host is reused by `modelDiscovery.ts`'s model picker, which still
|
|
9
|
+
* queries the `/v1/models` surface (discovery only); both derive from this root — they stay in sync
|
|
10
|
+
* at the host level even though the two use different endpoints under it.
|
|
8
11
|
*/
|
|
9
12
|
const DEFAULT_OLLAMA_HOST = 'http://127.0.0.1:11434';
|
|
10
13
|
/**
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* the
|
|
14
|
+
* GS2-59 — default context window (`num_ctx`) for Ollama models. Ollama's OWN default is 4096, but
|
|
15
|
+
* gaunt-sloth's agentic prompt (system + full lean toolset + a tool result) already lands ~4000
|
|
16
|
+
* tokens; at 4096 a thinking model (e.g. gemma4:31b) spends its entire remaining budget on the
|
|
17
|
+
* reasoning field and emits EMPTY `content` on the turn after a tool executes — the GS2-59
|
|
18
|
+
* blank-answer regression. The previous `ChatOpenAI`→`/v1` path could not fix this because the
|
|
19
|
+
* OpenAI-compat shim IGNORES `num_ctx`; the native `/api/chat` path honors it.
|
|
20
|
+
*
|
|
21
|
+
* 16384 is chosen as the largest window that is BOTH safely above the ~4000-token starvation point
|
|
22
|
+
* (4× headroom for reasoning + a few tool results) AND fits constrained consumer VRAM: Ollama
|
|
23
|
+
* preallocates the KV cache at `num_ctx`, so on a box where a large model already spills partly to
|
|
24
|
+
* CPU (e.g. a 19GB model on ~18GB of GPU), a 32768 cache tips the GPU allocation into an
|
|
25
|
+
* out-of-memory error. 16384 was verified live to run the agentic tool→synthesis turn on such a
|
|
26
|
+
* box; 32768 OOM'd it. Overridable per config via `llm.numCtx` — raise it if you have the VRAM and
|
|
27
|
+
* run long sessions, lower it on very tight hardware. NOTE: a per-request `num_ctx` overrides the
|
|
28
|
+
* daemon's `OLLAMA_CONTEXT_LENGTH`, so a user who tuned their server window higher should set
|
|
29
|
+
* `llm.numCtx` to match rather than rely on the server default.
|
|
19
30
|
*/
|
|
20
|
-
const
|
|
31
|
+
const DEFAULT_OLLAMA_NUM_CTX = 16384;
|
|
21
32
|
/**
|
|
22
|
-
* Resolve the
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
* `
|
|
26
|
-
* `host:port`; either form is normalized to a `http(s)://host[:port]/v1` base.
|
|
33
|
+
* Resolve the base URL for the local Ollama daemon — the NATIVE root (no `/v1` suffix; `ChatOllama`
|
|
34
|
+
* appends its own `/api/chat` path). Honors the `OLLAMA_HOST` env override (the same variable the
|
|
35
|
+
* Ollama CLI uses): a full URL (`http://127.0.0.1:11434`) or a bare `host:port` is normalized to
|
|
36
|
+
* `http(s)://host[:port]` with any trailing slash stripped.
|
|
27
37
|
*/
|
|
28
38
|
function resolveBaseUrl() {
|
|
29
39
|
const host = env.OLLAMA_HOST;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
else if (/^https?:\/\//.test(host)) {
|
|
35
|
-
base = host.replace(/\/+$/, '');
|
|
36
|
-
}
|
|
37
|
-
else {
|
|
38
|
-
base = `http://${host}`.replace(/\/+$/, '');
|
|
39
|
-
}
|
|
40
|
-
return `${base}/v1`;
|
|
40
|
+
if (!host)
|
|
41
|
+
return DEFAULT_OLLAMA_HOST;
|
|
42
|
+
const base = /^https?:\/\//.test(host) ? host : `http://${host}`;
|
|
43
|
+
return base.replace(/\/+$/, '');
|
|
41
44
|
}
|
|
42
|
-
|
|
45
|
+
/**
|
|
46
|
+
* GS2-59 — build a native `ChatOllama` client (`@langchain/ollama`, talking to Ollama's
|
|
47
|
+
* `/api/chat`). This replaces the previous `ChatOpenAI`→`/v1` client, which had two fatal
|
|
48
|
+
* properties for local thinking models: it DROPPED the model's separate reasoning field (the
|
|
49
|
+
* completions converter discards it — `__includeRawResponse` is openrouter-only), and it IGNORED
|
|
50
|
+
* `num_ctx` so a large agentic prompt starved the answer to empty content. `ChatOllama` fixes both:
|
|
51
|
+
* it honors `numCtx`, and it surfaces the model's thinking in `additional_kwargs.reasoning_content`
|
|
52
|
+
* — the exact field the reasoning pipeline (`pickReasoningDelta`) already reads — so the `/reasoning`
|
|
53
|
+
* panel populates with no downstream change.
|
|
54
|
+
*
|
|
55
|
+
* Ollama is a local, unauthenticated daemon, so the old OpenAI-client knobs are gone (2.0 migration
|
|
56
|
+
* note): point elsewhere with `OLLAMA_HOST`; the previous `configuration.baseURL` / placeholder
|
|
57
|
+
* `apiKey` fields no longer apply. If a reverse proxy in front of Ollama needs auth, set `headers`
|
|
58
|
+
* in the config (passed straight through to `ChatOllama`).
|
|
59
|
+
*/
|
|
43
60
|
// noinspection JSUnusedGlobalSymbols
|
|
44
61
|
export async function processJsonConfig(llmConfig) {
|
|
45
|
-
const {
|
|
46
|
-
// Ollama is local and unauthenticated; ChatOpenAI still needs a non-empty key.
|
|
47
|
-
const apiKey = llmConfig.apiKey || OLLAMA_PLACEHOLDER_API_KEY;
|
|
62
|
+
const { ChatOllama } = await import('@langchain/ollama');
|
|
48
63
|
const configFields = {
|
|
49
64
|
...llmConfig,
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
},
|
|
65
|
+
model: llmConfig.model || getCuratedFallbackModel('ollama'),
|
|
66
|
+
// Precedence: an explicit config `baseUrl` (the native ChatOllama field) wins, else the
|
|
67
|
+
// `OLLAMA_HOST` env, else the local default. Config is the more specific/intentional signal.
|
|
68
|
+
baseUrl: llmConfig.baseUrl ?? resolveBaseUrl(),
|
|
69
|
+
numCtx: llmConfig.numCtx ?? DEFAULT_OLLAMA_NUM_CTX,
|
|
56
70
|
};
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return new
|
|
71
|
+
// Strip OpenAI-client / gaunt-sloth-internal keys ChatOllama neither needs nor understands.
|
|
72
|
+
for (const key of ['type', 'apiKeyEnvironmentVariable', 'apiKey', 'configuration']) {
|
|
73
|
+
delete configFields[key];
|
|
74
|
+
}
|
|
75
|
+
return new ChatOllama(configFields);
|
|
62
76
|
}
|
|
63
|
-
|
|
64
|
-
"llm": {
|
|
65
|
-
"type": "ollama",
|
|
66
|
-
"model": "qwen3-coder"
|
|
67
|
-
}
|
|
68
|
-
}`;
|
|
69
|
-
export function init(configFileName) {
|
|
77
|
+
export function init(configFileName, force = false, model) {
|
|
70
78
|
// Determine which content to use based on file extension
|
|
71
79
|
if (!configFileName.endsWith('.json')) {
|
|
72
80
|
throw new Error('Only JSON config is supported.');
|
|
73
81
|
}
|
|
74
|
-
|
|
82
|
+
writeConfigFileWithMessages(configFileName, buildInitConfigContent('ollama', model), force);
|
|
75
83
|
displayWarning(`You need to edit your ${configFileName} to configure the model. ` +
|
|
76
84
|
'Ollama runs locally and needs no API key; set OLLAMA_HOST if your daemon ' +
|
|
77
85
|
'is not on the default http://127.0.0.1:11434.');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../src/providers/ollama.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"ollama.js","sourceRoot":"","sources":["../../src/providers/ollama.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAOhD,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAEnG;;;;;;GAMG;AACH,MAAM,mBAAmB,GAAG,wBAAwB,CAAC;AAErD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,sBAAsB,GAAG,KAAK,CAAC;AAErC;;;;;GAKG;AACH,SAAS,cAAc;IACrB,MAAM,IAAI,GAAG,GAAG,CAAC,WAAW,CAAC;IAC7B,IAAI,CAAC,IAAI;QAAE,OAAO,mBAAmB,CAAC;IACtC,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC;IACjE,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAClC,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,qCAAqC;AACrC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,SAAgD;IAEhD,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACzD,MAAM,YAAY,GAA4B;QAC5C,GAAG,SAAS;QACZ,KAAK,EAAE,SAAS,CAAC,KAAK,IAAI,uBAAuB,CAAC,QAAQ,CAAC;QAC3D,wFAAwF;QACxF,6FAA6F;QAC7F,OAAO,EAAE,SAAS,CAAC,OAAO,IAAI,cAAc,EAAE;QAC9C,MAAM,EAAE,SAAS,CAAC,MAAM,IAAI,sBAAsB;KACnD,CAAC;IACF,4FAA4F;IAC5F,KAAK,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,2BAA2B,EAAE,QAAQ,EAAE,eAAe,CAAC,EAAE,CAAC;QACnF,OAAO,YAAY,CAAC,GAAG,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,UAAU,CAAC,YAA+B,CAAC,CAAC;AACzD,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,cAAsB,EAAE,KAAK,GAAG,KAAK,EAAE,KAAc;IACxE,yDAAyD;IACzD,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IAED,2BAA2B,CAAC,cAAc,EAAE,sBAAsB,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;IAC5F,cAAc,CACZ,yBAAyB,cAAc,2BAA2B;QAChE,2EAA2E;QAC3E,+CAA+C,CAClD,CAAC;AACJ,CAAC"}
|
|
@@ -2,4 +2,4 @@ import { BaseChatModel, type BaseChatModelParams } from '@langchain/core/languag
|
|
|
2
2
|
import { OpenAIChatInput } from '@langchain/openai';
|
|
3
3
|
import { ChatOpenAIFields } from '@langchain/openai';
|
|
4
4
|
export declare function processJsonConfig(llmConfig: OpenAIChatInput & ChatOpenAIFields & BaseChatModelParams): Promise<BaseChatModel>;
|
|
5
|
-
export declare function init(configFileName: string): void;
|
|
5
|
+
export declare function init(configFileName: string, force?: boolean, model?: string): void;
|
package/dist/providers/openai.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { displayWarning } from '#src/utils/consoleUtils.js';
|
|
2
2
|
import { env } from '#src/utils/systemUtils.js';
|
|
3
|
-
import {
|
|
3
|
+
import { writeConfigFileWithMessages } from '#src/utils/fileUtils.js';
|
|
4
|
+
import { buildInitConfigContent, getCuratedFallbackModel } from '#src/providers/modelDiscovery.js';
|
|
4
5
|
/**
|
|
5
6
|
* OpenAI reasoning-model families that reject any non-default `temperature`: the API 400s with
|
|
6
7
|
* "Unsupported value: 'temperature' does not support 0 ... Only the default (1) value is
|
|
@@ -15,6 +16,35 @@ const SUPPORTED_DEFAULT_TEMPERATURE = 1;
|
|
|
15
16
|
function isTemperatureRestrictedModel(model) {
|
|
16
17
|
return !!model && TEMPERATURE_RESTRICTED_MODEL.test(model);
|
|
17
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* Decide whether to force the OpenAI Responses API (`/v1/responses`) for this request.
|
|
21
|
+
*
|
|
22
|
+
* OpenAI's `/v1/chat/completions` endpoint rejects reasoning-capable models (the gpt-5.x / o-series
|
|
23
|
+
* families) when `reasoning_effort` is combined with function tools:
|
|
24
|
+
* "Function tools with reasoning_effort are not supported for gpt-5.6-luna in
|
|
25
|
+
* /v1/chat/completions. To use function tools, use /v1/responses or set reasoning_effort to
|
|
26
|
+
* 'none'."
|
|
27
|
+
* LangChain's auto-router only flips to the Responses API for OpenAI built-in tools,
|
|
28
|
+
* `reasoning.summary` (not `.effort`), custom tools, or a hardcoded model allowlist — none of which
|
|
29
|
+
* covers ordinary function tools on a reasoning model that isn't yet on that allowlist (e.g.
|
|
30
|
+
* gpt-5.6-luna). Crucially, these models **default `reasoning_effort` to a non-`none` value**, so the
|
|
31
|
+
* collision fires even when the gth config sets NO reasoning at all (the failing case: a bare
|
|
32
|
+
* `{ type: openai, model: gpt-5.6-luna }` still 400s on `chat/completions` + tools). So for any
|
|
33
|
+
* reasoning-capable model, when the user has not made an explicit choice, default `useResponsesApi`
|
|
34
|
+
* to true — do NOT gate on reasoning being explicitly configured (GS2-74's original bug: it required
|
|
35
|
+
* `reasoningEffort`/`reasoning` to be set, missing the far more common bare-config path).
|
|
36
|
+
*
|
|
37
|
+
* Guards: (1) only reasoning-capable models — leave gpt-4o etc. on completions; (2) never override an
|
|
38
|
+
* explicit `useResponsesApi` the user set (true OR false). The model-name guard also scopes this away
|
|
39
|
+
* from OpenAI-compatible providers that reuse this file (Inception/DeepSeek/xAI ids don't match the
|
|
40
|
+
* regex). Routing a no-tools/plain call to Responses is still correct FOR GTH because gth never
|
|
41
|
+
* injects reasoning params itself — so even a non-reasoning `gpt-5`-prefixed id (e.g.
|
|
42
|
+
* `gpt-5-chat-latest`, which this regex also sweeps) is accepted there. (Responses isn't a universal
|
|
43
|
+
* superset — it drops some chat/completions-only params like `n>1` — but gth uses none of those.)
|
|
44
|
+
*/
|
|
45
|
+
function shouldUseResponsesApi(fields) {
|
|
46
|
+
return fields.useResponsesApi === undefined && isTemperatureRestrictedModel(fields.model);
|
|
47
|
+
}
|
|
18
48
|
// Function to process JSON config and create OpenAI LLM instance
|
|
19
49
|
// noinspection JSUnusedGlobalSymbols
|
|
20
50
|
export async function processJsonConfig(llmConfig) {
|
|
@@ -24,7 +54,7 @@ export async function processJsonConfig(llmConfig) {
|
|
|
24
54
|
const configFields = {
|
|
25
55
|
...llmConfig,
|
|
26
56
|
apiKey: openaiApiKey,
|
|
27
|
-
model: llmConfig.model || '
|
|
57
|
+
model: llmConfig.model || getCuratedFallbackModel('openai'),
|
|
28
58
|
};
|
|
29
59
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
30
60
|
delete configFields.type;
|
|
@@ -42,6 +72,11 @@ export async function processJsonConfig(llmConfig) {
|
|
|
42
72
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
43
73
|
delete configFields.temperature;
|
|
44
74
|
}
|
|
75
|
+
// Reasoning-capable OpenAI models 400 on `/v1/chat/completions` when `reasoning_effort` meets
|
|
76
|
+
// function tools; route them to the Responses API unless the user pinned `useResponsesApi`.
|
|
77
|
+
if (shouldUseResponsesApi(configFields)) {
|
|
78
|
+
configFields.useResponsesApi = true;
|
|
79
|
+
}
|
|
45
80
|
return new ChatOpenAI(configFields);
|
|
46
81
|
}
|
|
47
82
|
function getApiKey(llmConfig) {
|
|
@@ -54,18 +89,12 @@ function getApiKey(llmConfig) {
|
|
|
54
89
|
return llmConfig.apiKey || env.OPENAI_API_KEY;
|
|
55
90
|
}
|
|
56
91
|
}
|
|
57
|
-
|
|
58
|
-
"llm": {
|
|
59
|
-
"type": "openai",
|
|
60
|
-
"model": "gpt-5.5"
|
|
61
|
-
}
|
|
62
|
-
}`;
|
|
63
|
-
export function init(configFileName) {
|
|
92
|
+
export function init(configFileName, force = false, model) {
|
|
64
93
|
// Determine which content to use based on file extension
|
|
65
94
|
if (!configFileName.endsWith('.json')) {
|
|
66
95
|
throw new Error('Only JSON config is supported.');
|
|
67
96
|
}
|
|
68
|
-
|
|
97
|
+
writeConfigFileWithMessages(configFileName, buildInitConfigContent('openai', model), force);
|
|
69
98
|
displayWarning(`You need to edit your ${configFileName} to configure model, ` +
|
|
70
99
|
'or define OPENAI_API_KEY environment variable.');
|
|
71
100
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAQhD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"openai.js","sourceRoot":"","sources":["../../src/providers/openai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAQhD,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAEnG;;;;;;;GAOG;AACH,MAAM,4BAA4B,GAAG,eAAe,CAAC;AAErD,yFAAyF;AACzF,MAAM,6BAA6B,GAAG,CAAC,CAAC;AAExC,SAAS,4BAA4B,CAAC,KAAyB;IAC7D,OAAO,CAAC,CAAC,KAAK,IAAI,4BAA4B,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC7D,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,SAAS,qBAAqB,CAAC,MAAqD;IAClF,OAAO,MAAM,CAAC,eAAe,KAAK,SAAS,IAAI,4BAA4B,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5F,CAAC;AAED,iEAAiE;AACjE,qCAAqC;AACrC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,SAAmE;IAEnE,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAC;IACzD,wEAAwE;IACxE,MAAM,YAAY,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;IAC1C,MAAM,YAAY,GAAG;QACnB,GAAG,SAAS;QACZ,MAAM,EAAE,YAAY;QACpB,KAAK,EAAE,SAAS,CAAC,KAAK,IAAI,uBAAuB,CAAC,QAAQ,CAAC;KAC5D,CAAC;IACF,8DAA8D;IAC9D,OAAQ,YAAoB,CAAC,IAAI,CAAC;IAClC,8DAA8D;IAC9D,OAAQ,YAAoB,CAAC,yBAAyB,CAAC;IAEvD,6FAA6F;IAC7F,8FAA8F;IAC9F,6FAA6F;IAC7F,IACE,4BAA4B,CAAC,YAAY,CAAC,KAAK,CAAC;QAChD,YAAY,CAAC,WAAW,KAAK,SAAS;QACtC,YAAY,CAAC,WAAW,KAAK,6BAA6B,EAC1D,CAAC;QACD,cAAc,CACZ,UAAU,YAAY,CAAC,KAAK,0CAA0C;YACpE,qBAAqB,6BAA6B,gBAAgB;YAClE,0CAA0C,YAAY,CAAC,WAAW,GAAG,CACxE,CAAC;QACF,8DAA8D;QAC9D,OAAQ,YAAoB,CAAC,WAAW,CAAC;IAC3C,CAAC;IAED,8FAA8F;IAC9F,4FAA4F;IAC5F,IAAI,qBAAqB,CAAC,YAAY,CAAC,EAAE,CAAC;QACxC,YAAY,CAAC,eAAe,GAAG,IAAI,CAAC;IACtC,CAAC;IAED,OAAO,IAAI,UAAU,CAAC,YAAY,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,SAAS,CAAC,SAAmE;IACpF,8DAA8D;IAC9D,MAAM,IAAI,GAAG,SAA0C,CAAC;IACxD,IAAI,IAAI,CAAC,yBAAyB,IAAI,GAAG,CAAC,IAAI,CAAC,yBAAyB,CAAC,EAAE,CAAC;QAC1E,OAAO,GAAG,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;IAC7C,CAAC;SAAM,CAAC;QACN,OAAO,SAAS,CAAC,MAAM,IAAI,GAAG,CAAC,cAAc,CAAC;IAChD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,cAAsB,EAAE,KAAK,GAAG,KAAK,EAAE,KAAc;IACxE,yDAAyD;IACzD,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IAED,2BAA2B,CAAC,cAAc,EAAE,sBAAsB,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;IAC5F,cAAc,CACZ,yBAAyB,cAAc,uBAAuB;QAC5D,gDAAgD,CACnD,CAAC;AACJ,CAAC"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { BaseChatModel,
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function init(configFileName: string): void;
|
|
1
|
+
import type { BaseChatModel, BaseChatModelParams } from '@langchain/core/language_models/chat_models';
|
|
2
|
+
import type { ChatOpenRouterInput } from '@langchain/openrouter';
|
|
3
|
+
export declare function processJsonConfig(llmConfig: ChatOpenRouterInput & BaseChatModelParams & Record<string, unknown>): Promise<BaseChatModel>;
|
|
4
|
+
export declare function init(configFileName: string, force?: boolean, model?: string): void;
|
|
@@ -1,56 +1,41 @@
|
|
|
1
1
|
import { displayWarning } from '#src/utils/consoleUtils.js';
|
|
2
2
|
import { env } from '#src/utils/systemUtils.js';
|
|
3
|
-
import {
|
|
3
|
+
import { writeConfigFileWithMessages } from '#src/utils/fileUtils.js';
|
|
4
|
+
import { buildInitConfigContent, getCuratedFallbackModel } from '#src/providers/modelDiscovery.js';
|
|
4
5
|
// Function to process JSON config and create OpenRouter LLM instance
|
|
5
6
|
// noinspection JSUnusedGlobalSymbols
|
|
6
7
|
export async function processJsonConfig(llmConfig) {
|
|
7
|
-
const {
|
|
8
|
-
// Use environment variable if available, otherwise use the config value
|
|
8
|
+
const { ChatOpenRouter } = await import('@langchain/openrouter');
|
|
9
9
|
const openRouterApiKey = getApiKey(llmConfig);
|
|
10
10
|
if (!openRouterApiKey) {
|
|
11
11
|
throw new Error('You need to define OPEN_ROUTER_API_KEY environment variable, or set apiKey in your config file.');
|
|
12
12
|
}
|
|
13
|
-
const
|
|
14
|
-
|
|
13
|
+
const { type: _type, apiKeyEnvironmentVariable: _envVar, configuration, siteUrl, siteName, ...restConfig } = llmConfig;
|
|
14
|
+
const configObj = configuration;
|
|
15
|
+
const resolvedSiteUrl = siteUrl ?? configObj?.defaultHeaders?.['HTTP-Referer'] ?? 'https://gauntsloth.app/';
|
|
16
|
+
const resolvedSiteName = siteName ?? configObj?.defaultHeaders?.['X-Title'] ?? 'Gaunt Sloth';
|
|
17
|
+
return new ChatOpenRouter({
|
|
18
|
+
...restConfig,
|
|
15
19
|
apiKey: openRouterApiKey,
|
|
16
|
-
model: llmConfig.model || '
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
'HTTP-Referer': 'https://gauntsloth.app/',
|
|
22
|
-
'X-Title': 'Gaunt Sloth',
|
|
23
|
-
},
|
|
24
|
-
},
|
|
25
|
-
};
|
|
26
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
-
delete configFields.type;
|
|
28
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
|
-
delete configFields.apiKeyEnvironmentVariable;
|
|
30
|
-
return new ChatOpenAI(configFields);
|
|
20
|
+
model: llmConfig.model || getCuratedFallbackModel('openrouter'),
|
|
21
|
+
siteUrl: resolvedSiteUrl,
|
|
22
|
+
siteName: resolvedSiteName,
|
|
23
|
+
...(configObj?.baseURL ? { baseURL: configObj.baseURL } : {}),
|
|
24
|
+
});
|
|
31
25
|
}
|
|
32
26
|
function getApiKey(llmConfig) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return env[conf.apiKeyEnvironmentVariable];
|
|
37
|
-
}
|
|
38
|
-
else {
|
|
39
|
-
return llmConfig.apiKey || env.OPEN_ROUTER_API_KEY || env.OPENROUTER_API_KEY;
|
|
27
|
+
const envVarName = llmConfig.apiKeyEnvironmentVariable;
|
|
28
|
+
if (envVarName && env[envVarName]) {
|
|
29
|
+
return env[envVarName];
|
|
40
30
|
}
|
|
31
|
+
return (llmConfig.apiKey || env.OPEN_ROUTER_API_KEY || env.OPENROUTER_API_KEY);
|
|
41
32
|
}
|
|
42
|
-
|
|
43
|
-
"llm": {
|
|
44
|
-
"type": "openrouter",
|
|
45
|
-
"model": "qwen/qwen3-coder"
|
|
46
|
-
}
|
|
47
|
-
}`;
|
|
48
|
-
export function init(configFileName) {
|
|
33
|
+
export function init(configFileName, force = false, model) {
|
|
49
34
|
// Determine which content to use based on file extension
|
|
50
35
|
if (!configFileName.endsWith('.json')) {
|
|
51
36
|
throw new Error('Only JSON config is supported.');
|
|
52
37
|
}
|
|
53
|
-
|
|
38
|
+
writeConfigFileWithMessages(configFileName, buildInitConfigContent('openrouter', model), force);
|
|
54
39
|
displayWarning(`You need to edit your ${configFileName} to configure model, ` +
|
|
55
40
|
'or define OPEN_ROUTER_API_KEY environment variable.');
|
|
56
41
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openrouter.js","sourceRoot":"","sources":["../../src/providers/openrouter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"openrouter.js","sourceRoot":"","sources":["../../src/providers/openrouter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAOhD,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAEnG,qEAAqE;AACrE,qCAAqC;AACrC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,SAA8E;IAE9E,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;IAEjE,MAAM,gBAAgB,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;IAC9C,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CACb,iGAAiG,CAClG,CAAC;IACJ,CAAC;IAED,MAAM,EACJ,IAAI,EAAE,KAAK,EACX,yBAAyB,EAAE,OAAO,EAClC,aAAa,EACb,OAAO,EACP,QAAQ,EACR,GAAG,UAAU,EACd,GAAG,SAAS,CAAC;IAEd,MAAM,SAAS,GAAG,aACyD,CAAC;IAE5E,MAAM,eAAe,GACnB,OAAO,IAAI,SAAS,EAAE,cAAc,EAAE,CAAC,cAAc,CAAC,IAAI,yBAAyB,CAAC;IACtF,MAAM,gBAAgB,GAAG,QAAQ,IAAI,SAAS,EAAE,cAAc,EAAE,CAAC,SAAS,CAAC,IAAI,aAAa,CAAC;IAE7F,OAAO,IAAI,cAAc,CAAC;QACxB,GAAG,UAAU;QACb,MAAM,EAAE,gBAAgB;QACxB,KAAK,EAAE,SAAS,CAAC,KAAK,IAAI,uBAAuB,CAAC,YAAY,CAAC;QAC/D,OAAO,EAAE,eAAe;QACxB,QAAQ,EAAE,gBAAgB;QAC1B,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9D,CAAC,CAAC;AACL,CAAC;AAED,SAAS,SAAS,CAAC,SAAkC;IACnD,MAAM,UAAU,GAAG,SAAS,CAAC,yBAA+C,CAAC;IAC7E,IAAI,UAAU,IAAI,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QAClC,OAAO,GAAG,CAAC,UAAU,CAAC,CAAC;IACzB,CAAC;IACD,OAAO,CACJ,SAAS,CAAC,MAA6B,IAAI,GAAG,CAAC,mBAAmB,IAAI,GAAG,CAAC,kBAAkB,CAC9F,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,cAAsB,EAAE,KAAK,GAAG,KAAK,EAAE,KAAc;IACxE,yDAAyD;IACzD,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IAED,2BAA2B,CAAC,cAAc,EAAE,sBAAsB,CAAC,YAAY,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;IAChG,cAAc,CACZ,yBAAyB,cAAc,uBAAuB;QAC5D,qDAAqD,CACxD,CAAC;AACJ,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BaseChatModel } from '@langchain/core/language_models/chat_models';
|
|
2
2
|
import type { ChatGoogleParams } from '@langchain/google/node';
|
|
3
|
-
export declare function init(configFileName: string): void;
|
|
3
|
+
export declare function init(configFileName: string, force?: boolean, model?: string): void;
|
|
4
4
|
export declare function processJsonConfig(llmConfig: ChatGoogleParams & {
|
|
5
5
|
type?: string;
|
|
6
6
|
apiKeyEnvironmentVariable?: string;
|
|
@@ -11,19 +11,16 @@
|
|
|
11
11
|
* Hopefully this issue will go away when LangChain switches to the new GenAI dependency.
|
|
12
12
|
*/
|
|
13
13
|
import { displayWarning } from '#src/utils/consoleUtils.js';
|
|
14
|
-
import {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
}`;
|
|
21
|
-
export function init(configFileName) {
|
|
14
|
+
import { writeConfigFileWithMessages } from '#src/utils/fileUtils.js';
|
|
15
|
+
import { buildInitConfigContent, getCuratedFallbackModel } from '#src/providers/modelDiscovery.js';
|
|
16
|
+
import { applyGeminiToolSchemaSanitizer } from '#src/providers/geminiSchemaSanitizer.js';
|
|
17
|
+
import { applyGeminiThoughtSummaries } from '#src/providers/geminiThinking.js';
|
|
18
|
+
export function init(configFileName, force = false, model) {
|
|
22
19
|
// Determine which content to use based on file extension
|
|
23
20
|
if (!configFileName.endsWith('.json')) {
|
|
24
21
|
throw new Error('Only JSON config is supported.');
|
|
25
22
|
}
|
|
26
|
-
|
|
23
|
+
writeConfigFileWithMessages(configFileName, buildInitConfigContent('vertexai', model), force);
|
|
27
24
|
displayWarning('For Google VertexAI you likely to need to do `gcloud auth login` and `gcloud auth application-default login`.');
|
|
28
25
|
}
|
|
29
26
|
// Function to process JSON config and create VertexAI LLM instance
|
|
@@ -31,11 +28,15 @@ export async function processJsonConfig(llmConfig) {
|
|
|
31
28
|
const { ChatGoogle } = await import('@langchain/google/node');
|
|
32
29
|
const configFields = {
|
|
33
30
|
...llmConfig,
|
|
34
|
-
model: llmConfig.model || '
|
|
31
|
+
model: llmConfig.model || getCuratedFallbackModel('vertexai'),
|
|
35
32
|
vertexai: true,
|
|
36
33
|
};
|
|
37
34
|
delete configFields.type;
|
|
38
35
|
delete configFields.apiKeyEnvironmentVariable;
|
|
39
|
-
|
|
36
|
+
// GS2-58: normalise every tool's JSON-Schema at the ChatGoogle boundary so Gemini's OpenAPI-3.0
|
|
37
|
+
// subset accepts built-in, custom, and MCP tools alike (see geminiSchemaSanitizer).
|
|
38
|
+
// CFG-33: Vertex serves the same Gemini models through the same ChatGoogle class, so it has the
|
|
39
|
+
// same silently-discarded thinking; ask for the summaries here too (see geminiThinking).
|
|
40
|
+
return applyGeminiThoughtSummaries(applyGeminiToolSchemaSanitizer(new ChatGoogle(configFields)));
|
|
40
41
|
}
|
|
41
42
|
//# sourceMappingURL=vertexai.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vertexai.js","sourceRoot":"","sources":["../../src/providers/vertexai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAI5D,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"vertexai.js","sourceRoot":"","sources":["../../src/providers/vertexai.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAI5D,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AACnG,OAAO,EAAE,8BAA8B,EAAE,MAAM,yCAAyC,CAAC;AACzF,OAAO,EAAE,2BAA2B,EAAE,MAAM,kCAAkC,CAAC;AAE/E,MAAM,UAAU,IAAI,CAAC,cAAsB,EAAE,KAAK,GAAG,KAAK,EAAE,KAAc;IACxE,yDAAyD;IACzD,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IAED,2BAA2B,CAAC,cAAc,EAAE,sBAAsB,CAAC,UAAU,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;IAC9F,cAAc,CACZ,+GAA+G,CAChH,CAAC;AACJ,CAAC;AAED,mEAAmE;AACnE,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,SAAmF;IAEnF,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,wBAAwB,CAAC,CAAC;IAC9D,MAAM,YAAY,GAAG;QACnB,GAAG,SAAS;QACZ,KAAK,EAAE,SAAS,CAAC,KAAK,IAAI,uBAAuB,CAAC,UAAU,CAAC;QAC7D,QAAQ,EAAE,IAAI;KACf,CAAC;IACF,OAAO,YAAY,CAAC,IAAI,CAAC;IACzB,OAAO,YAAY,CAAC,yBAAyB,CAAC;IAC9C,gGAAgG;IAChG,oFAAoF;IACpF,gGAAgG;IAChG,yFAAyF;IACzF,OAAO,2BAA2B,CAAC,8BAA8B,CAAC,IAAI,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACnG,CAAC"}
|
package/dist/providers/xai.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { BaseChatModel, BaseChatModelParams } from '@langchain/core/language_models/chat_models';
|
|
2
2
|
import type { ChatXAIInput } from '@langchain/xai';
|
|
3
3
|
export declare function processJsonConfig(llmConfig: ChatXAIInput & BaseChatModelParams): Promise<BaseChatModel>;
|
|
4
|
-
export declare function init(configFileName: string): void;
|
|
4
|
+
export declare function init(configFileName: string, force?: boolean, model?: string): void;
|
package/dist/providers/xai.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { displayWarning } from '#src/utils/consoleUtils.js';
|
|
2
2
|
import { env } from '#src/utils/systemUtils.js';
|
|
3
|
-
import {
|
|
3
|
+
import { writeConfigFileWithMessages } from '#src/utils/fileUtils.js';
|
|
4
|
+
import { buildInitConfigContent, getCuratedFallbackModel } from '#src/providers/modelDiscovery.js';
|
|
4
5
|
// Function to process JSON config and create XAI LLM instance
|
|
5
6
|
export async function processJsonConfig(llmConfig) {
|
|
6
7
|
const { ChatXAI } = await import('@langchain/xai');
|
|
@@ -9,21 +10,15 @@ export async function processJsonConfig(llmConfig) {
|
|
|
9
10
|
return new ChatXAI({
|
|
10
11
|
...llmConfig,
|
|
11
12
|
apiKey,
|
|
12
|
-
model: llmConfig.model || '
|
|
13
|
+
model: llmConfig.model || getCuratedFallbackModel('xai'),
|
|
13
14
|
});
|
|
14
15
|
}
|
|
15
|
-
|
|
16
|
-
"llm": {
|
|
17
|
-
"type": "xai",
|
|
18
|
-
"model": "grok-4.3"
|
|
19
|
-
}
|
|
20
|
-
}`;
|
|
21
|
-
export function init(configFileName) {
|
|
16
|
+
export function init(configFileName, force = false, model) {
|
|
22
17
|
// Determine which content to use based on file extension
|
|
23
18
|
if (!configFileName.endsWith('.json')) {
|
|
24
19
|
throw new Error('Only JSON config is supported.');
|
|
25
20
|
}
|
|
26
|
-
|
|
21
|
+
writeConfigFileWithMessages(configFileName, buildInitConfigContent('xai', model), force);
|
|
27
22
|
displayWarning(`You need to update your ${configFileName} to add your xAI API key, ` +
|
|
28
23
|
'or define XAI_API_KEY environment variable.');
|
|
29
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"xai.js","sourceRoot":"","sources":["../../src/providers/xai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAOhD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"xai.js","sourceRoot":"","sources":["../../src/providers/xai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,GAAG,EAAE,MAAM,2BAA2B,CAAC;AAOhD,OAAO,EAAE,2BAA2B,EAAE,MAAM,yBAAyB,CAAC;AACtE,OAAO,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,MAAM,kCAAkC,CAAC;AAEnG,8DAA8D;AAC9D,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,SAA6C;IAE7C,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACnD,wEAAwE;IACxE,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,IAAI,GAAG,CAAC,WAAW,CAAC;IACnD,OAAO,IAAI,OAAO,CAAC;QACjB,GAAG,SAAS;QACZ,MAAM;QACN,KAAK,EAAE,SAAS,CAAC,KAAK,IAAI,uBAAuB,CAAC,KAAK,CAAC;KACzD,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,cAAsB,EAAE,KAAK,GAAG,KAAK,EAAE,KAAc;IACxE,yDAAyD;IACzD,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QACtC,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACpD,CAAC;IAED,2BAA2B,CAAC,cAAc,EAAE,sBAAsB,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;IACzF,cAAc,CACZ,2BAA2B,cAAc,4BAA4B;QACnE,6CAA6C,CAChD,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @module runtime/askStructured
|
|
3
|
+
*
|
|
4
|
+
* A reusable, non-agentic "ask the LLM and get a schema-validated object back" primitive — the
|
|
5
|
+
* structured-output half the (later) `gth workflow` host calls. Deliberately mirrors the
|
|
6
|
+
* *mechanism* of the structured-evaluation calls ({@link judgeEvalCase} — the EVAL GRADER in
|
|
7
|
+
* `@gaunt-sloth/batch`'s `judge.ts` — and its in-core sibling {@link rateShellCommand}, the
|
|
8
|
+
* approvals AI rater in `core/shell/rater.ts`):
|
|
9
|
+
* `model.withStructuredOutput(schema)` for a single structured call, `.invoke([SystemMessage,
|
|
10
|
+
* HumanMessage])` raced against a wall-clock timeout via `Promise.race`, a defensive `safeParse`
|
|
11
|
+
* re-validation, `clearTimeout` in `finally`, and — crucially — it **never throws**, returning a
|
|
12
|
+
* failure object instead.
|
|
13
|
+
*
|
|
14
|
+
* Differences from those two: this one is **generic** over the Zod schema and takes the
|
|
15
|
+
* system/user strings from the caller (they hard-code a schema and build a rubric/safety
|
|
16
|
+
* prompt), and it reads the model from `config.llm` (like `runSingleShot`/`rateShellCommand`),
|
|
17
|
+
* so the workflow host can hand it the resolved {@link GthConfig} directly. `judgeEvalCase` could
|
|
18
|
+
* later be refactored to delegate to this primitive — out of scope here.
|
|
19
|
+
*/
|
|
20
|
+
import * as z from 'zod';
|
|
21
|
+
import type { GthConfig } from '#src/config.js';
|
|
22
|
+
/**
|
|
23
|
+
* Default wall-clock budget (ms) for the structured LLM call — same value as their
|
|
24
|
+
* `EVAL_JUDGE_DEFAULT_TIMEOUT_MS` / `JUDGE_DEFAULT_TIMEOUT_MS`, kept as this module's own constant
|
|
25
|
+
* since the primitive is conceptually independent of them.
|
|
26
|
+
*/
|
|
27
|
+
export declare const ASK_STRUCTURED_DEFAULT_TIMEOUT_MS = 30000;
|
|
28
|
+
/**
|
|
29
|
+
* The exact `error` text {@link askStructured} returns when its wall-clock budget fires — i.e. the
|
|
30
|
+
* provider produced **no answer at all** within the budget.
|
|
31
|
+
*
|
|
32
|
+
* Exported as a builder rather than left as an inline literal because the three failure classes here
|
|
33
|
+
* (no response · an answer that does not fit the schema · a call that failed outright) are the
|
|
34
|
+
* question a reader of a red run has to answer first, and they are only distinguishable by this text.
|
|
35
|
+
* A caller that re-types the sentence to recognise it stops recognising it the day the wording moves,
|
|
36
|
+
* and silently re-files a stall as a rejection — which is precisely the confusion this exists to end.
|
|
37
|
+
*/
|
|
38
|
+
export declare function structuredCallTimedOutError(timeoutMs: number): string;
|
|
39
|
+
/**
|
|
40
|
+
* The exact `error` text {@link askStructured} returns when the provider **did** answer and the
|
|
41
|
+
* answer failed the caller's own schema. The counterpart of {@link structuredCallTimedOutError};
|
|
42
|
+
* see that doc for why both are exported rather than written inline.
|
|
43
|
+
*/
|
|
44
|
+
export declare const STRUCTURED_CALL_UNPARSEABLE_ERROR = "Model returned unparseable output.";
|
|
45
|
+
/**
|
|
46
|
+
* Which of {@link askStructured}'s three failure paths a result came from.
|
|
47
|
+
*
|
|
48
|
+
* - `timeout` — the budget fired and the provider had returned nothing at all.
|
|
49
|
+
* - `unparseable` — the provider answered, and the answer failed the caller's schema.
|
|
50
|
+
* - `call-failed` — the call threw before any answer arrived: a provider rejection (OpenAI's 400 on
|
|
51
|
+
* a strict `json_schema` is the canonical one), an auth failure, a transport failure.
|
|
52
|
+
*/
|
|
53
|
+
export type StructuredFailureKind = 'timeout' | 'unparseable' | 'call-failed';
|
|
54
|
+
/**
|
|
55
|
+
* Name which failure happened, given the `error` string and the budget the call was made with.
|
|
56
|
+
*
|
|
57
|
+
* The single place the three classes are told apart. A stall and a rejection are the two failures a
|
|
58
|
+
* reader has to distinguish first and the two that look most alike from the outside — a red that
|
|
59
|
+
* cannot say which happened sends the reader to re-run a real defect, or to investigate a provider
|
|
60
|
+
* hiccup. Every caller that wants to say which one it was calls this rather than matching the prose
|
|
61
|
+
* itself, so the wording can only be got wrong in one place, and that place has a test.
|
|
62
|
+
*
|
|
63
|
+
* @param error The `error` from a `{ ok: false }` {@link AskStructuredResult}.
|
|
64
|
+
* @param timeoutMs The budget passed to that same {@link askStructured} call — the timeout text
|
|
65
|
+
* carries it, so a different value here reports a genuine timeout as `call-failed`.
|
|
66
|
+
*/
|
|
67
|
+
export declare function classifyStructuredFailure(error: string, timeoutMs: number): StructuredFailureKind;
|
|
68
|
+
/** Inputs to {@link askStructured}. The caller supplies the model (via config), the two message
|
|
69
|
+
* texts, and an optional timeout — the Zod schema is a separate positional argument so `<T>` can
|
|
70
|
+
* be inferred from it. */
|
|
71
|
+
export interface AskStructuredOptions {
|
|
72
|
+
config: GthConfig;
|
|
73
|
+
/** System-message text (instructions). May be empty. */
|
|
74
|
+
system: string;
|
|
75
|
+
/** Human-message text (the actual content/question). */
|
|
76
|
+
user: string;
|
|
77
|
+
/** Wall-clock budget in ms. Default {@link ASK_STRUCTURED_DEFAULT_TIMEOUT_MS} (30_000). */
|
|
78
|
+
timeoutMs?: number;
|
|
79
|
+
}
|
|
80
|
+
/** Discriminated result of {@link askStructured}: the parsed value on success, an error string on
|
|
81
|
+
* any failure (unusable model, timeout, unparseable output, or a thrown error). Never throws. */
|
|
82
|
+
export type AskStructuredResult<T> = {
|
|
83
|
+
ok: true;
|
|
84
|
+
value: T;
|
|
85
|
+
} | {
|
|
86
|
+
ok: false;
|
|
87
|
+
error: string;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Ask the configured model for a single schema-validated object — a non-agentic structured-output
|
|
91
|
+
* call that mirrors their mechanism (see the module doc) and never throws.
|
|
92
|
+
*
|
|
93
|
+
* - No usable model (`config.llm` missing or lacking `withStructuredOutput`) →
|
|
94
|
+
* `{ ok: false, error: 'No usable model configured.' }`.
|
|
95
|
+
* - Timeout → `ok: false` with the error {@link structuredCallTimedOutError} builds for that budget.
|
|
96
|
+
* - Output that fails `schema.safeParse` → `{ ok: false, error: {@link STRUCTURED_CALL_UNPARSEABLE_ERROR} }`.
|
|
97
|
+
* - Any thrown error → `{ ok: false, error: <message> }` — a provider rejection (e.g. OpenAI's 400 on
|
|
98
|
+
* a strict `json_schema`), an auth or transport failure. Distinct from the two above BY CODE PATH,
|
|
99
|
+
* so a caller can classify a failure by comparing against those two exported texts.
|
|
100
|
+
* - Success → `{ ok: true, value }` with the parsed data.
|
|
101
|
+
*
|
|
102
|
+
* @param schema The Zod schema the model output must satisfy; `<T>` is inferred from it.
|
|
103
|
+
* @param opts The model (via `config.llm`), the system/user message texts, and an optional timeout.
|
|
104
|
+
*/
|
|
105
|
+
export declare function askStructured<T>(schema: z.ZodType<T>, opts: AskStructuredOptions): Promise<AskStructuredResult<T>>;
|