summaryrefslogtreecommitdiffhomepage
path: root/packages/api/src/agent-manager.ts
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-06-02 13:02:08 +0900
committerAdam Malczewski <[email protected]>2026-06-02 13:02:08 +0900
commit2503eba38b7885ab92a9c0e4f082323d1b3a8679 (patch)
treecc9ccc2184510d93c601a98ed08a05fdeb146a6f /packages/api/src/agent-manager.ts
parent3f629a8469fe483243671e1ca15582a111e96541 (diff)
downloaddispatch-2503eba38b7885ab92a9c0e4f082323d1b3a8679.tar.gz
dispatch-2503eba38b7885ab92a9c0e4f082323d1b3a8679.zip
feat(agents): per-model reasoning effort level
Add a per-model/key reasoning effort setting to agent definitions, surfaced and editable in the Agent Settings page and displayed at a glance in the model selector views. - core: single source of truth for effort levels (REASONING_EFFORTS, DEFAULT_REASONING_EFFORT='high', labels, isReasoningEffort guard); add 'xhigh' level; AgentModelEntry.effort; xhigh budget=24000 for classic-thinking Claude; default floor 'high'. Persist/parse effort in the agent TOML loader. - api: thread effort through the fallback chain with per-model -> per-tab -> default precedence; validate /chat + agentModels effort from the canonical list. - frontend: effort <select> per model row in AgentBuilder; effort badges in ModelSelector (agent + subagent chains); Thinking dropdown sourced from canonical list; per-tab default raised to 'high'. - tests: +15 (loader round-trip, agent xhigh budget, canonical list + guard, api precedence, route validation).
Diffstat (limited to 'packages/api/src/agent-manager.ts')
-rw-r--r--packages/api/src/agent-manager.ts20
1 files changed, 13 insertions, 7 deletions
diff --git a/packages/api/src/agent-manager.ts b/packages/api/src/agent-manager.ts
index 5a0ffdf..d03e696 100644
--- a/packages/api/src/agent-manager.ts
+++ b/packages/api/src/agent-manager.ts
@@ -1,6 +1,7 @@
import {
Agent,
type AgentEvent,
+ type AgentModelEntry,
type AgentSkillMapping,
type AgentStatus,
appendChunks,
@@ -42,6 +43,7 @@ import {
loadSkills,
ModelRegistry,
type QueuedMessage,
+ type ReasoningEffort,
refreshAccountCredentials,
refreshAccountCredentialsAsync,
resolveApiKey,
@@ -172,7 +174,7 @@ interface TabAgent {
taskList: TaskList;
_lastPermKey?: string;
/** Ordered key+model fallback hierarchy from the agent definition. */
- agentModels?: Array<{ key_id: string; model_id: string }>;
+ agentModels?: AgentModelEntry[];
/** Abort controller for cancelling a running agent. */
abortController?: AbortController;
/** For child agents: resolves when the agent finishes its task. */
@@ -1333,8 +1335,8 @@ export class AgentManager {
opts: {
keyId?: string;
modelId?: string;
- agentModels?: Array<{ key_id: string; model_id: string }>;
- reasoningEffort?: "none" | "low" | "medium" | "high" | "max";
+ agentModels?: AgentModelEntry[];
+ reasoningEffort?: ReasoningEffort;
workingDirectory?: string;
queueId?: string;
/**
@@ -1419,9 +1421,9 @@ export class AgentManager {
message: string,
keyId?: string,
modelId?: string,
- reasoningEffort?: "none" | "low" | "medium" | "high" | "max",
+ reasoningEffort?: ReasoningEffort,
workingDirectory?: string,
- agentModels?: Array<{ key_id: string; model_id: string }>,
+ agentModels?: AgentModelEntry[],
): Promise<void> {
const tabAgent = this._getOrCreateTabAgent(tabId);
@@ -1471,6 +1473,10 @@ export class AgentManager {
// to the tabAgent's stored defaults via the `?? tabAgent.keyId` chain.
currentKeyId = entry.key_id || undefined;
currentModelId = entry.model_id || undefined;
+ // Effort precedence: per-model (agent definition) → per-tab selector
+ // (the `reasoningEffort` arg) → the Agent's own DEFAULT_REASONING_EFFORT
+ // floor (applied inside `agent.run`).
+ const effortForEntry = entry.effort ?? reasoningEffort;
allOutput = "";
// Single ordered chunk list accumulating this attempt's assistant
@@ -1514,7 +1520,7 @@ export class AgentManager {
}
for await (const event of agent.run(message, {
- ...(reasoningEffort ? { reasoningEffort } : {}),
+ ...(effortForEntry ? { reasoningEffort: effortForEntry } : {}),
abortSignal: tabAgent.abortController?.signal,
})) {
// Stop processing if the tab was aborted (closed/stopped).
@@ -1703,7 +1709,7 @@ export class AgentManager {
tabAgent: TabAgent,
keyId?: string,
modelId?: string,
- ): Array<{ key_id: string; model_id: string }> {
+ ): AgentModelEntry[] {
// Agent mode: use the agent's configured fallback hierarchy in strict order
const models = tabAgent.agentModels;
if (models && models.length > 0) {