@dreb/coding-agent 2.59.2 → 2.60.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.
@@ -36,7 +36,7 @@ import { PerformanceTracker } from "./performance-tracker.js";
36
36
  import { expandPromptTemplate } from "./prompt-templates.js";
37
37
  import { scrubSecrets } from "./secret-scrubber.js";
38
38
  import { isSensitivePath } from "./sensitive-paths.js";
39
- import { CURRENT_SESSION_VERSION, getLatestCompactionEntry } from "./session-manager.js";
39
+ import { CURRENT_SESSION_VERSION, getLatestCompactionEntry, SessionManager, } from "./session-manager.js";
40
40
  import { DEFAULT_BG_PARENT_TURN_LIMIT, DEFAULT_MAX_CONCURRENT_SUBAGENTS, } from "./settings-manager.js";
41
41
  import { createSyntheticSourceInfo } from "./source-info.js";
42
42
  import { buildSystemPrompt } from "./system-prompt.js";
@@ -1233,7 +1233,15 @@ export class AgentSession {
1233
1233
  }
1234
1234
  const loaderSystemPrompt = this._resourceLoader.getSystemPrompt();
1235
1235
  const loaderAppendSystemPrompt = this._resourceLoader.getAppendSystemPrompt();
1236
- const appendSystemPrompt = loaderAppendSystemPrompt.length > 0 ? loaderAppendSystemPrompt.join("\n\n") : undefined;
1236
+ const modelPromptSettings = this.model
1237
+ ? this.settingsManager.getModelPromptSettings(this.model.provider, this.model.id)
1238
+ : undefined;
1239
+ const customPrompt = loaderSystemPrompt ?? modelPromptSettings?.systemPrompt;
1240
+ const appendPromptParts = [...loaderAppendSystemPrompt];
1241
+ if (modelPromptSettings?.appendSystemPrompt) {
1242
+ appendPromptParts.push(modelPromptSettings.appendSystemPrompt);
1243
+ }
1244
+ const appendSystemPrompt = appendPromptParts.length > 0 ? appendPromptParts.join("\n\n") : undefined;
1237
1245
  const loadedSkills = this._getFilteredSkills();
1238
1246
  const loadedContextFiles = this._resourceLoader.getAgentsFiles().agentsFiles;
1239
1247
  const memoryIndexes = this._resourceLoader.getMemoryIndexes();
@@ -1242,7 +1250,7 @@ export class AgentSession {
1242
1250
  skills: loadedSkills,
1243
1251
  contextFiles: loadedContextFiles,
1244
1252
  memoryIndexes,
1245
- customPrompt: loaderSystemPrompt,
1253
+ customPrompt,
1246
1254
  appendSystemPrompt,
1247
1255
  selectedTools: validToolNames,
1248
1256
  toolSnippets,
@@ -1723,6 +1731,7 @@ export class AgentSession {
1723
1731
  if (!apiKey) {
1724
1732
  throw new Error(`No API key for ${model.provider}/${model.id}`);
1725
1733
  }
1734
+ this._validateModelPromptSettings(model);
1726
1735
  const previousModel = this.model;
1727
1736
  const thinkingLevel = this._getThinkingLevelForModelSwitch();
1728
1737
  this.agent.setModel(this._applyContextTier(model));
@@ -1744,6 +1753,10 @@ export class AgentSession {
1744
1753
  _refreshThinkingDisplay(model) {
1745
1754
  this.agent.thinkingDisplay = resolveThinkingDisplay(model, this.settingsManager.getModelThinkingDisplay(model.id));
1746
1755
  }
1756
+ /** Reject malformed target-model prompt settings before a model switch mutates session state. */
1757
+ _validateModelPromptSettings(model) {
1758
+ this.settingsManager.getModelPromptSettings(model.provider, model.id);
1759
+ }
1747
1760
  /**
1748
1761
  * Cycle to next/previous model.
1749
1762
  * Uses scoped models (from --models flag) if available, otherwise all available models.
@@ -1786,6 +1799,7 @@ export class AgentSession {
1786
1799
  const len = scopedModels.length;
1787
1800
  const nextIndex = direction === "forward" ? (currentIndex + 1) % len : (currentIndex - 1 + len) % len;
1788
1801
  const next = scopedModels[nextIndex];
1802
+ this._validateModelPromptSettings(next.model);
1789
1803
  const thinkingLevel = this._getThinkingLevelForModelSwitch(next.thinkingLevel);
1790
1804
  // Apply model
1791
1805
  this.agent.setModel(this._applyContextTier(next.model));
@@ -1817,6 +1831,7 @@ export class AgentSession {
1817
1831
  if (!apiKey) {
1818
1832
  throw new Error(`No API key for ${nextModel.provider}/${nextModel.id}`);
1819
1833
  }
1834
+ this._validateModelPromptSettings(nextModel);
1820
1835
  const thinkingLevel = this._getThinkingLevelForModelSwitch();
1821
1836
  this.agent.setModel(this._applyContextTier(nextModel));
1822
1837
  this._refreshThinkingDisplay(nextModel);
@@ -2959,6 +2974,17 @@ export class AgentSession {
2959
2974
  return false;
2960
2975
  }
2961
2976
  }
2977
+ // Resolve and validate the target model before disconnecting or mutating the active session.
2978
+ // Prompt validation can throw for malformed settings, so it belongs in this preflight phase.
2979
+ const targetModel = SessionManager.open(sessionPath).buildSessionContext().model;
2980
+ let restoredModel;
2981
+ if (targetModel) {
2982
+ const availableModels = await this._modelRegistry.getAvailable();
2983
+ restoredModel = availableModels.find((m) => m.provider === targetModel.provider && m.id === targetModel.modelId);
2984
+ if (restoredModel) {
2985
+ this._validateModelPromptSettings(restoredModel);
2986
+ }
2987
+ }
2962
2988
  this._disconnectFromAgent();
2963
2989
  await this.abort();
2964
2990
  this._steeringMessages = [];
@@ -2980,16 +3006,12 @@ export class AgentSession {
2980
3006
  }
2981
3007
  // Emit session event to custom tools
2982
3008
  this.agent.replaceMessages(sessionContext.messages);
2983
- // Restore model if saved
2984
- if (sessionContext.model) {
3009
+ // Restore the preflighted model if the target session saved one that is still available.
3010
+ if (restoredModel) {
2985
3011
  const previousModel = this.model;
2986
- const availableModels = await this._modelRegistry.getAvailable();
2987
- const match = availableModels.find((m) => m.provider === sessionContext.model.provider && m.id === sessionContext.model.modelId);
2988
- if (match) {
2989
- this.agent.setModel(this._applyContextTier(match));
2990
- this._refreshThinkingDisplay(match);
2991
- await this._emitModelSelect(match, previousModel, "restore");
2992
- }
3012
+ this.agent.setModel(this._applyContextTier(restoredModel));
3013
+ this._refreshThinkingDisplay(restoredModel);
3014
+ await this._emitModelSelect(restoredModel, previousModel, "restore");
2993
3015
  }
2994
3016
  const hasThinkingEntry = this.sessionManager.getBranch().some((entry) => entry.type === "thinking_level_change");
2995
3017
  const defaultThinkingLevel = this.settingsManager.getDefaultThinkingLevel() ?? DEFAULT_THINKING_LEVEL;
@@ -3009,6 +3031,7 @@ export class AgentSession {
3009
3031
  this._gitRepoState = getGitRepoState(this._cwd) ?? undefined;
3010
3032
  this._resourceLoader.refreshDreamLastRun();
3011
3033
  this._baseSystemPrompt = this._rebuildSystemPrompt(this.getActiveToolNames());
3034
+ this.agent.setSystemPrompt(this._baseSystemPrompt);
3012
3035
  this._reconnectToAgent();
3013
3036
  return true;
3014
3037
  }