@dreb/coding-agent 2.23.0 → 2.25.0
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/CHANGELOG.md +4 -0
- package/README.md +2 -0
- package/dist/core/agent-session.d.ts +11 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +35 -2
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/types.d.ts +14 -1
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +4 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/settings-manager.d.ts +14 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +41 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tools/index.d.ts +1 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +1 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/subagent.d.ts +5 -1
- package/dist/core/tools/subagent.d.ts.map +1 -1
- package/dist/core/tools/subagent.js +51 -13
- package/dist/core/tools/subagent.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +36 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +195 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +51 -1
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/tab-title.d.ts +5 -0
- package/dist/modes/interactive/tab-title.d.ts.map +1 -1
- package/dist/modes/interactive/tab-title.js +6 -0
- package/dist/modes/interactive/tab-title.js.map +1 -1
- package/docs/agent-models.md +64 -0
- package/docs/extensions.md +13 -0
- package/docs/mach6.md +2 -0
- package/docs/settings.md +18 -0
- package/package.json +1 -1
|
@@ -65,7 +65,7 @@ export function parseAgentFrontmatter(content) {
|
|
|
65
65
|
},
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
|
-
function discoverAgentTypes(cwd) {
|
|
68
|
+
export function discoverAgentTypes(cwd) {
|
|
69
69
|
const agents = new Map();
|
|
70
70
|
// Package-bundled agents (shipped with dreb — the canonical source of truth for built-in agents)
|
|
71
71
|
const packageAgentsDir = join(getPackageDir(), "agents");
|
|
@@ -321,6 +321,12 @@ async function spawnSubagent(agentConfig, task, cwd, signal, onProgress, parentP
|
|
|
321
321
|
}
|
|
322
322
|
}
|
|
323
323
|
const output = outputParts.join("\n\n");
|
|
324
|
+
// Inspect the final assistant message's stopReason to detect truncation
|
|
325
|
+
// ("length") or a loud truncation failure ("error") from the core agent loop.
|
|
326
|
+
// stopReason is present at runtime even though collectedMessages is loosely typed.
|
|
327
|
+
const lastMsg = collectedMessages.length > 0 ? collectedMessages[collectedMessages.length - 1] : undefined;
|
|
328
|
+
const lastStopReason = lastMsg ? lastMsg.stopReason : undefined;
|
|
329
|
+
const lastErrorMessage = lastMsg ? lastMsg.errorMessage : undefined;
|
|
324
330
|
// Build error message from best available source: stderr, plain stdout lines, or generic
|
|
325
331
|
let errorMessage = null;
|
|
326
332
|
if (exitCode !== 0) {
|
|
@@ -329,6 +335,29 @@ async function spawnSubagent(agentConfig, task, cwd, signal, onProgress, parentP
|
|
|
329
335
|
errorMessage =
|
|
330
336
|
stderrTrimmed.slice(0, 500) || plainOutput.slice(0, 500) || `Subagent exited with code ${exitCode}`;
|
|
331
337
|
}
|
|
338
|
+
else if (output.trim() === "") {
|
|
339
|
+
// Clean exit but no output — surface why instead of returning a silent empty result.
|
|
340
|
+
if (lastStopReason === "length") {
|
|
341
|
+
errorMessage = "Subagent response was truncated at the model's token limit before producing any output.";
|
|
342
|
+
}
|
|
343
|
+
else if (lastStopReason === "error" && lastErrorMessage) {
|
|
344
|
+
errorMessage = String(lastErrorMessage).slice(0, 500);
|
|
345
|
+
}
|
|
346
|
+
else {
|
|
347
|
+
errorMessage = "Subagent completed with no output.";
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
else if (lastStopReason === "length") {
|
|
351
|
+
// Clean exit with partial output — keep the output but make the truncation loud.
|
|
352
|
+
errorMessage = "Subagent response was truncated at the model's token limit; output may be incomplete.";
|
|
353
|
+
}
|
|
354
|
+
else if (lastStopReason === "error" && lastErrorMessage) {
|
|
355
|
+
// Clean exit with partial output but a loud failure (e.g. length retries
|
|
356
|
+
// exhausted → the core agent loop converts the truncation to stopReason
|
|
357
|
+
// "error" while preserving the partial text). Surface the error instead of
|
|
358
|
+
// letting the partial output masquerade as a clean success.
|
|
359
|
+
errorMessage = String(lastErrorMessage).slice(0, 500);
|
|
360
|
+
}
|
|
332
361
|
// Discover the session file written by the child process
|
|
333
362
|
const sessionFile = sessionDir ? discoverSessionFile(sessionDir, agentConfig.name) : undefined;
|
|
334
363
|
resolvePromise({
|
|
@@ -681,7 +710,7 @@ function clampCwd(defaultCwd, itemCwd) {
|
|
|
681
710
|
}
|
|
682
711
|
return { ok: true, cwd: resolved };
|
|
683
712
|
}
|
|
684
|
-
export async function executeSingle(agents, agentName, task, cwd, signal, onProgress, modelOverride, parentProvider, registry, sessionDir, parentModel) {
|
|
713
|
+
export async function executeSingle(agents, agentName, task, cwd, signal, onProgress, modelOverride, parentProvider, registry, sessionDir, parentModel, agentModels) {
|
|
685
714
|
const name = agentName || DEFAULT_AGENT;
|
|
686
715
|
const config = agents.get(name);
|
|
687
716
|
if (!config) {
|
|
@@ -705,9 +734,9 @@ export async function executeSingle(agents, agentName, task, cwd, signal, onProg
|
|
|
705
734
|
errorMessage: `Task prompt too long (${task.length} chars, max ${MAX_TASK_LENGTH}). Shorten the prompt.`,
|
|
706
735
|
};
|
|
707
736
|
}
|
|
708
|
-
// Per-invocation model override takes precedence over agent definition model.
|
|
709
|
-
// Override is always a single string; agent config may be
|
|
710
|
-
const modelSpec = modelOverride || config.model;
|
|
737
|
+
// Per-invocation model override takes precedence over agent settings, which take precedence over agent definition model.
|
|
738
|
+
// Override is always a single string; agentModels and agent config may be arrays.
|
|
739
|
+
const modelSpec = modelOverride || (agentModels && agentModels.length > 0 ? agentModels : undefined) || config.model;
|
|
711
740
|
let effectiveConfig = modelOverride ? { ...config, model: modelOverride } : config;
|
|
712
741
|
let resolvedProvider = parentProvider;
|
|
713
742
|
let warning;
|
|
@@ -738,15 +767,16 @@ export async function executeSingle(agents, agentName, task, cwd, signal, onProg
|
|
|
738
767
|
}
|
|
739
768
|
warning = resolved.warning;
|
|
740
769
|
}
|
|
741
|
-
|
|
770
|
+
const usedModel = effectiveConfig.model?.toString();
|
|
771
|
+
onProgress?.(`Running ${name} agent${usedModel ? ` (${usedModel})` : ""}...`);
|
|
742
772
|
const result = await spawnSubagent(effectiveConfig, task, cwd, signal, onProgress, resolvedProvider, sessionDir);
|
|
743
|
-
result.output = prependModelFallbackSummary(result.output, skippedModels, result.model ??
|
|
773
|
+
result.output = prependModelFallbackSummary(result.output, skippedModels, result.model ?? usedModel);
|
|
744
774
|
if (warning) {
|
|
745
775
|
result.output = `[WARNING: ${warning}]\n\n${result.output}`;
|
|
746
776
|
}
|
|
747
777
|
return result;
|
|
748
778
|
}
|
|
749
|
-
async function executeChain(agents, chain, defaultCwd, signal, onProgress, parentProvider, registry, sessionBaseDir, defaultAgent, defaultModel, parentModel) {
|
|
779
|
+
async function executeChain(agents, chain, defaultCwd, signal, onProgress, parentProvider, registry, sessionBaseDir, defaultAgent, defaultModel, parentModel, getAgentModelsForAgentFn) {
|
|
750
780
|
const results = [];
|
|
751
781
|
let previousOutput = "";
|
|
752
782
|
for (let i = 0; i < chain.length; i++) {
|
|
@@ -781,7 +811,9 @@ async function executeChain(agents, chain, defaultCwd, signal, onProgress, paren
|
|
|
781
811
|
}
|
|
782
812
|
// Each chain step gets its own session subdirectory
|
|
783
813
|
const stepSessionDir = sessionBaseDir ? join(sessionBaseDir, `step-${i + 1}`) : undefined;
|
|
784
|
-
const
|
|
814
|
+
const stepAgentName = step.agent || defaultAgent || DEFAULT_AGENT;
|
|
815
|
+
const stepMach6Models = getAgentModelsForAgentFn?.(stepAgentName);
|
|
816
|
+
const result = await executeSingle(agents, step.agent || defaultAgent, task, cwdResult.cwd, signal, onProgress, step.model || defaultModel, parentProvider, registry, stepSessionDir, parentModel, stepMach6Models);
|
|
785
817
|
results.push(result);
|
|
786
818
|
if (result.exitCode !== 0) {
|
|
787
819
|
break; // stop chain on error
|
|
@@ -918,7 +950,7 @@ function formatSubagentResult(result, options, theme, showImages) {
|
|
|
918
950
|
}
|
|
919
951
|
return text;
|
|
920
952
|
}
|
|
921
|
-
function formatSingleResult(result) {
|
|
953
|
+
export function formatSingleResult(result) {
|
|
922
954
|
let text = `## Agent: ${result.agent}${result.model ? ` (model: ${result.model})` : ""}\n`;
|
|
923
955
|
if (result.exitCode !== 0) {
|
|
924
956
|
text += `**Error** (exit ${result.exitCode}): ${result.errorMessage || "Unknown error"}\n`;
|
|
@@ -926,10 +958,14 @@ function formatSingleResult(result) {
|
|
|
926
958
|
text += `\nStderr:\n${result.stderr}\n`;
|
|
927
959
|
}
|
|
928
960
|
}
|
|
961
|
+
else if (result.errorMessage) {
|
|
962
|
+
// Clean exit but an error was surfaced (e.g. truncation at the token limit).
|
|
963
|
+
text += `**Error**: ${result.errorMessage}\n`;
|
|
964
|
+
}
|
|
929
965
|
if (result.output) {
|
|
930
966
|
text += `\n${result.output}`;
|
|
931
967
|
}
|
|
932
|
-
else if (result.exitCode === 0) {
|
|
968
|
+
else if (result.exitCode === 0 && !result.errorMessage) {
|
|
933
969
|
text += "\n(No output)";
|
|
934
970
|
}
|
|
935
971
|
if (result.sessionFile) {
|
|
@@ -943,6 +979,7 @@ export function createSubagentToolDefinition(cwd, options) {
|
|
|
943
979
|
const getParentProvider = options?.parentProvider ?? (() => undefined);
|
|
944
980
|
const getParentModel = options?.parentModel ?? (() => undefined);
|
|
945
981
|
const modelRegistry = options?.modelRegistry;
|
|
982
|
+
const getAgentModelsForAgent = options?.getAgentModelsForAgent;
|
|
946
983
|
// Discover agents at definition time to build the prompt guidelines.
|
|
947
984
|
// This is cheap (reads .md files) and the same call happens on every execute().
|
|
948
985
|
const knownAgents = discoverAgentTypes(cwd);
|
|
@@ -1095,7 +1132,8 @@ export function createSubagentToolDefinition(cwd, options) {
|
|
|
1095
1132
|
// Each background agent gets its own session subdirectory
|
|
1096
1133
|
const sessionId = generateAgentId();
|
|
1097
1134
|
const sessionDir = join(subagentSessionsBase, sessionId);
|
|
1098
|
-
|
|
1135
|
+
const agentModels = getAgentModelsForAgent?.(agentName || DEFAULT_AGENT);
|
|
1136
|
+
return launchBackgroundLifecycle(agentName, taskLabel, (signal) => executeSingle(agents, agentName === DEFAULT_AGENT ? undefined : agentName, task, resolvedCwd, signal, undefined, modelOverride, getParentProvider(), modelRegistry, sessionDir, getParentModel(), agentModels));
|
|
1099
1137
|
};
|
|
1100
1138
|
if (params.task) {
|
|
1101
1139
|
// Single background task
|
|
@@ -1161,7 +1199,7 @@ export function createSubagentToolDefinition(cwd, options) {
|
|
|
1161
1199
|
const chainSteps = params.chain;
|
|
1162
1200
|
const chainSessionDir = join(subagentSessionsBase, `chain-${generateAgentId()}`);
|
|
1163
1201
|
const agentId = launchBackgroundLifecycle(agentName, taskSummary, async (signal) => {
|
|
1164
|
-
const results = await executeChain(agents, chainSteps, cwd, signal, undefined, getParentProvider(), modelRegistry, chainSessionDir, params.agent, params.model, getParentModel());
|
|
1202
|
+
const results = await executeChain(agents, chainSteps, cwd, signal, undefined, getParentProvider(), modelRegistry, chainSessionDir, params.agent, params.model, getParentModel(), getAgentModelsForAgent);
|
|
1165
1203
|
const resultText = results
|
|
1166
1204
|
.map((r, i) => `### Step ${i + 1}\n${formatSingleResult(r)}`)
|
|
1167
1205
|
.join("\n\n---\n\n");
|