summaryrefslogtreecommitdiffhomepage
path: root/packages/api
diff options
context:
space:
mode:
authorAdam Malczewski <[email protected]>2026-05-29 15:38:35 +0900
committerAdam Malczewski <[email protected]>2026-05-29 15:38:35 +0900
commit48194753eee9c6cb8995cf52afcbd615cf115491 (patch)
treea4aa2c22ed0db272d6848c28f755ad9950418c54 /packages/api
parentaa230050f4edb7bfc8d3e4d59d95c68c36264b41 (diff)
downloaddispatch-48194753eee9c6cb8995cf52afcbd615cf115491.tar.gz
dispatch-48194753eee9c6cb8995cf52afcbd615cf115491.zip
feat: subagent summon — catalog filter, error hints, system prompt, AgentBuilder default, SubAgent mode display
- Filter summon tool catalog to is_subagent-flagged agents only - Return fresh subagent list in error when slug not found - Add subagent hint to system prompt when summon tool available - Default is_subagent checkbox to true in AgentBuilder - Fix tab-created event to include agentSlug and agentModels - Add SubAgent read-only mode to ModelSelector with model slider
Diffstat (limited to 'packages/api')
-rw-r--r--packages/api/src/agent-manager.ts32
1 files changed, 23 insertions, 9 deletions
diff --git a/packages/api/src/agent-manager.ts b/packages/api/src/agent-manager.ts
index 9ed2f51..69c071d 100644
--- a/packages/api/src/agent-manager.ts
+++ b/packages/api/src/agent-manager.ts
@@ -134,10 +134,15 @@ function buildSystemPrompt(toolNames: string[], basePrompt?: string): string {
if (!toolList) return base;
const hasTodo = toolNames.includes("todo");
+ const hasSummon = toolNames.includes("summon");
let prompt = `${base}\n\nYou have access to the following tools:\n\n${toolList}\n\nWhen asked to work with files, use these tools. Always confirm what you did after completing an action.`;
if (hasTodo) {
prompt += `\n\n${TODO_GUIDANCE}`;
}
+ if (hasSummon) {
+ prompt +=
+ '\n\nYou have pre-configured subagent types. Use summon(agent="slug", task="...") to delegate specialized work to a subagent. Use list_files and read_file to inspect available agent definitions.';
+ }
return prompt;
}
@@ -940,9 +945,13 @@ export class AgentManager {
if (options.agentSlug) {
agentDef = loadAgent(options.agentSlug, parentEffectiveDir);
if (!agentDef) {
- throw new Error(
- `Agent definition not found: "${options.agentSlug}". Inspect the agents directories to see available slugs.`,
- );
+ const allDefs = loadAgents(parentEffectiveDir);
+ const subagents = allDefs.filter((d) => d.is_subagent).map((d) => `${d.slug} (${d.name})`);
+ const hint =
+ subagents.length > 0
+ ? ` Available subagents: ${subagents.join(", ")}.`
+ : " No subagent definitions exist yet.";
+ throw new Error(`Agent definition not found: "${options.agentSlug}".${hint}`);
}
}
@@ -989,13 +998,16 @@ export class AgentManager {
tabAgent.workingDirectoryOverride = resolvedWorkingDirectory;
tabAgent.finalOutput = "";
- if (agentDef && agentDef.models.length > 0) {
+ const primary = agentDef?.models[0];
+ if (agentDef && primary) {
// The agent definition specifies its own model fallback chain.
- // Clear keyId/modelId so the fallback sequence uses the
- // definition's models (matches how a top-level tab using this
- // definition would be configured).
- tabAgent.keyId = null;
- tabAgent.modelId = null;
+ // Set keyId/modelId to the primary (first) model in the chain so
+ // the frontend can display the concrete key/model this subagent
+ // was configured with, while `agentModels` drives the fallback
+ // sequence (matches how a top-level tab using this definition
+ // would be configured).
+ tabAgent.keyId = primary.key_id;
+ tabAgent.modelId = primary.model_id;
tabAgent.agentModels = agentDef.models;
} else {
// No definition (or definition has no models) → inherit from
@@ -1036,7 +1048,9 @@ export class AgentManager {
keyId: tabAgent.keyId,
modelId: tabAgent.modelId,
parentTabId: options.parentTabId ?? null,
+ agentSlug: options.agentSlug ?? null,
workingDirectory: resolvedWorkingDirectory ?? null,
+ agentModels: tabAgent.agentModels ?? null,
},
tabId,
);