@charzhu/openjaw-agent 0.2.5 → 0.2.6
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/dist/main.js +451 -40
- package/dist/main.js.map +4 -4
- package/package.json +1 -2
package/dist/main.js
CHANGED
|
@@ -123,6 +123,7 @@ function loadAgentConfig() {
|
|
|
123
123
|
temperature: parsedLlm?.temperature ?? DEFAULT_CONFIG.llm.temperature,
|
|
124
124
|
computer_use: parsedLlm?.computer_use ?? DEFAULT_CONFIG.llm.computer_use,
|
|
125
125
|
use_responses_api: parsedLlm?.use_responses_api ?? DEFAULT_CONFIG.llm.use_responses_api,
|
|
126
|
+
model_reasoning_effort: parsedLlm?.model_reasoning_effort,
|
|
126
127
|
openai_tool_mode: parsedLlm?.openai_tool_mode ?? DEFAULT_CONFIG.llm.openai_tool_mode,
|
|
127
128
|
openai_max_tools: parsedLlm?.openai_max_tools ?? DEFAULT_CONFIG.llm.openai_max_tools,
|
|
128
129
|
openai_mcp_max_tools: parsedLlm?.openai_mcp_max_tools,
|
|
@@ -1973,6 +1974,55 @@ var init_provider_auth = __esm({
|
|
|
1973
1974
|
}
|
|
1974
1975
|
});
|
|
1975
1976
|
|
|
1977
|
+
// src/providers/types.ts
|
|
1978
|
+
function isReasoningEffort(value) {
|
|
1979
|
+
return REASONING_EFFORTS.includes(value);
|
|
1980
|
+
}
|
|
1981
|
+
function reasoningEffortLabel(effort) {
|
|
1982
|
+
switch (effort) {
|
|
1983
|
+
case "none":
|
|
1984
|
+
return "None";
|
|
1985
|
+
case "minimal":
|
|
1986
|
+
return "Minimal";
|
|
1987
|
+
case "low":
|
|
1988
|
+
return "Low";
|
|
1989
|
+
case "medium":
|
|
1990
|
+
return "Medium";
|
|
1991
|
+
case "high":
|
|
1992
|
+
return "High";
|
|
1993
|
+
case "xhigh":
|
|
1994
|
+
return "Extra high";
|
|
1995
|
+
}
|
|
1996
|
+
}
|
|
1997
|
+
function normalizeReasoningEfforts(values) {
|
|
1998
|
+
if (!Array.isArray(values)) return [];
|
|
1999
|
+
const efforts = [];
|
|
2000
|
+
for (const item of values) {
|
|
2001
|
+
if (typeof item !== "string" || !isReasoningEffort(item)) continue;
|
|
2002
|
+
if (!efforts.includes(item)) efforts.push(item);
|
|
2003
|
+
}
|
|
2004
|
+
return efforts;
|
|
2005
|
+
}
|
|
2006
|
+
function defaultReasoningEffort(efforts) {
|
|
2007
|
+
if (efforts.length === 0) return void 0;
|
|
2008
|
+
return efforts.includes("medium") ? "medium" : efforts[0];
|
|
2009
|
+
}
|
|
2010
|
+
function orderedReasoningEfforts(efforts) {
|
|
2011
|
+
return REASONING_EFFORTS.filter((effort) => efforts.includes(effort));
|
|
2012
|
+
}
|
|
2013
|
+
var REASONING_EFFORTS;
|
|
2014
|
+
var init_types = __esm({
|
|
2015
|
+
"src/providers/types.ts"() {
|
|
2016
|
+
"use strict";
|
|
2017
|
+
REASONING_EFFORTS = ["none", "minimal", "low", "medium", "high", "xhigh"];
|
|
2018
|
+
__name(isReasoningEffort, "isReasoningEffort");
|
|
2019
|
+
__name(reasoningEffortLabel, "reasoningEffortLabel");
|
|
2020
|
+
__name(normalizeReasoningEfforts, "normalizeReasoningEfforts");
|
|
2021
|
+
__name(defaultReasoningEffort, "defaultReasoningEffort");
|
|
2022
|
+
__name(orderedReasoningEfforts, "orderedReasoningEfforts");
|
|
2023
|
+
}
|
|
2024
|
+
});
|
|
2025
|
+
|
|
1976
2026
|
// src/providers/copilot.ts
|
|
1977
2027
|
function normalizeCopilotEnterpriseDomain(value) {
|
|
1978
2028
|
return value.replace(/^https?:\/\//, "").replace(/\/+$/, "");
|
|
@@ -2063,20 +2113,67 @@ function safeJsonParse(value) {
|
|
|
2063
2113
|
return {};
|
|
2064
2114
|
}
|
|
2065
2115
|
}
|
|
2066
|
-
function
|
|
2116
|
+
function valueAtPath(value, path3) {
|
|
2117
|
+
let current = value;
|
|
2118
|
+
for (const key of path3) {
|
|
2119
|
+
if (!current || typeof current !== "object" || Array.isArray(current)) return void 0;
|
|
2120
|
+
current = current[key];
|
|
2121
|
+
}
|
|
2122
|
+
return current;
|
|
2123
|
+
}
|
|
2124
|
+
function firstPositiveIntegerAtAny(value, paths2) {
|
|
2125
|
+
for (const path3 of paths2) {
|
|
2126
|
+
const candidate = valueAtPath(value, path3);
|
|
2127
|
+
if (typeof candidate !== "number" || !Number.isFinite(candidate) || candidate <= 0) continue;
|
|
2128
|
+
return Math.trunc(candidate);
|
|
2129
|
+
}
|
|
2130
|
+
return void 0;
|
|
2131
|
+
}
|
|
2132
|
+
function readCopilotContextWindow(capabilities) {
|
|
2133
|
+
return firstPositiveIntegerAtAny(capabilities, [
|
|
2134
|
+
["limits", "max_context_window_tokens"],
|
|
2135
|
+
["limits", "maxContextWindowTokens"],
|
|
2136
|
+
["limits", "max_prompt_tokens"],
|
|
2137
|
+
["max_context_window_tokens"],
|
|
2138
|
+
["maxContextWindowTokens"],
|
|
2139
|
+
["context_window"],
|
|
2140
|
+
["contextWindow"]
|
|
2141
|
+
]);
|
|
2142
|
+
}
|
|
2143
|
+
function readCopilotOutputTokens(capabilities) {
|
|
2144
|
+
return firstPositiveIntegerAtAny(capabilities, [
|
|
2145
|
+
["limits", "max_output_tokens"],
|
|
2146
|
+
["limits", "maxOutputTokens"],
|
|
2147
|
+
["max_output_tokens"],
|
|
2148
|
+
["maxOutputTokens"]
|
|
2149
|
+
]);
|
|
2150
|
+
}
|
|
2151
|
+
function readCopilotReasoningEfforts(capabilities) {
|
|
2152
|
+
return normalizeReasoningEfforts(valueAtPath(capabilities, ["supports", "reasoning_effort"]));
|
|
2153
|
+
}
|
|
2154
|
+
function buildReasoning(effort, modelInfo) {
|
|
2155
|
+
const supported = modelInfo?.supportedReasoningEfforts?.map((option) => option.effort) ?? [];
|
|
2156
|
+
const selected = effort && supported.includes(effort) ? effort : void 0;
|
|
2157
|
+
const effective = selected ?? modelInfo?.defaultReasoningEffort;
|
|
2158
|
+
return effective ? { effort: effective } : void 0;
|
|
2159
|
+
}
|
|
2160
|
+
function parseCopilotModels(body) {
|
|
2067
2161
|
const items = Array.isArray(body.data) ? body.data : [];
|
|
2068
2162
|
const models = [];
|
|
2069
2163
|
for (const item of items) {
|
|
2070
2164
|
if (!item.id || item.model_picker_enabled === false || item.policy?.state === "disabled") continue;
|
|
2071
2165
|
const visionMedia = item.capabilities?.limits?.vision?.supported_media_types ?? [];
|
|
2166
|
+
const supportedReasoning = readCopilotReasoningEfforts(item.capabilities);
|
|
2072
2167
|
models.push({
|
|
2073
2168
|
id: item.id,
|
|
2074
2169
|
name: item.name,
|
|
2075
2170
|
supportedEndpoints: item.supported_endpoints ?? [],
|
|
2076
2171
|
supportsVision: item.capabilities?.supports?.vision === true || visionMedia.some((media) => media.startsWith("image/")),
|
|
2077
2172
|
supportsToolCalls: item.capabilities?.supports?.tool_calls !== false,
|
|
2078
|
-
contextWindow: item.capabilities
|
|
2079
|
-
outputTokens: item.capabilities
|
|
2173
|
+
contextWindow: readCopilotContextWindow(item.capabilities),
|
|
2174
|
+
outputTokens: readCopilotOutputTokens(item.capabilities),
|
|
2175
|
+
supportedReasoningEfforts: supportedReasoning.map((effort) => ({ effort, description: effort })),
|
|
2176
|
+
defaultReasoningEffort: defaultReasoningEffort(supportedReasoning)
|
|
2080
2177
|
});
|
|
2081
2178
|
}
|
|
2082
2179
|
return models;
|
|
@@ -2086,6 +2183,7 @@ var init_copilot = __esm({
|
|
|
2086
2183
|
"src/providers/copilot.ts"() {
|
|
2087
2184
|
"use strict";
|
|
2088
2185
|
init_provider_auth();
|
|
2186
|
+
init_types();
|
|
2089
2187
|
COPILOT_PROVIDER = "github-copilot";
|
|
2090
2188
|
USER_AGENT = "openjaw-agent/0.1.0";
|
|
2091
2189
|
OPENAI_TOOL_NAME2 = /^[A-Za-z0-9_-]{1,64}$/;
|
|
@@ -2100,7 +2198,13 @@ var init_copilot = __esm({
|
|
|
2100
2198
|
__name(hasImageContent, "hasImageContent");
|
|
2101
2199
|
__name(openAIUserContent, "openAIUserContent");
|
|
2102
2200
|
__name(safeJsonParse, "safeJsonParse");
|
|
2103
|
-
__name(
|
|
2201
|
+
__name(valueAtPath, "valueAtPath");
|
|
2202
|
+
__name(firstPositiveIntegerAtAny, "firstPositiveIntegerAtAny");
|
|
2203
|
+
__name(readCopilotContextWindow, "readCopilotContextWindow");
|
|
2204
|
+
__name(readCopilotOutputTokens, "readCopilotOutputTokens");
|
|
2205
|
+
__name(readCopilotReasoningEfforts, "readCopilotReasoningEfforts");
|
|
2206
|
+
__name(buildReasoning, "buildReasoning");
|
|
2207
|
+
__name(parseCopilotModels, "parseCopilotModels");
|
|
2104
2208
|
CopilotProvider = class {
|
|
2105
2209
|
static {
|
|
2106
2210
|
__name(this, "CopilotProvider");
|
|
@@ -2113,7 +2217,14 @@ var init_copilot = __esm({
|
|
|
2113
2217
|
}
|
|
2114
2218
|
async listModels() {
|
|
2115
2219
|
const models = await this.fetchModelInfo();
|
|
2116
|
-
return models.map((model) => ({
|
|
2220
|
+
return models.map((model) => ({
|
|
2221
|
+
id: model.id,
|
|
2222
|
+
name: model.name ?? model.id,
|
|
2223
|
+
contextWindow: model.contextWindow,
|
|
2224
|
+
outputTokens: model.outputTokens,
|
|
2225
|
+
supportedReasoningEfforts: model.supportedReasoningEfforts,
|
|
2226
|
+
defaultReasoningEffort: model.defaultReasoningEffort
|
|
2227
|
+
}));
|
|
2117
2228
|
}
|
|
2118
2229
|
async chat(options) {
|
|
2119
2230
|
const modelInfo = await this.resolveModelInfo(this.config.model);
|
|
@@ -2121,7 +2232,7 @@ var init_copilot = __esm({
|
|
|
2121
2232
|
return this.chatAnthropicMessages(options);
|
|
2122
2233
|
}
|
|
2123
2234
|
if (this.shouldRouteToResponses(modelInfo)) {
|
|
2124
|
-
return this.chatResponses(options);
|
|
2235
|
+
return this.chatResponses(options, modelInfo);
|
|
2125
2236
|
}
|
|
2126
2237
|
return this.chatCompletions(options);
|
|
2127
2238
|
}
|
|
@@ -2178,7 +2289,7 @@ var init_copilot = __esm({
|
|
|
2178
2289
|
throw new Error(`GitHub Copilot models error: ${res.status}${detail ? ` ${detail.slice(0, 160)}` : ""}`);
|
|
2179
2290
|
}
|
|
2180
2291
|
const parsed = await res.json();
|
|
2181
|
-
const models =
|
|
2292
|
+
const models = parseCopilotModels(parsed);
|
|
2182
2293
|
this.modelCache = new Map(models.map((model) => [model.id, model]));
|
|
2183
2294
|
return models;
|
|
2184
2295
|
}
|
|
@@ -2294,12 +2405,14 @@ var init_copilot = __esm({
|
|
|
2294
2405
|
}
|
|
2295
2406
|
return input;
|
|
2296
2407
|
}
|
|
2297
|
-
async chatResponses(options) {
|
|
2408
|
+
async chatResponses(options, modelInfo) {
|
|
2409
|
+
const reasoning = buildReasoning(options.reasoningEffort, modelInfo);
|
|
2298
2410
|
const requestBody = {
|
|
2299
2411
|
model: this.config.model,
|
|
2300
2412
|
input: this.buildResponsesInput(options),
|
|
2301
2413
|
instructions: Array.isArray(options.systemPrompt) ? options.systemPrompt.map((block) => block.text).join("\n\n") : options.systemPrompt,
|
|
2302
|
-
tools: options.tools.length > 0 ? options.tools.map(toResponsesTool) : void 0
|
|
2414
|
+
tools: options.tools.length > 0 ? options.tools.map(toResponsesTool) : void 0,
|
|
2415
|
+
...reasoning && { reasoning, include: ["reasoning.encrypted_content"] }
|
|
2303
2416
|
};
|
|
2304
2417
|
const res = await fetch(`${this.baseUrl()}/responses`, {
|
|
2305
2418
|
method: "POST",
|
|
@@ -2691,7 +2804,16 @@ var init_cost_tracker = __esm({
|
|
|
2691
2804
|
});
|
|
2692
2805
|
|
|
2693
2806
|
// src/context-manager.ts
|
|
2694
|
-
function
|
|
2807
|
+
function contextKey(provider, model) {
|
|
2808
|
+
return `${provider}\0${model}`;
|
|
2809
|
+
}
|
|
2810
|
+
function normalizeContextWindow(value) {
|
|
2811
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) return void 0;
|
|
2812
|
+
return Math.trunc(value);
|
|
2813
|
+
}
|
|
2814
|
+
function getContextWindow(model, metadata) {
|
|
2815
|
+
const liveContextWindow = normalizeContextWindow(metadata?.contextWindow);
|
|
2816
|
+
if (liveContextWindow !== void 0) return liveContextWindow;
|
|
2695
2817
|
if (CONTEXT_WINDOWS[model]) return CONTEXT_WINDOWS[model];
|
|
2696
2818
|
for (const [key, size] of Object.entries(CONTEXT_WINDOWS)) {
|
|
2697
2819
|
if (model.startsWith(key)) return size;
|
|
@@ -2716,12 +2838,45 @@ var init_context_manager = __esm({
|
|
|
2716
2838
|
"gpt-4o": 128e3
|
|
2717
2839
|
};
|
|
2718
2840
|
DEFAULT_CONTEXT_WINDOW = 2e5;
|
|
2841
|
+
__name(contextKey, "contextKey");
|
|
2842
|
+
__name(normalizeContextWindow, "normalizeContextWindow");
|
|
2719
2843
|
__name(getContextWindow, "getContextWindow");
|
|
2720
2844
|
ContextManager = class {
|
|
2721
2845
|
static {
|
|
2722
2846
|
__name(this, "ContextManager");
|
|
2723
2847
|
}
|
|
2724
2848
|
lastTotalTokens = 0;
|
|
2849
|
+
activeProvider = null;
|
|
2850
|
+
liveModelContextWindows = /* @__PURE__ */ new Map();
|
|
2851
|
+
setActiveProvider(provider) {
|
|
2852
|
+
this.activeProvider = provider;
|
|
2853
|
+
}
|
|
2854
|
+
setProviderModelMetadata(provider, models) {
|
|
2855
|
+
const prefix = `${provider}\0`;
|
|
2856
|
+
for (const key of [...this.liveModelContextWindows.keys()]) {
|
|
2857
|
+
if (key.startsWith(prefix)) this.liveModelContextWindows.delete(key);
|
|
2858
|
+
}
|
|
2859
|
+
for (const model of models ?? []) {
|
|
2860
|
+
const contextWindow = normalizeContextWindow(model.contextWindow);
|
|
2861
|
+
if (contextWindow !== void 0) {
|
|
2862
|
+
this.liveModelContextWindows.set(contextKey(provider, model.id), contextWindow);
|
|
2863
|
+
}
|
|
2864
|
+
}
|
|
2865
|
+
}
|
|
2866
|
+
clearProviderModelMetadata(provider) {
|
|
2867
|
+
if (!provider) {
|
|
2868
|
+
this.liveModelContextWindows.clear();
|
|
2869
|
+
return;
|
|
2870
|
+
}
|
|
2871
|
+
const prefix = `${provider}\0`;
|
|
2872
|
+
for (const key of [...this.liveModelContextWindows.keys()]) {
|
|
2873
|
+
if (key.startsWith(prefix)) this.liveModelContextWindows.delete(key);
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
getContextWindow(model) {
|
|
2877
|
+
const liveContextWindow = this.activeProvider ? this.liveModelContextWindows.get(contextKey(this.activeProvider, model)) : void 0;
|
|
2878
|
+
return getContextWindow(model, { contextWindow: liveContextWindow });
|
|
2879
|
+
}
|
|
2725
2880
|
/** Update from actual API response usage */
|
|
2726
2881
|
updateFromUsage(usage2) {
|
|
2727
2882
|
this.lastTotalTokens = usage2.inputTokens + usage2.outputTokens + usage2.cacheReadTokens + usage2.cacheCreationTokens;
|
|
@@ -2733,7 +2888,7 @@ var init_context_manager = __esm({
|
|
|
2733
2888
|
/** Get warning level based on model context window */
|
|
2734
2889
|
getWarningLevel(model, newContentChars = 0) {
|
|
2735
2890
|
const estimated = this.getEstimatedTokens(newContentChars);
|
|
2736
|
-
const limit = getContextWindow(model);
|
|
2891
|
+
const limit = this.getContextWindow(model);
|
|
2737
2892
|
const ratio = estimated / limit;
|
|
2738
2893
|
if (ratio > 0.95) return "critical";
|
|
2739
2894
|
if (ratio > 0.85) return "warning";
|
|
@@ -2741,12 +2896,12 @@ var init_context_manager = __esm({
|
|
|
2741
2896
|
}
|
|
2742
2897
|
/** Get context usage as percentage */
|
|
2743
2898
|
getUsagePercent(model) {
|
|
2744
|
-
const limit = getContextWindow(model);
|
|
2899
|
+
const limit = this.getContextWindow(model);
|
|
2745
2900
|
return limit > 0 ? Math.round(this.lastTotalTokens / limit * 100) : 0;
|
|
2746
2901
|
}
|
|
2747
2902
|
/** Format context display string */
|
|
2748
2903
|
formatContext(model) {
|
|
2749
|
-
const limit = getContextWindow(model);
|
|
2904
|
+
const limit = this.getContextWindow(model);
|
|
2750
2905
|
const fmt2 = /* @__PURE__ */ __name((n) => n >= 1e3 ? `${(n / 1e3).toFixed(0)}K` : String(n), "fmt");
|
|
2751
2906
|
const pct = this.getUsagePercent(model);
|
|
2752
2907
|
return `${fmt2(this.lastTotalTokens)}/${fmt2(limit)} (${pct}%)`;
|
|
@@ -3096,7 +3251,6 @@ var init_context_compressor = __esm({
|
|
|
3096
3251
|
"src/context-compressor.ts"() {
|
|
3097
3252
|
"use strict";
|
|
3098
3253
|
init_providers();
|
|
3099
|
-
init_context_manager();
|
|
3100
3254
|
DEFAULT_COMPRESSION_THRESHOLD = 0.7;
|
|
3101
3255
|
PROTECTED_HEAD = 3;
|
|
3102
3256
|
PROTECTED_TAIL_TOKENS = 2e4;
|
|
@@ -3188,7 +3342,7 @@ Rules:
|
|
|
3188
3342
|
shouldCompress(threshold) {
|
|
3189
3343
|
const t = threshold ?? this.config.llm.compression_threshold ?? DEFAULT_COMPRESSION_THRESHOLD;
|
|
3190
3344
|
const model = this.config.llm.model;
|
|
3191
|
-
const limit = getContextWindow(model);
|
|
3345
|
+
const limit = this.contextManager.getContextWindow(model);
|
|
3192
3346
|
const current = this.contextManager.getEstimatedTokens();
|
|
3193
3347
|
const ratio = current / limit;
|
|
3194
3348
|
if (ratio < t) return false;
|
|
@@ -3281,7 +3435,7 @@ ${summary}
|
|
|
3281
3435
|
async _summarize(middle, _systemPrompt) {
|
|
3282
3436
|
const auxProvider = this._getAuxProvider();
|
|
3283
3437
|
const middleText = buildMiddleText(middle);
|
|
3284
|
-
const contextWindow = getContextWindow(this.config.llm.model);
|
|
3438
|
+
const contextWindow = this.contextManager.getContextWindow(this.config.llm.model);
|
|
3285
3439
|
const targetTokens = Math.max(
|
|
3286
3440
|
SUMMARY_MIN_TOKENS,
|
|
3287
3441
|
Math.min(SUMMARY_MAX_TOKENS, Math.floor(contextWindow * SUMMARY_PCT))
|
|
@@ -4129,6 +4283,7 @@ var init_agent_loop = __esm({
|
|
|
4129
4283
|
cacheMonitor;
|
|
4130
4284
|
telemetry;
|
|
4131
4285
|
contextCompressor;
|
|
4286
|
+
liveModelMetadata = /* @__PURE__ */ new Map();
|
|
4132
4287
|
_compactedOnResume = false;
|
|
4133
4288
|
_toolRoundsInRun = 0;
|
|
4134
4289
|
_skillSuggested = false;
|
|
@@ -4146,6 +4301,7 @@ var init_agent_loop = __esm({
|
|
|
4146
4301
|
this.provider = createProvider(config);
|
|
4147
4302
|
this.costTracker = new CostTracker();
|
|
4148
4303
|
this.contextManager = new ContextManager();
|
|
4304
|
+
this.contextManager.setActiveProvider(config.llm.provider);
|
|
4149
4305
|
this.cacheMonitor = new CacheMonitor();
|
|
4150
4306
|
this.telemetry = new Telemetry("pending");
|
|
4151
4307
|
if (resumeSessionId) {
|
|
@@ -4162,6 +4318,7 @@ var init_agent_loop = __esm({
|
|
|
4162
4318
|
this.telemetry = new Telemetry(this.session.id);
|
|
4163
4319
|
this.telemetry.recordSessionStart(config.llm.model, config.llm.provider);
|
|
4164
4320
|
this.contextCompressor = new ContextCompressor(config, this.contextManager, this.telemetry);
|
|
4321
|
+
void this.refreshActiveModelMetadata();
|
|
4165
4322
|
}
|
|
4166
4323
|
get tools() {
|
|
4167
4324
|
return this.toolRegistry;
|
|
@@ -4191,6 +4348,9 @@ var init_agent_loop = __esm({
|
|
|
4191
4348
|
}
|
|
4192
4349
|
return this.config.llm.provider;
|
|
4193
4350
|
}
|
|
4351
|
+
get reasoningEffort() {
|
|
4352
|
+
return this.config.llm.model_reasoning_effort;
|
|
4353
|
+
}
|
|
4194
4354
|
/**
|
|
4195
4355
|
* Provide the user's response to an ask_user question.
|
|
4196
4356
|
* Called by Chat.tsx or bridges when the user answers.
|
|
@@ -4208,7 +4368,7 @@ var init_agent_loop = __esm({
|
|
|
4208
4368
|
return this._waitingForAskUserFlag;
|
|
4209
4369
|
}
|
|
4210
4370
|
/** Switch provider and/or model at runtime */
|
|
4211
|
-
switchModel(provider, model) {
|
|
4371
|
+
switchModel(provider, model, reasoningEffort) {
|
|
4212
4372
|
let baseUrl = this.config.llm.base_url;
|
|
4213
4373
|
if (baseUrl) {
|
|
4214
4374
|
if (provider === "openai" && baseUrl.includes("/api/anthropic")) {
|
|
@@ -4223,14 +4383,26 @@ var init_agent_loop = __esm({
|
|
|
4223
4383
|
}
|
|
4224
4384
|
this.config = {
|
|
4225
4385
|
...this.config,
|
|
4226
|
-
llm: { ...this.config.llm, provider, model, base_url: baseUrl }
|
|
4386
|
+
llm: { ...this.config.llm, provider, model, base_url: baseUrl, model_reasoning_effort: reasoningEffort }
|
|
4227
4387
|
};
|
|
4228
4388
|
this.provider = createProvider(this.config);
|
|
4389
|
+
this.contextManager.setActiveProvider(provider);
|
|
4229
4390
|
this._toolExposureState = createToolExposureState();
|
|
4230
4391
|
this.session.provider = provider;
|
|
4231
4392
|
this.session.model = model;
|
|
4232
4393
|
saveSession(this.session);
|
|
4233
4394
|
saveAgentConfig(this.config);
|
|
4395
|
+
void this.refreshActiveModelMetadata();
|
|
4396
|
+
}
|
|
4397
|
+
updateReasoningEffort(reasoningEffort) {
|
|
4398
|
+
this.config = {
|
|
4399
|
+
...this.config,
|
|
4400
|
+
llm: { ...this.config.llm, model_reasoning_effort: reasoningEffort }
|
|
4401
|
+
};
|
|
4402
|
+
this.session.provider = this.config.llm.provider;
|
|
4403
|
+
this.session.model = this.config.llm.model;
|
|
4404
|
+
saveSession(this.session);
|
|
4405
|
+
saveAgentConfig(this.config);
|
|
4234
4406
|
}
|
|
4235
4407
|
/** Apply provider config changes that are not expressible as a model-only switch. */
|
|
4236
4408
|
updateProviderConfig(updates) {
|
|
@@ -4239,15 +4411,53 @@ var init_agent_loop = __esm({
|
|
|
4239
4411
|
llm: { ...this.config.llm, ...updates }
|
|
4240
4412
|
};
|
|
4241
4413
|
this.provider = createProvider(this.config);
|
|
4414
|
+
this.contextManager.setActiveProvider(this.config.llm.provider);
|
|
4242
4415
|
this._toolExposureState = createToolExposureState();
|
|
4243
4416
|
this.session.provider = this.config.llm.provider;
|
|
4244
4417
|
this.session.model = this.config.llm.model;
|
|
4245
4418
|
saveSession(this.session);
|
|
4246
4419
|
saveAgentConfig(this.config);
|
|
4420
|
+
void this.refreshActiveModelMetadata();
|
|
4247
4421
|
}
|
|
4248
4422
|
/** List available models from the current provider's API */
|
|
4249
4423
|
async listModels() {
|
|
4250
|
-
|
|
4424
|
+
const models = await this.provider.listModels?.() ?? null;
|
|
4425
|
+
if (models) this.setProviderModelMetadata(this.config.llm.provider, models);
|
|
4426
|
+
return models;
|
|
4427
|
+
}
|
|
4428
|
+
setProviderModelMetadata(provider, models) {
|
|
4429
|
+
const prefix = `${provider}\0`;
|
|
4430
|
+
for (const key of [...this.liveModelMetadata.keys()]) {
|
|
4431
|
+
if (key.startsWith(prefix)) this.liveModelMetadata.delete(key);
|
|
4432
|
+
}
|
|
4433
|
+
for (const model of models ?? []) {
|
|
4434
|
+
this.liveModelMetadata.set(`${provider}\0${model.id}`, model);
|
|
4435
|
+
}
|
|
4436
|
+
this.contextManager.setProviderModelMetadata(provider, models);
|
|
4437
|
+
}
|
|
4438
|
+
getActiveModelMetadata(model = this.config.llm.model) {
|
|
4439
|
+
return this.getModelMetadata(this.config.llm.provider, model);
|
|
4440
|
+
}
|
|
4441
|
+
getModelMetadata(provider, model) {
|
|
4442
|
+
return this.liveModelMetadata.get(`${provider}\0${model}`);
|
|
4443
|
+
}
|
|
4444
|
+
async refreshActiveModelMetadata() {
|
|
4445
|
+
const providerName = this.config.llm.provider;
|
|
4446
|
+
const provider = this.provider;
|
|
4447
|
+
this.contextManager.setActiveProvider(providerName);
|
|
4448
|
+
if (providerName !== "github-copilot") return;
|
|
4449
|
+
try {
|
|
4450
|
+
const models = await provider.listModels?.() ?? null;
|
|
4451
|
+
if (models) {
|
|
4452
|
+
this.setProviderModelMetadata(providerName, models);
|
|
4453
|
+
} else {
|
|
4454
|
+
this.setProviderModelMetadata(providerName, null);
|
|
4455
|
+
this.contextManager.clearProviderModelMetadata(providerName);
|
|
4456
|
+
}
|
|
4457
|
+
} catch {
|
|
4458
|
+
this.setProviderModelMetadata(providerName, null);
|
|
4459
|
+
this.contextManager.clearProviderModelMetadata(providerName);
|
|
4460
|
+
}
|
|
4251
4461
|
}
|
|
4252
4462
|
async listAllModels() {
|
|
4253
4463
|
const { STATIC_MODELS: STATIC_MODELS2 } = await Promise.resolve().then(() => (init_models_static(), models_static_exports));
|
|
@@ -4278,13 +4488,16 @@ var init_agent_loop = __esm({
|
|
|
4278
4488
|
const seen = /* @__PURE__ */ new Set();
|
|
4279
4489
|
if (live && live.length > 0) {
|
|
4280
4490
|
sources[currentProvider] = { source: "live" };
|
|
4491
|
+
this.setProviderModelMetadata(currentProvider, live);
|
|
4281
4492
|
for (const m of live) {
|
|
4282
4493
|
if (seen.has(m.id)) continue;
|
|
4283
4494
|
seen.add(m.id);
|
|
4284
|
-
models.push({ provider: currentProvider, id: m.id, name: m.name, source: "live" });
|
|
4495
|
+
models.push({ provider: currentProvider, id: m.id, name: m.name, contextWindow: m.contextWindow, outputTokens: m.outputTokens, source: "live" });
|
|
4285
4496
|
}
|
|
4286
4497
|
} else {
|
|
4287
4498
|
sources[currentProvider] = { source: "static", error: lastError };
|
|
4499
|
+
this.setProviderModelMetadata(currentProvider, null);
|
|
4500
|
+
this.contextManager.clearProviderModelMetadata(currentProvider);
|
|
4288
4501
|
for (const m of STATIC_MODELS2[currentProvider]) {
|
|
4289
4502
|
if (seen.has(m.id)) continue;
|
|
4290
4503
|
seen.add(m.id);
|
|
@@ -4328,13 +4541,16 @@ var init_agent_loop = __esm({
|
|
|
4328
4541
|
const seen = new Set(models.filter((m) => m.provider === provider && !m.group).map((m) => m.id));
|
|
4329
4542
|
if (live && live.length > 0) {
|
|
4330
4543
|
sources[provider] = { source: "live" };
|
|
4544
|
+
this.setProviderModelMetadata(provider, live);
|
|
4331
4545
|
for (const m of live) {
|
|
4332
4546
|
if (seen.has(m.id)) continue;
|
|
4333
4547
|
seen.add(m.id);
|
|
4334
|
-
models.push({ provider, id: m.id, name: m.name, source: "live" });
|
|
4548
|
+
models.push({ provider, id: m.id, name: m.name, contextWindow: m.contextWindow, outputTokens: m.outputTokens, source: "live" });
|
|
4335
4549
|
}
|
|
4336
4550
|
} else {
|
|
4337
4551
|
sources[provider] = { source: "static", error: lastError };
|
|
4552
|
+
this.setProviderModelMetadata(provider, null);
|
|
4553
|
+
this.contextManager.clearProviderModelMetadata(provider);
|
|
4338
4554
|
for (const m of STATIC_MODELS2[provider]) {
|
|
4339
4555
|
if (seen.has(m.id)) continue;
|
|
4340
4556
|
seen.add(m.id);
|
|
@@ -4592,6 +4808,7 @@ ${summary}
|
|
|
4592
4808
|
messages,
|
|
4593
4809
|
tools,
|
|
4594
4810
|
signal,
|
|
4811
|
+
reasoningEffort: this.config.llm.model_reasoning_effort,
|
|
4595
4812
|
debug: {
|
|
4596
4813
|
toolMode: exposure.mode,
|
|
4597
4814
|
fullToolCount: exposure.fullToolCount,
|
|
@@ -47628,6 +47845,12 @@ ${helpMessage}` : field.label;
|
|
|
47628
47845
|
if (key === "mtime") {
|
|
47629
47846
|
return { mtime: Date.now() };
|
|
47630
47847
|
}
|
|
47848
|
+
if (key === "reasoning") {
|
|
47849
|
+
return {
|
|
47850
|
+
display: getUiState().showReasoning !== false ? "show" : "hide",
|
|
47851
|
+
value: agentLoop.reasoningEffort ?? "default"
|
|
47852
|
+
};
|
|
47853
|
+
}
|
|
47631
47854
|
const ui = getUiState();
|
|
47632
47855
|
return {
|
|
47633
47856
|
config: {
|
|
@@ -47652,6 +47875,30 @@ ${helpMessage}` : field.label;
|
|
|
47652
47875
|
if (typeof params?.key === "string") {
|
|
47653
47876
|
const key = params.key;
|
|
47654
47877
|
const rawValue = String(params.value ?? "").trim();
|
|
47878
|
+
if (key === "reasoning") {
|
|
47879
|
+
if (!rawValue) {
|
|
47880
|
+
return {
|
|
47881
|
+
display: getUiState().showReasoning !== false ? "show" : "hide",
|
|
47882
|
+
value: agentLoop.reasoningEffort ?? "default"
|
|
47883
|
+
};
|
|
47884
|
+
}
|
|
47885
|
+
if (rawValue === "hide" || rawValue === "show") {
|
|
47886
|
+
return { value: rawValue };
|
|
47887
|
+
}
|
|
47888
|
+
const parsed = parseReasoningEffortInput(rawValue);
|
|
47889
|
+
const modelInfo = agentLoop.getActiveModelMetadata();
|
|
47890
|
+
const nextEffort = parsed.clear ? void 0 : modelInfo ? resolveReasoningEffortForModel(modelInfo, parsed.effort) : parsed.effort;
|
|
47891
|
+
agentLoop.updateReasoningEffort(nextEffort);
|
|
47892
|
+
bus.emitEvent({
|
|
47893
|
+
payload: sessionInfoSnapshot(agentLoop, toolRegistry),
|
|
47894
|
+
session_id: agentLoop.sessionId,
|
|
47895
|
+
type: "session.info"
|
|
47896
|
+
});
|
|
47897
|
+
return {
|
|
47898
|
+
info: sessionInfoSnapshot(agentLoop, toolRegistry),
|
|
47899
|
+
value: nextEffort ?? "default"
|
|
47900
|
+
};
|
|
47901
|
+
}
|
|
47655
47902
|
if (key === "model") {
|
|
47656
47903
|
if (!rawValue) {
|
|
47657
47904
|
return { value: agentLoop.model };
|
|
@@ -47665,6 +47912,15 @@ ${helpMessage}` : field.label;
|
|
|
47665
47912
|
provider = flagsStripped[provIdx + 1];
|
|
47666
47913
|
flagsStripped.splice(provIdx, 2);
|
|
47667
47914
|
}
|
|
47915
|
+
let requestedReasoningEffort;
|
|
47916
|
+
let clearReasoningEffort = false;
|
|
47917
|
+
const effortIdx = flagsStripped.findIndex((t) => t === "--reasoning-effort" || t === "--effort");
|
|
47918
|
+
if (effortIdx >= 0) {
|
|
47919
|
+
const parsed = parseReasoningEffortInput(flagsStripped[effortIdx + 1] ?? "");
|
|
47920
|
+
requestedReasoningEffort = parsed.effort;
|
|
47921
|
+
clearReasoningEffort = parsed.clear;
|
|
47922
|
+
flagsStripped.splice(effortIdx, flagsStripped[effortIdx + 1] ? 2 : 1);
|
|
47923
|
+
}
|
|
47668
47924
|
const model = flagsStripped.join(" ").trim();
|
|
47669
47925
|
if (!model) {
|
|
47670
47926
|
throw new Error("config.set model: missing model id");
|
|
@@ -47673,15 +47929,17 @@ ${helpMessage}` : field.label;
|
|
|
47673
47929
|
throw new Error(`config.set model: unknown provider "${provider}"`);
|
|
47674
47930
|
}
|
|
47675
47931
|
const credential_warning = isProviderAuthenticated(provider) ? void 0 : `${PROVIDER_LABELS[provider]} is not connected \u2014 run /connect to add credentials`;
|
|
47932
|
+
const modelInfo = agentLoop.getModelMetadata(provider, model);
|
|
47933
|
+
const reasoningEffort = clearReasoningEffort ? void 0 : requestedReasoningEffort ? modelInfo ? resolveReasoningEffortForModel(modelInfo, requestedReasoningEffort) : requestedReasoningEffort : modelInfo ? resolveReasoningEffortForModel(modelInfo, agentLoop.reasoningEffort) : agentLoop.reasoningEffort;
|
|
47676
47934
|
try {
|
|
47677
|
-
agentLoop.switchModel(provider, model);
|
|
47935
|
+
agentLoop.switchModel(provider, model, reasoningEffort);
|
|
47678
47936
|
} catch (err) {
|
|
47679
47937
|
throw new Error(err instanceof Error ? err.message : String(err));
|
|
47680
47938
|
}
|
|
47681
47939
|
if (persistGlobal) {
|
|
47682
47940
|
const next = {
|
|
47683
47941
|
...agentConfig,
|
|
47684
|
-
llm: { ...agentConfig.llm, model, provider }
|
|
47942
|
+
llm: { ...agentConfig.llm, model, provider, model_reasoning_effort: reasoningEffort }
|
|
47685
47943
|
};
|
|
47686
47944
|
try {
|
|
47687
47945
|
saveAgentConfig(next);
|
|
@@ -47698,6 +47956,7 @@ ${helpMessage}` : field.label;
|
|
|
47698
47956
|
return {
|
|
47699
47957
|
credential_warning,
|
|
47700
47958
|
info: sessionInfoSnapshot(agentLoop, toolRegistry),
|
|
47959
|
+
reasoning_effort: reasoningEffort,
|
|
47701
47960
|
value: model
|
|
47702
47961
|
};
|
|
47703
47962
|
}
|
|
@@ -47952,7 +48211,11 @@ ${helpMessage}` : field.label;
|
|
|
47952
48211
|
bus.registerRpc("model.switch", (params) => {
|
|
47953
48212
|
const provider = String(params.provider ?? agentLoop.providerName);
|
|
47954
48213
|
const model = String(params.model ?? agentLoop.model);
|
|
47955
|
-
|
|
48214
|
+
const rawEffort = typeof params.reasoning_effort === "string" ? params.reasoning_effort : typeof params.effort === "string" ? params.effort : "";
|
|
48215
|
+
const parsedEffort = rawEffort ? parseReasoningEffortInput(rawEffort) : void 0;
|
|
48216
|
+
const modelInfo = agentLoop.getModelMetadata(provider, model);
|
|
48217
|
+
const reasoningEffort = parsedEffort?.clear ? void 0 : parsedEffort?.effort ? modelInfo ? resolveReasoningEffortForModel(modelInfo, parsedEffort.effort) : parsedEffort.effort : modelInfo ? resolveReasoningEffortForModel(modelInfo, agentLoop.reasoningEffort) : agentLoop.reasoningEffort;
|
|
48218
|
+
agentLoop.switchModel(provider, model, reasoningEffort);
|
|
47956
48219
|
return {
|
|
47957
48220
|
info: sessionInfoSnapshot(agentLoop, toolRegistry),
|
|
47958
48221
|
ok: true
|
|
@@ -47964,12 +48227,20 @@ ${helpMessage}` : field.label;
|
|
|
47964
48227
|
const liveResults = await Promise.all(
|
|
47965
48228
|
PROVIDERS2.map((slug) => fetchLiveModels(slug, agentConfig, currentModel))
|
|
47966
48229
|
);
|
|
48230
|
+
for (let i = 0; i < PROVIDERS2.length; i++) {
|
|
48231
|
+
const provider = PROVIDERS2[i];
|
|
48232
|
+
const models = liveResults[i]?.models;
|
|
48233
|
+
if (provider && models) {
|
|
48234
|
+
agentLoop.setProviderModelMetadata(provider, models);
|
|
48235
|
+
}
|
|
48236
|
+
}
|
|
47967
48237
|
const providers = PROVIDERS2.map(
|
|
47968
48238
|
(slug, i) => buildProviderOption(slug, currentProvider, currentModel, liveResults[i]?.models, liveResults[i]?.error)
|
|
47969
48239
|
);
|
|
47970
48240
|
return {
|
|
47971
48241
|
model: currentModel,
|
|
47972
48242
|
provider: currentProvider,
|
|
48243
|
+
reasoning_effort: agentLoop.reasoningEffort,
|
|
47973
48244
|
providers
|
|
47974
48245
|
};
|
|
47975
48246
|
});
|
|
@@ -48714,14 +48985,13 @@ ${helpMessage}` : field.label;
|
|
|
48714
48985
|
}
|
|
48715
48986
|
};
|
|
48716
48987
|
}
|
|
48717
|
-
var PROVIDERS2, PROVIDER_LABELS, PROVIDER_AUTH, isProviderAuthenticated, buildProviderOption, fetchLiveModels, BRIDGE_SOURCES, isBridgeSource, inferBridgeSource, bridgeLabels, bridgeEventLabels, stripBridgeGlyph, firstLogLine, bridgeUser, formatBridgeText, runProcess, contentToText, sessionMessageToMarkdown, usageSnapshot, sessionInfoSnapshot, MCP_TOOL_PREFIX, MAX_TOTAL_TOOLS, syncMcpTools;
|
|
48988
|
+
var PROVIDERS2, PROVIDER_LABELS, PROVIDER_AUTH, isProviderAuthenticated, buildProviderOption, fetchLiveModels, parseReasoningEffortInput, reasoningEffortsForModel, resolveReasoningEffortForModel, BRIDGE_SOURCES, isBridgeSource, inferBridgeSource, bridgeLabels, bridgeEventLabels, stripBridgeGlyph, firstLogLine, bridgeUser, formatBridgeText, runProcess, contentToText, sessionMessageToMarkdown, usageSnapshot, sessionInfoSnapshot, MCP_TOOL_PREFIX, MAX_TOTAL_TOOLS, syncMcpTools;
|
|
48718
48989
|
var init_rpcHandlers = __esm({
|
|
48719
48990
|
"src/rpcHandlers.ts"() {
|
|
48720
48991
|
"use strict";
|
|
48721
48992
|
init_connect();
|
|
48722
48993
|
init_config();
|
|
48723
48994
|
init_copilot_auth();
|
|
48724
|
-
init_context_manager();
|
|
48725
48995
|
init_eventBridge();
|
|
48726
48996
|
init_fork();
|
|
48727
48997
|
init_provider_auth();
|
|
@@ -48733,6 +49003,7 @@ var init_rpcHandlers = __esm({
|
|
|
48733
49003
|
init_clipboard();
|
|
48734
49004
|
init_models_static();
|
|
48735
49005
|
init_providers();
|
|
49006
|
+
init_types();
|
|
48736
49007
|
init_registry3();
|
|
48737
49008
|
PROVIDERS2 = ["anthropic", "openai", "github-copilot"];
|
|
48738
49009
|
PROVIDER_LABELS = {
|
|
@@ -48757,6 +49028,7 @@ var init_rpcHandlers = __esm({
|
|
|
48757
49028
|
const auth = PROVIDER_AUTH[slug];
|
|
48758
49029
|
const authenticated = isProviderAuthenticated(slug);
|
|
48759
49030
|
let models = [];
|
|
49031
|
+
let modelOptions = [];
|
|
48760
49032
|
let source = "static";
|
|
48761
49033
|
if (authenticated) {
|
|
48762
49034
|
if (liveModels && liveModels.length > 0) {
|
|
@@ -48765,10 +49037,12 @@ var init_rpcHandlers = __esm({
|
|
|
48765
49037
|
if (seen.has(m.id)) continue;
|
|
48766
49038
|
seen.add(m.id);
|
|
48767
49039
|
models.push(m.id);
|
|
49040
|
+
modelOptions.push(m);
|
|
48768
49041
|
}
|
|
48769
49042
|
source = "live";
|
|
48770
49043
|
} else {
|
|
48771
49044
|
models = STATIC_MODELS[slug].map((m) => m.id);
|
|
49045
|
+
modelOptions = STATIC_MODELS[slug].map((m) => ({ id: m.id, name: m.name }));
|
|
48772
49046
|
source = "static";
|
|
48773
49047
|
}
|
|
48774
49048
|
}
|
|
@@ -48784,6 +49058,7 @@ var init_rpcHandlers = __esm({
|
|
|
48784
49058
|
is_current: slug === currentProvider,
|
|
48785
49059
|
key_env: auth.key_env,
|
|
48786
49060
|
models,
|
|
49061
|
+
model_options: modelOptions,
|
|
48787
49062
|
name: PROVIDER_LABELS[slug],
|
|
48788
49063
|
slug,
|
|
48789
49064
|
source,
|
|
@@ -48819,6 +49094,22 @@ var init_rpcHandlers = __esm({
|
|
|
48819
49094
|
return { error: err instanceof Error ? err.message : String(err), models: null };
|
|
48820
49095
|
}
|
|
48821
49096
|
}, "fetchLiveModels");
|
|
49097
|
+
parseReasoningEffortInput = /* @__PURE__ */ __name((value) => {
|
|
49098
|
+
const normalized = value.trim().toLowerCase();
|
|
49099
|
+
if (!normalized || normalized === "default" || normalized === "clear" || normalized === "auto") {
|
|
49100
|
+
return { clear: true };
|
|
49101
|
+
}
|
|
49102
|
+
if (!isReasoningEffort(normalized)) {
|
|
49103
|
+
throw new Error(`unknown reasoning effort: ${value}`);
|
|
49104
|
+
}
|
|
49105
|
+
return { clear: false, effort: normalized };
|
|
49106
|
+
}, "parseReasoningEffortInput");
|
|
49107
|
+
reasoningEffortsForModel = /* @__PURE__ */ __name((model) => model?.supportedReasoningEfforts?.map((option) => option.effort) ?? [], "reasoningEffortsForModel");
|
|
49108
|
+
resolveReasoningEffortForModel = /* @__PURE__ */ __name((model, requested) => {
|
|
49109
|
+
const supported = reasoningEffortsForModel(model);
|
|
49110
|
+
const selected = requested && supported.includes(requested) ? requested : void 0;
|
|
49111
|
+
return selected ?? model?.defaultReasoningEffort ?? defaultReasoningEffort(supported);
|
|
49112
|
+
}, "resolveReasoningEffortForModel");
|
|
48822
49113
|
BRIDGE_SOURCES = ["telegram", "teams", "feishu", "wechat"];
|
|
48823
49114
|
isBridgeSource = /* @__PURE__ */ __name((value) => typeof value === "string" && BRIDGE_SOURCES.includes(value), "isBridgeSource");
|
|
48824
49115
|
inferBridgeSource = /* @__PURE__ */ __name((event) => {
|
|
@@ -48918,7 +49209,7 @@ ${raw}`;
|
|
|
48918
49209
|
}, "sessionMessageToMarkdown");
|
|
48919
49210
|
usageSnapshot = /* @__PURE__ */ __name((agentLoop) => {
|
|
48920
49211
|
const cost = agentLoop.costTracker.getSessionCost();
|
|
48921
|
-
const contextMax = getContextWindow(agentLoop.model);
|
|
49212
|
+
const contextMax = agentLoop.contextManager.getContextWindow(agentLoop.model);
|
|
48922
49213
|
const contextUsed = agentLoop.contextManager.lastPromptTokens;
|
|
48923
49214
|
return {
|
|
48924
49215
|
cache_read: cost.totalCacheReadTokens,
|
|
@@ -48938,6 +49229,7 @@ ${raw}`;
|
|
|
48938
49229
|
sessionInfoSnapshot = /* @__PURE__ */ __name((agentLoop, toolRegistry) => ({
|
|
48939
49230
|
cwd: process.cwd(),
|
|
48940
49231
|
model: agentLoop.model,
|
|
49232
|
+
reasoning_effort: agentLoop.reasoningEffort,
|
|
48941
49233
|
skills: {},
|
|
48942
49234
|
system_prompt: "",
|
|
48943
49235
|
tools: { [agentLoop.providerName]: toolRegistry.listTools().map((t) => t.name) },
|
|
@@ -56602,12 +56894,15 @@ import { Fragment as Fragment5, jsx as jsx25, jsxs as jsxs13 } from "react/jsx-r
|
|
|
56602
56894
|
function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t }) {
|
|
56603
56895
|
const [providers, setProviders] = useState19([]);
|
|
56604
56896
|
const [currentModel, setCurrentModel] = useState19("");
|
|
56897
|
+
const [currentReasoningEffort, setCurrentReasoningEffort] = useState19();
|
|
56605
56898
|
const [err, setErr] = useState19("");
|
|
56606
56899
|
const [loading, setLoading] = useState19(true);
|
|
56607
56900
|
const [persistGlobal, setPersistGlobal] = useState19(false);
|
|
56608
56901
|
const [providerIdx, setProviderIdx] = useState19(0);
|
|
56609
56902
|
const [modelIdx, setModelIdx] = useState19(0);
|
|
56903
|
+
const [effortIdx, setEffortIdx] = useState19(0);
|
|
56610
56904
|
const [stage, setStage] = useState19("provider");
|
|
56905
|
+
const [selectedModelForEffort, setSelectedModelForEffort] = useState19(null);
|
|
56611
56906
|
const [keyInput, setKeyInput] = useState19("");
|
|
56612
56907
|
const [keySaving, setKeySaving] = useState19(false);
|
|
56613
56908
|
const [keyError, setKeyError] = useState19("");
|
|
@@ -56633,6 +56928,7 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56633
56928
|
const next = r.providers ?? [];
|
|
56634
56929
|
setProviders(next);
|
|
56635
56930
|
setCurrentModel(String(r.model ?? ""));
|
|
56931
|
+
setCurrentReasoningEffort(r.reasoning_effort);
|
|
56636
56932
|
setProviderIdx(
|
|
56637
56933
|
Math.max(
|
|
56638
56934
|
0,
|
|
@@ -56640,6 +56936,8 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56640
56936
|
)
|
|
56641
56937
|
);
|
|
56642
56938
|
setModelIdx(0);
|
|
56939
|
+
setEffortIdx(0);
|
|
56940
|
+
setSelectedModelForEffort(null);
|
|
56643
56941
|
setStage("provider");
|
|
56644
56942
|
setErr("");
|
|
56645
56943
|
setLoading(false);
|
|
@@ -56650,8 +56948,34 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56650
56948
|
});
|
|
56651
56949
|
}, [gw, sessionId]);
|
|
56652
56950
|
const provider = providers[providerIdx];
|
|
56653
|
-
const
|
|
56951
|
+
const modelOptions = useMemo12(() => {
|
|
56952
|
+
if (!provider) return [];
|
|
56953
|
+
if (provider.model_options?.length) return provider.model_options;
|
|
56954
|
+
return (provider.models ?? []).map((id) => ({ id }));
|
|
56955
|
+
}, [provider]);
|
|
56956
|
+
const models = useMemo12(() => modelOptions.map((model) => model.id), [modelOptions]);
|
|
56957
|
+
const effortChoices = useMemo12(() => modelReasoningEfforts(selectedModelForEffort), [selectedModelForEffort]);
|
|
56958
|
+
const providerHasReasoningStage = modelOptions.some((model) => modelReasoningEfforts(model).length > 1);
|
|
56654
56959
|
const names = useMemo12(() => providerDisplayNames(providers), [providers]);
|
|
56960
|
+
const selectionScopeFlag = /* @__PURE__ */ __name(() => persistGlobal ? " --global" : ` ${TUI_SESSION_MODEL_FLAG}`, "selectionScopeFlag");
|
|
56961
|
+
const selectModel = /* @__PURE__ */ __name((model, effort) => {
|
|
56962
|
+
if (!provider) return;
|
|
56963
|
+
onSelect(`${model.id} --provider ${provider.slug} --reasoning-effort ${effort}${selectionScopeFlag()}`);
|
|
56964
|
+
}, "selectModel");
|
|
56965
|
+
const chooseModel = /* @__PURE__ */ __name((model) => {
|
|
56966
|
+
if (!model) {
|
|
56967
|
+
setStage("provider");
|
|
56968
|
+
return;
|
|
56969
|
+
}
|
|
56970
|
+
const efforts = modelReasoningEfforts(model);
|
|
56971
|
+
if (efforts.length > 1) {
|
|
56972
|
+
setSelectedModelForEffort(model);
|
|
56973
|
+
setEffortIdx(initialEffortIndex(efforts, currentReasoningEffort, defaultReasoningForModel(model, efforts)));
|
|
56974
|
+
setStage("effort");
|
|
56975
|
+
return;
|
|
56976
|
+
}
|
|
56977
|
+
selectModel(model, efforts[0] ?? "default");
|
|
56978
|
+
}, "chooseModel");
|
|
56655
56979
|
useEffect17(() => {
|
|
56656
56980
|
mountedRef.current = true;
|
|
56657
56981
|
return () => {
|
|
@@ -56672,6 +56996,7 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56672
56996
|
}
|
|
56673
56997
|
setProviders(r.providers ?? []);
|
|
56674
56998
|
setCurrentModel(String(r.model ?? ""));
|
|
56999
|
+
setCurrentReasoningEffort(r.reasoning_effort);
|
|
56675
57000
|
}).catch(() => {
|
|
56676
57001
|
}), "refreshProviders");
|
|
56677
57002
|
const cancelActiveOAuth = /* @__PURE__ */ __name(() => {
|
|
@@ -56767,9 +57092,17 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56767
57092
|
setOauthError("");
|
|
56768
57093
|
return;
|
|
56769
57094
|
}
|
|
57095
|
+
if (stage === "effort") {
|
|
57096
|
+
setStage("model");
|
|
57097
|
+
setEffortIdx(0);
|
|
57098
|
+
setSelectedModelForEffort(null);
|
|
57099
|
+
return;
|
|
57100
|
+
}
|
|
56770
57101
|
if (stage === "model" || stage === "key" || stage === "disconnect") {
|
|
56771
57102
|
setStage("provider");
|
|
56772
57103
|
setModelIdx(0);
|
|
57104
|
+
setEffortIdx(0);
|
|
57105
|
+
setSelectedModelForEffort(null);
|
|
56773
57106
|
setKeyInput("");
|
|
56774
57107
|
setKeyError("");
|
|
56775
57108
|
setKeySaving(false);
|
|
@@ -56867,7 +57200,7 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56867
57200
|
if (r?.disconnected) {
|
|
56868
57201
|
setProviders(
|
|
56869
57202
|
(prev) => prev.map(
|
|
56870
|
-
(p) => p.slug === provider.slug ? { ...p, authenticated: false, models: [], total_models: 0, warning: p.key_env ? `paste ${p.key_env} to activate` : "run `hermes model` to configure" } : p
|
|
57203
|
+
(p) => p.slug === provider.slug ? { ...p, authenticated: false, models: [], model_options: [], total_models: 0, warning: p.key_env ? `paste ${p.key_env} to activate` : "run `hermes model` to configure" } : p
|
|
56871
57204
|
)
|
|
56872
57205
|
);
|
|
56873
57206
|
}
|
|
@@ -56885,9 +57218,9 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56885
57218
|
}
|
|
56886
57219
|
return;
|
|
56887
57220
|
}
|
|
56888
|
-
const count = stage === "provider" ? providers.length : models.length;
|
|
56889
|
-
const sel = stage === "provider" ? providerIdx : modelIdx;
|
|
56890
|
-
const setSel = stage === "provider" ? setProviderIdx : setModelIdx;
|
|
57221
|
+
const count = stage === "provider" ? providers.length : stage === "effort" ? effortChoices.length : models.length;
|
|
57222
|
+
const sel = stage === "provider" ? providerIdx : stage === "effort" ? effortIdx : modelIdx;
|
|
57223
|
+
const setSel = stage === "provider" ? setProviderIdx : stage === "effort" ? setEffortIdx : setModelIdx;
|
|
56891
57224
|
if (key.upArrow && sel > 0) {
|
|
56892
57225
|
setSel((v) => v - 1);
|
|
56893
57226
|
return;
|
|
@@ -56922,12 +57255,16 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
56922
57255
|
setModelIdx(0);
|
|
56923
57256
|
return;
|
|
56924
57257
|
}
|
|
56925
|
-
|
|
56926
|
-
|
|
56927
|
-
|
|
56928
|
-
|
|
56929
|
-
|
|
57258
|
+
if (stage === "effort") {
|
|
57259
|
+
const effort = effortChoices[effortIdx];
|
|
57260
|
+
if (selectedModelForEffort && effort) {
|
|
57261
|
+
selectModel(selectedModelForEffort, effort);
|
|
57262
|
+
} else {
|
|
57263
|
+
setStage("model");
|
|
57264
|
+
}
|
|
57265
|
+
return;
|
|
56930
57266
|
}
|
|
57267
|
+
chooseModel(modelOptions[modelIdx]);
|
|
56931
57268
|
return;
|
|
56932
57269
|
}
|
|
56933
57270
|
if (ch.toLowerCase() === "g") {
|
|
@@ -57090,7 +57427,11 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
57090
57427
|
);
|
|
57091
57428
|
const { items: items2, offset: offset2 } = windowItems(rows, providerIdx, VISIBLE2);
|
|
57092
57429
|
return /* @__PURE__ */ jsxs13(Box_default, { flexDirection: "column", width, children: [
|
|
57093
|
-
/* @__PURE__ */
|
|
57430
|
+
/* @__PURE__ */ jsxs13(Text9, { bold: true, color: t.color.accent, wrap: "truncate-end", children: [
|
|
57431
|
+
"Select provider (step 1/",
|
|
57432
|
+
providerHasReasoningStage ? "3" : "2",
|
|
57433
|
+
")"
|
|
57434
|
+
] }),
|
|
57094
57435
|
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: "Full model IDs on the next step \xB7 Enter to continue" }),
|
|
57095
57436
|
/* @__PURE__ */ jsxs13(Text9, { color: t.color.muted, wrap: "truncate-end", children: [
|
|
57096
57437
|
"Current: ",
|
|
@@ -57129,9 +57470,61 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
57129
57470
|
/* @__PURE__ */ jsx25(OverlayHint, { t, children: "\u2191/\u2193 select \xB7 Enter choose \xB7 d disconnect \xB7 Esc/q cancel" })
|
|
57130
57471
|
] });
|
|
57131
57472
|
}
|
|
57473
|
+
if (stage === "effort") {
|
|
57474
|
+
const defaultEffort = defaultReasoningForModel(selectedModelForEffort, effortChoices);
|
|
57475
|
+
const warningEffort = effortChoices.includes("xhigh") ? "xhigh" : effortChoices.includes("high") ? "high" : void 0;
|
|
57476
|
+
const warningText = warningEffort ? `\u26A0 ${reasoningEffortLabel(warningEffort)} reasoning can quickly consume rate limits.` : " ";
|
|
57477
|
+
const { items: items2, offset: offset2 } = windowItems(effortChoices, effortIdx, VISIBLE2);
|
|
57478
|
+
return /* @__PURE__ */ jsxs13(Box_default, { flexDirection: "column", width, children: [
|
|
57479
|
+
/* @__PURE__ */ jsx25(Text9, { bold: true, color: t.color.accent, wrap: "truncate-end", children: "Select reasoning level (step 3/3)" }),
|
|
57480
|
+
/* @__PURE__ */ jsxs13(Text9, { color: t.color.muted, wrap: "truncate-end", children: [
|
|
57481
|
+
modelOptionID(selectedModelForEffort ?? void 0) || "(unknown model)",
|
|
57482
|
+
" \xB7 Esc back"
|
|
57483
|
+
] }),
|
|
57484
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.label, wrap: "truncate-end", children: warningText }),
|
|
57485
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: offset2 > 0 ? ` \u2191 ${offset2} more` : " " }),
|
|
57486
|
+
Array.from({ length: VISIBLE2 }, (_, i) => {
|
|
57487
|
+
const effort = items2[i];
|
|
57488
|
+
const idx = offset2 + i;
|
|
57489
|
+
if (!effort) {
|
|
57490
|
+
return !effortChoices.length && i === 0 ? /* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: "no reasoning levels listed for this model" }, "empty-effort") : /* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: " " }, `pad-effort-${i}`);
|
|
57491
|
+
}
|
|
57492
|
+
const option = selectedModelForEffort?.supportedReasoningEfforts?.find((o) => o.effort === effort);
|
|
57493
|
+
const description = option?.description && option.description !== effort ? ` \xB7 ${option.description}` : "";
|
|
57494
|
+
const label = `${reasoningEffortLabel(effort)}${effort === defaultEffort ? " (default)" : ""}${description}`;
|
|
57495
|
+
return /* @__PURE__ */ jsxs13(
|
|
57496
|
+
Text9,
|
|
57497
|
+
{
|
|
57498
|
+
bold: effortIdx === idx,
|
|
57499
|
+
color: effortIdx === idx ? t.color.accent : t.color.muted,
|
|
57500
|
+
inverse: effortIdx === idx,
|
|
57501
|
+
wrap: "truncate-end",
|
|
57502
|
+
children: [
|
|
57503
|
+
effortIdx === idx ? "\u25B8 " : currentReasoningEffort === effort ? "* " : " ",
|
|
57504
|
+
idx + 1,
|
|
57505
|
+
". ",
|
|
57506
|
+
label
|
|
57507
|
+
]
|
|
57508
|
+
},
|
|
57509
|
+
`${modelOptionID(selectedModelForEffort ?? void 0)}:${effort}`
|
|
57510
|
+
);
|
|
57511
|
+
}),
|
|
57512
|
+
/* @__PURE__ */ jsx25(Text9, { color: t.color.muted, wrap: "truncate-end", children: offset2 + VISIBLE2 < effortChoices.length ? ` \u2193 ${effortChoices.length - offset2 - VISIBLE2} more` : " " }),
|
|
57513
|
+
/* @__PURE__ */ jsxs13(Text9, { color: t.color.muted, wrap: "truncate-end", children: [
|
|
57514
|
+
"persist: ",
|
|
57515
|
+
persistGlobal ? "global" : "session",
|
|
57516
|
+
" \xB7 g toggle"
|
|
57517
|
+
] }),
|
|
57518
|
+
/* @__PURE__ */ jsx25(OverlayHint, { t, children: "\u2191/\u2193 select \xB7 Enter switch \xB7 Esc back \xB7 q close" })
|
|
57519
|
+
] });
|
|
57520
|
+
}
|
|
57132
57521
|
const { items, offset } = windowItems(models, modelIdx, VISIBLE2);
|
|
57133
57522
|
return /* @__PURE__ */ jsxs13(Box_default, { flexDirection: "column", width, children: [
|
|
57134
|
-
/* @__PURE__ */
|
|
57523
|
+
/* @__PURE__ */ jsxs13(Text9, { bold: true, color: t.color.accent, wrap: "truncate-end", children: [
|
|
57524
|
+
"Select model (step 2/",
|
|
57525
|
+
providerHasReasoningStage ? "3" : "2",
|
|
57526
|
+
")"
|
|
57527
|
+
] }),
|
|
57135
57528
|
/* @__PURE__ */ jsxs13(Text9, { color: t.color.muted, wrap: "truncate-end", children: [
|
|
57136
57529
|
names[providerIdx] || "(unknown provider)",
|
|
57137
57530
|
" \xB7 Esc back"
|
|
@@ -57171,7 +57564,7 @@ function ModelPicker2({ gw, mode = "switch", onCancel, onSelect, sessionId, t })
|
|
|
57171
57564
|
/* @__PURE__ */ jsx25(OverlayHint, { t, children: models.length ? "\u2191/\u2193 select \xB7 Enter switch \xB7 Esc back \xB7 q close" : "Enter/Esc back \xB7 q close" })
|
|
57172
57565
|
] });
|
|
57173
57566
|
}
|
|
57174
|
-
var VISIBLE2, MIN_WIDTH2, MAX_WIDTH2;
|
|
57567
|
+
var VISIBLE2, MIN_WIDTH2, MAX_WIDTH2, modelOptionID, modelReasoningEfforts, defaultReasoningForModel, initialEffortIndex;
|
|
57175
57568
|
var init_modelPicker = __esm({
|
|
57176
57569
|
"src/components/modelPicker.tsx"() {
|
|
57177
57570
|
"use strict";
|
|
@@ -57179,10 +57572,28 @@ var init_modelPicker = __esm({
|
|
|
57179
57572
|
init_providers2();
|
|
57180
57573
|
init_slash();
|
|
57181
57574
|
init_rpc();
|
|
57575
|
+
init_types();
|
|
57182
57576
|
init_overlayControls();
|
|
57183
57577
|
VISIBLE2 = 12;
|
|
57184
57578
|
MIN_WIDTH2 = 40;
|
|
57185
57579
|
MAX_WIDTH2 = 90;
|
|
57580
|
+
modelOptionID = /* @__PURE__ */ __name((model) => model?.id ?? "", "modelOptionID");
|
|
57581
|
+
modelReasoningEfforts = /* @__PURE__ */ __name((model) => {
|
|
57582
|
+
const efforts = model?.supportedReasoningEfforts?.map((option) => option.effort) ?? [];
|
|
57583
|
+
return orderedReasoningEfforts(efforts);
|
|
57584
|
+
}, "modelReasoningEfforts");
|
|
57585
|
+
defaultReasoningForModel = /* @__PURE__ */ __name((model, efforts = modelReasoningEfforts(model)) => {
|
|
57586
|
+
const configured = model?.defaultReasoningEffort;
|
|
57587
|
+
if (configured && efforts.includes(configured)) {
|
|
57588
|
+
return configured;
|
|
57589
|
+
}
|
|
57590
|
+
return efforts[0];
|
|
57591
|
+
}, "defaultReasoningForModel");
|
|
57592
|
+
initialEffortIndex = /* @__PURE__ */ __name((efforts, current, fallback) => {
|
|
57593
|
+
const selected = current && efforts.includes(current) ? current : fallback;
|
|
57594
|
+
const idx = selected ? efforts.indexOf(selected) : -1;
|
|
57595
|
+
return idx >= 0 ? idx : 0;
|
|
57596
|
+
}, "initialEffortIndex");
|
|
57186
57597
|
__name(ModelPicker2, "ModelPicker");
|
|
57187
57598
|
}
|
|
57188
57599
|
});
|