@probelabs/probe 0.6.0-rc317 → 0.6.0-rc319
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/bin/binaries/{probe-v0.6.0-rc317-aarch64-apple-darwin.tar.gz → probe-v0.6.0-rc319-aarch64-apple-darwin.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc317-aarch64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc319-aarch64-unknown-linux-musl.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc317-x86_64-apple-darwin.tar.gz → probe-v0.6.0-rc319-x86_64-apple-darwin.tar.gz} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc317-x86_64-pc-windows-msvc.zip → probe-v0.6.0-rc319-x86_64-pc-windows-msvc.zip} +0 -0
- package/bin/binaries/{probe-v0.6.0-rc317-x86_64-unknown-linux-musl.tar.gz → probe-v0.6.0-rc319-x86_64-unknown-linux-musl.tar.gz} +0 -0
- package/build/tools/vercel.js +7 -9
- package/build/utils/provider.js +26 -2
- package/cjs/agent/ProbeAgent.cjs +24 -7
- package/cjs/index.cjs +24 -7
- package/package.json +1 -1
- package/src/tools/vercel.js +7 -9
- package/src/utils/provider.js +26 -2
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/build/tools/vercel.js
CHANGED
|
@@ -719,14 +719,12 @@ export const searchTool = (options = {}) => {
|
|
|
719
719
|
// ── Delegate-level semantic dedup ────────────────────────────
|
|
720
720
|
// Each delegate is a full flash agent session (minutes, not seconds).
|
|
721
721
|
// Use LLM to detect semantic duplicates and suggest rewrites.
|
|
722
|
-
// Compare against ALL previous delegations (not filtered by path) because
|
|
723
|
-
// the parent model often narrows the path while asking the same concept
|
|
724
|
-
// (e.g., "dedup" at /src → "deduplicate" at /src/search.js).
|
|
725
722
|
const delegatePath = searchPath || '';
|
|
723
|
+
const samePathDelegations = previousDelegations.filter(d => d.path === delegatePath);
|
|
726
724
|
|
|
727
725
|
let effectiveQuery = searchQuery;
|
|
728
726
|
|
|
729
|
-
if (
|
|
727
|
+
if (samePathDelegations.length > 0) {
|
|
730
728
|
const dedupProvider = options.searchDelegateProvider || process.env.PROBE_SEARCH_DELEGATE_PROVIDER || options.provider || process.env.FORCE_PROVIDER || null;
|
|
731
729
|
const dedupModelName = options.searchDelegateModel || process.env.PROBE_SEARCH_DELEGATE_MODEL || options.model || process.env.MODEL_NAME || null;
|
|
732
730
|
// Lazily create the dedup model (same provider/model as delegate)
|
|
@@ -742,8 +740,8 @@ export const searchTool = (options = {}) => {
|
|
|
742
740
|
|
|
743
741
|
const dedupSpanAttrs = {
|
|
744
742
|
'dedup.query': searchQuery,
|
|
745
|
-
'dedup.previous_count': String(
|
|
746
|
-
'dedup.previous_queries':
|
|
743
|
+
'dedup.previous_count': String(samePathDelegations.length),
|
|
744
|
+
'dedup.previous_queries': samePathDelegations.map(d => d.query).join(' | '),
|
|
747
745
|
'dedup.provider': dedupProvider || '',
|
|
748
746
|
'dedup.model': dedupModelName || '',
|
|
749
747
|
'dedup.model_available': cachedDedupModel ? 'true' : 'false',
|
|
@@ -751,7 +749,7 @@ export const searchTool = (options = {}) => {
|
|
|
751
749
|
|
|
752
750
|
const dedup = options.tracer?.withSpan
|
|
753
751
|
? await options.tracer.withSpan('search.delegate.dedup', async () => {
|
|
754
|
-
return await checkDelegateDedup(searchQuery,
|
|
752
|
+
return await checkDelegateDedup(searchQuery, samePathDelegations, cachedDedupModel, debug);
|
|
755
753
|
}, dedupSpanAttrs, (span, result) => {
|
|
756
754
|
span.setAttributes({
|
|
757
755
|
'dedup.action': result.action,
|
|
@@ -760,14 +758,14 @@ export const searchTool = (options = {}) => {
|
|
|
760
758
|
'dedup.error': result.error || '',
|
|
761
759
|
});
|
|
762
760
|
})
|
|
763
|
-
: await checkDelegateDedup(searchQuery,
|
|
761
|
+
: await checkDelegateDedup(searchQuery, samePathDelegations, cachedDedupModel, debug);
|
|
764
762
|
|
|
765
763
|
if (debug) {
|
|
766
764
|
console.error(`[DEDUP-LLM] Query: "${searchQuery}" → ${dedup.action}: ${dedup.reason}${dedup.rewritten ? ` → "${dedup.rewritten}"` : ''}`);
|
|
767
765
|
}
|
|
768
766
|
|
|
769
767
|
if (dedup.action === 'block') {
|
|
770
|
-
const prevQueries =
|
|
768
|
+
const prevQueries = samePathDelegations.map(d => `"${d.query}"`).join(', ');
|
|
771
769
|
return `DELEGATE BLOCKED: "${searchQuery}" is semantically duplicate of previous delegation(s) [${prevQueries}]. ${dedup.reason}\n\nDo NOT re-delegate the same concept. Use extract() on files already found, or synthesize your answer from existing results.`;
|
|
772
770
|
}
|
|
773
771
|
|
package/build/utils/provider.js
CHANGED
|
@@ -84,9 +84,32 @@ export function resolveApiKey(providerName) {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Resolve base URL for a provider from environment variables.
|
|
89
|
+
* Mirrors the env-var resolution in ProbeAgent and FallbackManager so that
|
|
90
|
+
* lightweight LLM calls (dedup, etc.) route through the same API gateway.
|
|
91
|
+
* @param {string} providerName
|
|
92
|
+
* @returns {string|undefined}
|
|
93
|
+
*/
|
|
94
|
+
export function resolveBaseUrl(providerName) {
|
|
95
|
+
const llmBaseUrl = process.env.LLM_BASE_URL;
|
|
96
|
+
switch (providerName) {
|
|
97
|
+
case 'anthropic':
|
|
98
|
+
return process.env.ANTHROPIC_API_URL || process.env.ANTHROPIC_BASE_URL || llmBaseUrl;
|
|
99
|
+
case 'openai':
|
|
100
|
+
return process.env.OPENAI_API_URL || llmBaseUrl;
|
|
101
|
+
case 'google':
|
|
102
|
+
return process.env.GOOGLE_API_URL || llmBaseUrl;
|
|
103
|
+
case 'bedrock':
|
|
104
|
+
return process.env.AWS_BEDROCK_BASE_URL || llmBaseUrl;
|
|
105
|
+
default:
|
|
106
|
+
return llmBaseUrl;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
87
110
|
/**
|
|
88
111
|
* Create a language model instance from provider name + model name.
|
|
89
|
-
* Resolves API keys from environment automatically.
|
|
112
|
+
* Resolves API keys and base URLs from environment automatically.
|
|
90
113
|
* Returns null on failure (graceful degradation for optional features).
|
|
91
114
|
* @param {string} providerName - 'anthropic' | 'openai' | 'google' | 'bedrock'
|
|
92
115
|
* @param {string} modelName - Model identifier (e.g., 'gemini-2.0-flash')
|
|
@@ -98,7 +121,8 @@ export async function createLanguageModel(providerName, modelName) {
|
|
|
98
121
|
if (!resolvedModel) return null;
|
|
99
122
|
try {
|
|
100
123
|
const apiKey = resolveApiKey(providerName);
|
|
101
|
-
const
|
|
124
|
+
const baseURL = resolveBaseUrl(providerName);
|
|
125
|
+
const provider = createProviderInstance({ provider: providerName, ...(apiKey ? { apiKey } : {}), ...(baseURL ? { baseURL } : {}) });
|
|
102
126
|
return provider(resolvedModel);
|
|
103
127
|
} catch {
|
|
104
128
|
return null;
|
package/cjs/agent/ProbeAgent.cjs
CHANGED
|
@@ -26155,13 +26155,29 @@ function resolveApiKey(providerName) {
|
|
|
26155
26155
|
return void 0;
|
|
26156
26156
|
}
|
|
26157
26157
|
}
|
|
26158
|
+
function resolveBaseUrl(providerName) {
|
|
26159
|
+
const llmBaseUrl = process.env.LLM_BASE_URL;
|
|
26160
|
+
switch (providerName) {
|
|
26161
|
+
case "anthropic":
|
|
26162
|
+
return process.env.ANTHROPIC_API_URL || process.env.ANTHROPIC_BASE_URL || llmBaseUrl;
|
|
26163
|
+
case "openai":
|
|
26164
|
+
return process.env.OPENAI_API_URL || llmBaseUrl;
|
|
26165
|
+
case "google":
|
|
26166
|
+
return process.env.GOOGLE_API_URL || llmBaseUrl;
|
|
26167
|
+
case "bedrock":
|
|
26168
|
+
return process.env.AWS_BEDROCK_BASE_URL || llmBaseUrl;
|
|
26169
|
+
default:
|
|
26170
|
+
return llmBaseUrl;
|
|
26171
|
+
}
|
|
26172
|
+
}
|
|
26158
26173
|
async function createLanguageModel(providerName, modelName) {
|
|
26159
26174
|
if (!providerName) return null;
|
|
26160
26175
|
const resolvedModel = modelName || DEFAULT_MODELS[providerName];
|
|
26161
26176
|
if (!resolvedModel) return null;
|
|
26162
26177
|
try {
|
|
26163
26178
|
const apiKey = resolveApiKey(providerName);
|
|
26164
|
-
const
|
|
26179
|
+
const baseURL = resolveBaseUrl(providerName);
|
|
26180
|
+
const provider = createProviderInstance({ provider: providerName, ...apiKey ? { apiKey } : {}, ...baseURL ? { baseURL } : {} });
|
|
26165
26181
|
return provider(resolvedModel);
|
|
26166
26182
|
} catch {
|
|
26167
26183
|
return null;
|
|
@@ -32551,8 +32567,9 @@ Change your strategy:${scopeHint}
|
|
|
32551
32567
|
}
|
|
32552
32568
|
}
|
|
32553
32569
|
const delegatePath = searchPath || "";
|
|
32570
|
+
const samePathDelegations = previousDelegations.filter((d) => d.path === delegatePath);
|
|
32554
32571
|
let effectiveQuery = searchQuery;
|
|
32555
|
-
if (
|
|
32572
|
+
if (samePathDelegations.length > 0) {
|
|
32556
32573
|
const dedupProvider = options.searchDelegateProvider || process.env.PROBE_SEARCH_DELEGATE_PROVIDER || options.provider || process.env.FORCE_PROVIDER || null;
|
|
32557
32574
|
const dedupModelName = options.searchDelegateModel || process.env.PROBE_SEARCH_DELEGATE_MODEL || options.model || process.env.MODEL_NAME || null;
|
|
32558
32575
|
if (cachedDedupModel === void 0) {
|
|
@@ -32566,14 +32583,14 @@ Change your strategy:${scopeHint}
|
|
|
32566
32583
|
}
|
|
32567
32584
|
const dedupSpanAttrs = {
|
|
32568
32585
|
"dedup.query": searchQuery,
|
|
32569
|
-
"dedup.previous_count": String(
|
|
32570
|
-
"dedup.previous_queries":
|
|
32586
|
+
"dedup.previous_count": String(samePathDelegations.length),
|
|
32587
|
+
"dedup.previous_queries": samePathDelegations.map((d) => d.query).join(" | "),
|
|
32571
32588
|
"dedup.provider": dedupProvider || "",
|
|
32572
32589
|
"dedup.model": dedupModelName || "",
|
|
32573
32590
|
"dedup.model_available": cachedDedupModel ? "true" : "false"
|
|
32574
32591
|
};
|
|
32575
32592
|
const dedup = options.tracer?.withSpan ? await options.tracer.withSpan("search.delegate.dedup", async () => {
|
|
32576
|
-
return await checkDelegateDedup(searchQuery,
|
|
32593
|
+
return await checkDelegateDedup(searchQuery, samePathDelegations, cachedDedupModel, debug);
|
|
32577
32594
|
}, dedupSpanAttrs, (span, result) => {
|
|
32578
32595
|
span.setAttributes({
|
|
32579
32596
|
"dedup.action": result.action,
|
|
@@ -32581,12 +32598,12 @@ Change your strategy:${scopeHint}
|
|
|
32581
32598
|
"dedup.rewritten": result.rewritten || "",
|
|
32582
32599
|
"dedup.error": result.error || ""
|
|
32583
32600
|
});
|
|
32584
|
-
}) : await checkDelegateDedup(searchQuery,
|
|
32601
|
+
}) : await checkDelegateDedup(searchQuery, samePathDelegations, cachedDedupModel, debug);
|
|
32585
32602
|
if (debug) {
|
|
32586
32603
|
console.error(`[DEDUP-LLM] Query: "${searchQuery}" \u2192 ${dedup.action}: ${dedup.reason}${dedup.rewritten ? ` \u2192 "${dedup.rewritten}"` : ""}`);
|
|
32587
32604
|
}
|
|
32588
32605
|
if (dedup.action === "block") {
|
|
32589
|
-
const prevQueries =
|
|
32606
|
+
const prevQueries = samePathDelegations.map((d) => `"${d.query}"`).join(", ");
|
|
32590
32607
|
return `DELEGATE BLOCKED: "${searchQuery}" is semantically duplicate of previous delegation(s) [${prevQueries}]. ${dedup.reason}
|
|
32591
32608
|
|
|
32592
32609
|
Do NOT re-delegate the same concept. Use extract() on files already found, or synthesize your answer from existing results.`;
|
package/cjs/index.cjs
CHANGED
|
@@ -28084,13 +28084,29 @@ function resolveApiKey(providerName) {
|
|
|
28084
28084
|
return void 0;
|
|
28085
28085
|
}
|
|
28086
28086
|
}
|
|
28087
|
+
function resolveBaseUrl(providerName) {
|
|
28088
|
+
const llmBaseUrl = process.env.LLM_BASE_URL;
|
|
28089
|
+
switch (providerName) {
|
|
28090
|
+
case "anthropic":
|
|
28091
|
+
return process.env.ANTHROPIC_API_URL || process.env.ANTHROPIC_BASE_URL || llmBaseUrl;
|
|
28092
|
+
case "openai":
|
|
28093
|
+
return process.env.OPENAI_API_URL || llmBaseUrl;
|
|
28094
|
+
case "google":
|
|
28095
|
+
return process.env.GOOGLE_API_URL || llmBaseUrl;
|
|
28096
|
+
case "bedrock":
|
|
28097
|
+
return process.env.AWS_BEDROCK_BASE_URL || llmBaseUrl;
|
|
28098
|
+
default:
|
|
28099
|
+
return llmBaseUrl;
|
|
28100
|
+
}
|
|
28101
|
+
}
|
|
28087
28102
|
async function createLanguageModel(providerName, modelName) {
|
|
28088
28103
|
if (!providerName) return null;
|
|
28089
28104
|
const resolvedModel = modelName || DEFAULT_MODELS[providerName];
|
|
28090
28105
|
if (!resolvedModel) return null;
|
|
28091
28106
|
try {
|
|
28092
28107
|
const apiKey = resolveApiKey(providerName);
|
|
28093
|
-
const
|
|
28108
|
+
const baseURL = resolveBaseUrl(providerName);
|
|
28109
|
+
const provider = createProviderInstance({ provider: providerName, ...apiKey ? { apiKey } : {}, ...baseURL ? { baseURL } : {} });
|
|
28094
28110
|
return provider(resolvedModel);
|
|
28095
28111
|
} catch {
|
|
28096
28112
|
return null;
|
|
@@ -107967,8 +107983,9 @@ Change your strategy:${scopeHint}
|
|
|
107967
107983
|
}
|
|
107968
107984
|
}
|
|
107969
107985
|
const delegatePath = searchPath || "";
|
|
107986
|
+
const samePathDelegations = previousDelegations.filter((d) => d.path === delegatePath);
|
|
107970
107987
|
let effectiveQuery = searchQuery;
|
|
107971
|
-
if (
|
|
107988
|
+
if (samePathDelegations.length > 0) {
|
|
107972
107989
|
const dedupProvider = options.searchDelegateProvider || process.env.PROBE_SEARCH_DELEGATE_PROVIDER || options.provider || process.env.FORCE_PROVIDER || null;
|
|
107973
107990
|
const dedupModelName = options.searchDelegateModel || process.env.PROBE_SEARCH_DELEGATE_MODEL || options.model || process.env.MODEL_NAME || null;
|
|
107974
107991
|
if (cachedDedupModel === void 0) {
|
|
@@ -107982,14 +107999,14 @@ Change your strategy:${scopeHint}
|
|
|
107982
107999
|
}
|
|
107983
108000
|
const dedupSpanAttrs = {
|
|
107984
108001
|
"dedup.query": searchQuery,
|
|
107985
|
-
"dedup.previous_count": String(
|
|
107986
|
-
"dedup.previous_queries":
|
|
108002
|
+
"dedup.previous_count": String(samePathDelegations.length),
|
|
108003
|
+
"dedup.previous_queries": samePathDelegations.map((d) => d.query).join(" | "),
|
|
107987
108004
|
"dedup.provider": dedupProvider || "",
|
|
107988
108005
|
"dedup.model": dedupModelName || "",
|
|
107989
108006
|
"dedup.model_available": cachedDedupModel ? "true" : "false"
|
|
107990
108007
|
};
|
|
107991
108008
|
const dedup = options.tracer?.withSpan ? await options.tracer.withSpan("search.delegate.dedup", async () => {
|
|
107992
|
-
return await checkDelegateDedup(searchQuery,
|
|
108009
|
+
return await checkDelegateDedup(searchQuery, samePathDelegations, cachedDedupModel, debug);
|
|
107993
108010
|
}, dedupSpanAttrs, (span, result) => {
|
|
107994
108011
|
span.setAttributes({
|
|
107995
108012
|
"dedup.action": result.action,
|
|
@@ -107997,12 +108014,12 @@ Change your strategy:${scopeHint}
|
|
|
107997
108014
|
"dedup.rewritten": result.rewritten || "",
|
|
107998
108015
|
"dedup.error": result.error || ""
|
|
107999
108016
|
});
|
|
108000
|
-
}) : await checkDelegateDedup(searchQuery,
|
|
108017
|
+
}) : await checkDelegateDedup(searchQuery, samePathDelegations, cachedDedupModel, debug);
|
|
108001
108018
|
if (debug) {
|
|
108002
108019
|
console.error(`[DEDUP-LLM] Query: "${searchQuery}" \u2192 ${dedup.action}: ${dedup.reason}${dedup.rewritten ? ` \u2192 "${dedup.rewritten}"` : ""}`);
|
|
108003
108020
|
}
|
|
108004
108021
|
if (dedup.action === "block") {
|
|
108005
|
-
const prevQueries =
|
|
108022
|
+
const prevQueries = samePathDelegations.map((d) => `"${d.query}"`).join(", ");
|
|
108006
108023
|
return `DELEGATE BLOCKED: "${searchQuery}" is semantically duplicate of previous delegation(s) [${prevQueries}]. ${dedup.reason}
|
|
108007
108024
|
|
|
108008
108025
|
Do NOT re-delegate the same concept. Use extract() on files already found, or synthesize your answer from existing results.`;
|
package/package.json
CHANGED
package/src/tools/vercel.js
CHANGED
|
@@ -719,14 +719,12 @@ export const searchTool = (options = {}) => {
|
|
|
719
719
|
// ── Delegate-level semantic dedup ────────────────────────────
|
|
720
720
|
// Each delegate is a full flash agent session (minutes, not seconds).
|
|
721
721
|
// Use LLM to detect semantic duplicates and suggest rewrites.
|
|
722
|
-
// Compare against ALL previous delegations (not filtered by path) because
|
|
723
|
-
// the parent model often narrows the path while asking the same concept
|
|
724
|
-
// (e.g., "dedup" at /src → "deduplicate" at /src/search.js).
|
|
725
722
|
const delegatePath = searchPath || '';
|
|
723
|
+
const samePathDelegations = previousDelegations.filter(d => d.path === delegatePath);
|
|
726
724
|
|
|
727
725
|
let effectiveQuery = searchQuery;
|
|
728
726
|
|
|
729
|
-
if (
|
|
727
|
+
if (samePathDelegations.length > 0) {
|
|
730
728
|
const dedupProvider = options.searchDelegateProvider || process.env.PROBE_SEARCH_DELEGATE_PROVIDER || options.provider || process.env.FORCE_PROVIDER || null;
|
|
731
729
|
const dedupModelName = options.searchDelegateModel || process.env.PROBE_SEARCH_DELEGATE_MODEL || options.model || process.env.MODEL_NAME || null;
|
|
732
730
|
// Lazily create the dedup model (same provider/model as delegate)
|
|
@@ -742,8 +740,8 @@ export const searchTool = (options = {}) => {
|
|
|
742
740
|
|
|
743
741
|
const dedupSpanAttrs = {
|
|
744
742
|
'dedup.query': searchQuery,
|
|
745
|
-
'dedup.previous_count': String(
|
|
746
|
-
'dedup.previous_queries':
|
|
743
|
+
'dedup.previous_count': String(samePathDelegations.length),
|
|
744
|
+
'dedup.previous_queries': samePathDelegations.map(d => d.query).join(' | '),
|
|
747
745
|
'dedup.provider': dedupProvider || '',
|
|
748
746
|
'dedup.model': dedupModelName || '',
|
|
749
747
|
'dedup.model_available': cachedDedupModel ? 'true' : 'false',
|
|
@@ -751,7 +749,7 @@ export const searchTool = (options = {}) => {
|
|
|
751
749
|
|
|
752
750
|
const dedup = options.tracer?.withSpan
|
|
753
751
|
? await options.tracer.withSpan('search.delegate.dedup', async () => {
|
|
754
|
-
return await checkDelegateDedup(searchQuery,
|
|
752
|
+
return await checkDelegateDedup(searchQuery, samePathDelegations, cachedDedupModel, debug);
|
|
755
753
|
}, dedupSpanAttrs, (span, result) => {
|
|
756
754
|
span.setAttributes({
|
|
757
755
|
'dedup.action': result.action,
|
|
@@ -760,14 +758,14 @@ export const searchTool = (options = {}) => {
|
|
|
760
758
|
'dedup.error': result.error || '',
|
|
761
759
|
});
|
|
762
760
|
})
|
|
763
|
-
: await checkDelegateDedup(searchQuery,
|
|
761
|
+
: await checkDelegateDedup(searchQuery, samePathDelegations, cachedDedupModel, debug);
|
|
764
762
|
|
|
765
763
|
if (debug) {
|
|
766
764
|
console.error(`[DEDUP-LLM] Query: "${searchQuery}" → ${dedup.action}: ${dedup.reason}${dedup.rewritten ? ` → "${dedup.rewritten}"` : ''}`);
|
|
767
765
|
}
|
|
768
766
|
|
|
769
767
|
if (dedup.action === 'block') {
|
|
770
|
-
const prevQueries =
|
|
768
|
+
const prevQueries = samePathDelegations.map(d => `"${d.query}"`).join(', ');
|
|
771
769
|
return `DELEGATE BLOCKED: "${searchQuery}" is semantically duplicate of previous delegation(s) [${prevQueries}]. ${dedup.reason}\n\nDo NOT re-delegate the same concept. Use extract() on files already found, or synthesize your answer from existing results.`;
|
|
772
770
|
}
|
|
773
771
|
|
package/src/utils/provider.js
CHANGED
|
@@ -84,9 +84,32 @@ export function resolveApiKey(providerName) {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Resolve base URL for a provider from environment variables.
|
|
89
|
+
* Mirrors the env-var resolution in ProbeAgent and FallbackManager so that
|
|
90
|
+
* lightweight LLM calls (dedup, etc.) route through the same API gateway.
|
|
91
|
+
* @param {string} providerName
|
|
92
|
+
* @returns {string|undefined}
|
|
93
|
+
*/
|
|
94
|
+
export function resolveBaseUrl(providerName) {
|
|
95
|
+
const llmBaseUrl = process.env.LLM_BASE_URL;
|
|
96
|
+
switch (providerName) {
|
|
97
|
+
case 'anthropic':
|
|
98
|
+
return process.env.ANTHROPIC_API_URL || process.env.ANTHROPIC_BASE_URL || llmBaseUrl;
|
|
99
|
+
case 'openai':
|
|
100
|
+
return process.env.OPENAI_API_URL || llmBaseUrl;
|
|
101
|
+
case 'google':
|
|
102
|
+
return process.env.GOOGLE_API_URL || llmBaseUrl;
|
|
103
|
+
case 'bedrock':
|
|
104
|
+
return process.env.AWS_BEDROCK_BASE_URL || llmBaseUrl;
|
|
105
|
+
default:
|
|
106
|
+
return llmBaseUrl;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
87
110
|
/**
|
|
88
111
|
* Create a language model instance from provider name + model name.
|
|
89
|
-
* Resolves API keys from environment automatically.
|
|
112
|
+
* Resolves API keys and base URLs from environment automatically.
|
|
90
113
|
* Returns null on failure (graceful degradation for optional features).
|
|
91
114
|
* @param {string} providerName - 'anthropic' | 'openai' | 'google' | 'bedrock'
|
|
92
115
|
* @param {string} modelName - Model identifier (e.g., 'gemini-2.0-flash')
|
|
@@ -98,7 +121,8 @@ export async function createLanguageModel(providerName, modelName) {
|
|
|
98
121
|
if (!resolvedModel) return null;
|
|
99
122
|
try {
|
|
100
123
|
const apiKey = resolveApiKey(providerName);
|
|
101
|
-
const
|
|
124
|
+
const baseURL = resolveBaseUrl(providerName);
|
|
125
|
+
const provider = createProviderInstance({ provider: providerName, ...(apiKey ? { apiKey } : {}), ...(baseURL ? { baseURL } : {}) });
|
|
102
126
|
return provider(resolvedModel);
|
|
103
127
|
} catch {
|
|
104
128
|
return null;
|