mirror of
https://github.com/PawanOsman/ChatGPT.git
synced 2026-07-18 08:05:57 +02:00
Enhance agent context handling and feature store options
- Updated the `runAgent` function to include additional parameters for context management, ensuring isolated execution for subagents. - Introduced a new `parseContextLabel` function to convert context size labels into token counts, improving flexibility for model configurations. - Enhanced the `optionsFor` method in `FeatureStore` to ensure every model has a context window option, providing a fallback for models without preset context values. - Refactored sidebar provider logic to utilize the new context parsing function, streamlining context size handling across the application.
This commit is contained in:
+7
-2
@@ -96,6 +96,8 @@ export async function runAgent(opts: RunAgentOptions): Promise<void> {
|
||||
});
|
||||
}
|
||||
let finalText = "";
|
||||
// Isolated context: empty history, own budget, no parent chat steps.
|
||||
// Parent only receives the final summary string (run-result), never sub history.
|
||||
const runP = runAgent({
|
||||
apiBaseUrl,
|
||||
apiKey,
|
||||
@@ -103,12 +105,16 @@ export async function runAgent(opts: RunAgentOptions): Promise<void> {
|
||||
mode: subReadonly ? "ask" : "agent",
|
||||
prompt: subPrompt,
|
||||
history: [],
|
||||
maxTokens,
|
||||
contextTokens,
|
||||
sampling,
|
||||
modelParams,
|
||||
anthropic,
|
||||
oauthKind,
|
||||
systemPromptOverride: subSystemOverride,
|
||||
enableFileReading,
|
||||
enableTerminalSuggestions,
|
||||
enableWorkspaceContext,
|
||||
approve,
|
||||
isSubagent: true,
|
||||
signal: childAC.signal,
|
||||
@@ -116,8 +122,7 @@ export async function runAgent(opts: RunAgentOptions): Promise<void> {
|
||||
if (e.type === "run-result") {
|
||||
finalText = e.text;
|
||||
}
|
||||
// Forward the subagent's stream to the parent so the UI can render it
|
||||
// as a nested read-only sub-chat keyed by the task call id.
|
||||
// UI-only stream; never re-inject subagent steps into parent history.
|
||||
if (callId) {
|
||||
emit({ type: "subagent-event", callId, event: e });
|
||||
}
|
||||
|
||||
+51
-14
@@ -101,6 +101,29 @@ const effort = (value = "medium", values = ["none", "low", "medium", "high"]): M
|
||||
const thinking = (value = "adaptive", values = ["disabled", "adaptive", "enabled"]): ModelOption => ({ key: "thinking", label: "Thinking", type: "select", values, value });
|
||||
const ctx = (values: string[], value: string): ModelOption => ({ key: "max_context", label: "Context", type: "select", values, value });
|
||||
|
||||
/** Fallback context sizes for models with no catalog preset (custom / fetched). */
|
||||
export const DEFAULT_CONTEXT_VALUES = ["32k", "64k", "128k", "200k", "256k", "512k", "1m"];
|
||||
export const DEFAULT_CONTEXT_VALUE = "128k";
|
||||
export const defaultContextOption = (): ModelOption =>
|
||||
ctx([...DEFAULT_CONTEXT_VALUES], DEFAULT_CONTEXT_VALUE);
|
||||
|
||||
/** Parse "200k" / "1m" / "128000" → token count. */
|
||||
export function parseContextLabel(v?: string): number {
|
||||
if (!v) return 0;
|
||||
const s = String(v).trim().toLowerCase();
|
||||
const m = s.match(/^([\d.]+)\s*([kmb])?$/);
|
||||
if (!m) {
|
||||
const n = Number(s.replace(/[^\d.]/g, ""));
|
||||
return Number.isFinite(n) && n > 0 ? Math.floor(n) : 0;
|
||||
}
|
||||
const n = parseFloat(m[1]);
|
||||
const u = m[2];
|
||||
if (u === "m") return Math.floor(n * 1_000_000);
|
||||
if (u === "b") return Math.floor(n * 1_000_000_000);
|
||||
if (u === "k") return Math.floor(n * 1_000);
|
||||
return Math.floor(n);
|
||||
}
|
||||
|
||||
/** Built-in catalog of popular coding models. Users can edit options per model. */
|
||||
export const MODEL_CATALOG: ModelDef[] = [
|
||||
// OpenAI — gpt-5.5 is the current flagship; effort supports none/low/medium/high (xhigh on top tiers).
|
||||
@@ -324,24 +347,38 @@ export class FeatureStore {
|
||||
/** Resolved options for a model: stored overrides take precedence over defaults.
|
||||
* Overrides are kind-scoped ("<kind>:<id>") so the same model id can hold
|
||||
* different option state per provider (e.g. anthropic vs claude-code);
|
||||
* a plain-id record is the legacy/shared fallback. */
|
||||
* a plain-id record is the legacy/shared fallback.
|
||||
* Models with no catalog context option get a default max_context selector. */
|
||||
optionsFor(modelId: string, kind?: string): ModelOption[] {
|
||||
const cfg = this.get();
|
||||
const def = this.defFor(modelId, kind);
|
||||
const saved = (kind ? cfg.modelOptions[`${kind}:${modelId}`] : undefined) ?? cfg.modelOptions[modelId];
|
||||
if (!saved) return def?.options ?? [];
|
||||
if (!def?.options) return saved;
|
||||
// Merge: option shape (label/type/values = model capabilities) always comes
|
||||
// from the current catalog; only the user's selected `value` is persisted.
|
||||
// This keeps stale saved options from hiding newly-added modes/values.
|
||||
const savedValue = new Map(saved.map((o) => [o.key, o.value]));
|
||||
return def.options.map((o) => {
|
||||
const v = savedValue.get(o.key);
|
||||
if (v == null) return o;
|
||||
// Drop a saved value that's no longer a valid choice for this option.
|
||||
if (o.values && !o.values.includes(v)) return o;
|
||||
return { ...o, value: v };
|
||||
});
|
||||
const base: ModelOption[] = (() => {
|
||||
if (!saved) return def?.options ? [...def.options] : [];
|
||||
if (!def?.options) return [...saved];
|
||||
// Merge: option shape (label/type/values = model capabilities) always comes
|
||||
// from the current catalog; only the user's selected `value` is persisted.
|
||||
const savedValue = new Map(saved.map((o) => [o.key, o.value]));
|
||||
return def.options.map((o) => {
|
||||
const v = savedValue.get(o.key);
|
||||
if (v == null) return o;
|
||||
if (o.values && !o.values.includes(v)) return o;
|
||||
return { ...o, value: v };
|
||||
});
|
||||
})();
|
||||
// Ensure every model exposes a context window (catalog or fallback dropdown).
|
||||
if (!base.some((o) => o.key === "max_context")) {
|
||||
const savedCtx = saved?.find((o) => o.key === "max_context")?.value;
|
||||
const fallback = defaultContextOption();
|
||||
if (savedCtx && fallback.values?.includes(savedCtx)) fallback.value = savedCtx;
|
||||
else if (savedCtx) {
|
||||
// Keep a custom value the user typed/saved even if not in the list.
|
||||
fallback.values = [...(fallback.values || []), savedCtx];
|
||||
fallback.value = savedCtx;
|
||||
}
|
||||
base.push(fallback);
|
||||
}
|
||||
return base;
|
||||
}
|
||||
|
||||
/** Friendly catalog label for an id, or the id itself if not catalogued. */
|
||||
|
||||
@@ -14,7 +14,7 @@ import { AgentEvent, Mode, Attachment } from "../agent/types";
|
||||
import { listModels, generateTitle, pickModel } from "../agent/provider";
|
||||
import { renderWebviewHtml } from "./webviewHtml";
|
||||
import { ConversationStore, titleFromText } from "../stores/conversationStore";
|
||||
import { FeatureStore, MODEL_CATALOG, kindMatches, optionsToParams, providerEnabled, type ModelDef, type ModelOption, type ProviderConfig } from "../stores/featureStore";
|
||||
import { FeatureStore, MODEL_CATALOG, kindMatches, optionsToParams, parseContextLabel, providerEnabled, type ModelDef, type ModelOption, type ProviderConfig } from "../stores/featureStore";
|
||||
import { effectiveContextLength, ensureLoaded, isRunning, serverUrlFor } from "../agent/llamacpp";
|
||||
import * as ollama from "../agent/ollama";
|
||||
import * as oauth from "../agent/oauth";
|
||||
@@ -937,12 +937,7 @@ export class SidebarProvider implements vscode.WebviewViewProvider {
|
||||
const m = f.llamacppModels.find((x) => x.id === modelId || x.id === bare);
|
||||
if (m) return effectiveContextLength(m, f.llamacppContextLength);
|
||||
const opt = this.featureStore.optionsFor(bare, oauthKind).find((o) => o.key === "max_context")?.value;
|
||||
const parsed = /^([\d.]+)\s*([km])?$/i.exec((opt || "").trim());
|
||||
if (parsed) {
|
||||
const unit = (parsed[2] || "").toLowerCase();
|
||||
return Math.round(parseFloat(parsed[1]) * (unit === "m" ? 1_000_000 : unit === "k" ? 1_000 : 1));
|
||||
}
|
||||
return 200_000; // ponytail: safe default; refine per-provider when model metadata is available
|
||||
return parseContextLabel(opt) || 128_000;
|
||||
}
|
||||
|
||||
/** Build the picker model list from ALL enabled providers. */
|
||||
|
||||
Reference in New Issue
Block a user