@bastani/atomic 0.8.30 → 0.8.31-alpha.2

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.
Files changed (205) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +12 -10
  3. package/dist/builtin/cursor/CHANGELOG.md +4 -0
  4. package/dist/builtin/cursor/package.json +2 -2
  5. package/dist/builtin/intercom/CHANGELOG.md +4 -0
  6. package/dist/builtin/intercom/package.json +2 -2
  7. package/dist/builtin/mcp/CHANGELOG.md +4 -0
  8. package/dist/builtin/mcp/package.json +3 -3
  9. package/dist/builtin/subagents/CHANGELOG.md +13 -0
  10. package/dist/builtin/subagents/agents/codebase-online-researcher.md +8 -8
  11. package/dist/builtin/subagents/agents/debugger.md +6 -6
  12. package/dist/builtin/subagents/package.json +4 -4
  13. package/dist/builtin/subagents/skills/effective-liteparse/SKILL.md +118 -0
  14. package/dist/builtin/subagents/skills/effective-liteparse/scripts/search.py +128 -0
  15. package/dist/builtin/subagents/skills/playwright-cli/SKILL.md +404 -0
  16. package/dist/builtin/subagents/skills/playwright-cli/references/element-attributes.md +23 -0
  17. package/dist/builtin/subagents/skills/playwright-cli/references/playwright-tests.md +39 -0
  18. package/dist/builtin/subagents/skills/playwright-cli/references/request-mocking.md +87 -0
  19. package/dist/builtin/subagents/skills/playwright-cli/references/running-code.md +241 -0
  20. package/dist/builtin/subagents/skills/playwright-cli/references/session-management.md +225 -0
  21. package/dist/builtin/subagents/skills/playwright-cli/references/spec-driven-testing.md +305 -0
  22. package/dist/builtin/subagents/skills/playwright-cli/references/storage-state.md +275 -0
  23. package/dist/builtin/subagents/skills/playwright-cli/references/test-generation.md +134 -0
  24. package/dist/builtin/subagents/skills/playwright-cli/references/tracing.md +139 -0
  25. package/dist/builtin/subagents/skills/playwright-cli/references/video-recording.md +143 -0
  26. package/dist/builtin/web-access/CHANGELOG.md +4 -0
  27. package/dist/builtin/web-access/package.json +2 -2
  28. package/dist/builtin/workflows/CHANGELOG.md +16 -0
  29. package/dist/builtin/workflows/README.md +4 -4
  30. package/dist/builtin/workflows/builtin/deep-research-codebase.ts +1 -1
  31. package/dist/builtin/workflows/builtin/goal.ts +2 -2
  32. package/dist/builtin/workflows/builtin/open-claude-design.ts +60 -57
  33. package/dist/builtin/workflows/builtin/ralph.ts +117 -14
  34. package/dist/builtin/workflows/builtin/shared-prompts.ts +1 -1
  35. package/dist/builtin/workflows/package.json +2 -2
  36. package/dist/builtin/workflows/skills/research-codebase/SKILL.md +1 -1
  37. package/dist/builtin/workflows/src/extension/workflow-schema.ts +3 -1
  38. package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +5 -0
  39. package/dist/builtin/workflows/src/runs/shared/model-fallback.ts +95 -8
  40. package/dist/builtin/workflows/src/shared/authoring-contract.d.ts +11 -0
  41. package/dist/cli/args.d.ts +1 -0
  42. package/dist/cli/args.d.ts.map +1 -1
  43. package/dist/cli/args.js +21 -1
  44. package/dist/cli/args.js.map +1 -1
  45. package/dist/cli/list-models.d.ts.map +1 -1
  46. package/dist/cli/list-models.js +2 -1
  47. package/dist/cli/list-models.js.map +1 -1
  48. package/dist/core/agent-session-services.d.ts +2 -0
  49. package/dist/core/agent-session-services.d.ts.map +1 -1
  50. package/dist/core/agent-session-services.js +2 -0
  51. package/dist/core/agent-session-services.js.map +1 -1
  52. package/dist/core/agent-session.d.ts +18 -0
  53. package/dist/core/agent-session.d.ts.map +1 -1
  54. package/dist/core/agent-session.js +182 -19
  55. package/dist/core/agent-session.js.map +1 -1
  56. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  57. package/dist/core/compaction/branch-summarization.js +20 -5
  58. package/dist/core/compaction/branch-summarization.js.map +1 -1
  59. package/dist/core/compaction/context-compaction.d.ts.map +1 -1
  60. package/dist/core/compaction/context-compaction.js +14 -3
  61. package/dist/core/compaction/context-compaction.js.map +1 -1
  62. package/dist/core/context-window.d.ts +39 -0
  63. package/dist/core/context-window.d.ts.map +1 -0
  64. package/dist/core/context-window.js +99 -0
  65. package/dist/core/context-window.js.map +1 -0
  66. package/dist/core/copilot-errors.d.ts +9 -0
  67. package/dist/core/copilot-errors.d.ts.map +1 -0
  68. package/dist/core/copilot-errors.js +32 -0
  69. package/dist/core/copilot-errors.js.map +1 -0
  70. package/dist/core/copilot-model-catalog.d.ts +135 -0
  71. package/dist/core/copilot-model-catalog.d.ts.map +1 -0
  72. package/dist/core/copilot-model-catalog.js +257 -0
  73. package/dist/core/copilot-model-catalog.js.map +1 -0
  74. package/dist/core/export-html/template.js +10 -1
  75. package/dist/core/extensions/types.d.ts +3 -1
  76. package/dist/core/extensions/types.d.ts.map +1 -1
  77. package/dist/core/extensions/types.js.map +1 -1
  78. package/dist/core/model-registry.d.ts +10 -0
  79. package/dist/core/model-registry.d.ts.map +1 -1
  80. package/dist/core/model-registry.js +107 -4
  81. package/dist/core/model-registry.js.map +1 -1
  82. package/dist/core/model-resolver.d.ts.map +1 -1
  83. package/dist/core/model-resolver.js +4 -0
  84. package/dist/core/model-resolver.js.map +1 -1
  85. package/dist/core/project-trust.d.ts.map +1 -1
  86. package/dist/core/project-trust.js +2 -1
  87. package/dist/core/project-trust.js.map +1 -1
  88. package/dist/core/provider-attribution.d.ts.map +1 -1
  89. package/dist/core/provider-attribution.js +17 -7
  90. package/dist/core/provider-attribution.js.map +1 -1
  91. package/dist/core/sdk.d.ts +8 -0
  92. package/dist/core/sdk.d.ts.map +1 -1
  93. package/dist/core/sdk.js +58 -0
  94. package/dist/core/sdk.js.map +1 -1
  95. package/dist/core/session-manager.d.ts +8 -1
  96. package/dist/core/session-manager.d.ts.map +1 -1
  97. package/dist/core/session-manager.js +19 -3
  98. package/dist/core/session-manager.js.map +1 -1
  99. package/dist/core/settings-manager.d.ts +15 -0
  100. package/dist/core/settings-manager.d.ts.map +1 -1
  101. package/dist/core/settings-manager.js +124 -1
  102. package/dist/core/settings-manager.js.map +1 -1
  103. package/dist/core/system-prompt.d.ts.map +1 -1
  104. package/dist/core/system-prompt.js +1 -0
  105. package/dist/core/system-prompt.js.map +1 -1
  106. package/dist/core/tools/edit-diff.d.ts +1 -2
  107. package/dist/core/tools/edit-diff.d.ts.map +1 -1
  108. package/dist/core/tools/edit-diff.js +1 -2
  109. package/dist/core/tools/edit-diff.js.map +1 -1
  110. package/dist/index.d.ts +3 -1
  111. package/dist/index.d.ts.map +1 -1
  112. package/dist/index.js +2 -0
  113. package/dist/index.js.map +1 -1
  114. package/dist/main.d.ts.map +1 -1
  115. package/dist/main.js +24 -1
  116. package/dist/main.js.map +1 -1
  117. package/dist/modes/index.d.ts +1 -1
  118. package/dist/modes/index.d.ts.map +1 -1
  119. package/dist/modes/index.js.map +1 -1
  120. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  121. package/dist/modes/interactive/components/config-selector.js +5 -7
  122. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  123. package/dist/modes/interactive/components/context-window-selector.d.ts +53 -0
  124. package/dist/modes/interactive/components/context-window-selector.d.ts.map +1 -0
  125. package/dist/modes/interactive/components/context-window-selector.js +136 -0
  126. package/dist/modes/interactive/components/context-window-selector.js.map +1 -0
  127. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  128. package/dist/modes/interactive/components/model-selector.js +2 -1
  129. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  130. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  131. package/dist/modes/interactive/components/scoped-models-selector.js +4 -1
  132. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  133. package/dist/modes/interactive/components/settings-selector.d.ts +2 -0
  134. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  135. package/dist/modes/interactive/components/settings-selector.js +165 -15
  136. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  137. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  138. package/dist/modes/interactive/components/tree-selector.js +51 -4
  139. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  140. package/dist/modes/interactive/interactive-mode.d.ts +6 -1
  141. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  142. package/dist/modes/interactive/interactive-mode.js +115 -55
  143. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  144. package/dist/modes/interactive/model-search.d.ts +7 -0
  145. package/dist/modes/interactive/model-search.d.ts.map +1 -0
  146. package/dist/modes/interactive/model-search.js +6 -0
  147. package/dist/modes/interactive/model-search.js.map +1 -0
  148. package/dist/modes/interactive/theme/theme-controller.d.ts +30 -0
  149. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -0
  150. package/dist/modes/interactive/theme/theme-controller.js +108 -0
  151. package/dist/modes/interactive/theme/theme-controller.js.map +1 -0
  152. package/dist/modes/interactive/theme/theme-schema.json +2 -1
  153. package/dist/modes/interactive/theme/theme.d.ts +5 -0
  154. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  155. package/dist/modes/interactive/theme/theme.js +70 -29
  156. package/dist/modes/interactive/theme/theme.js.map +1 -1
  157. package/dist/modes/rpc/rpc-client.d.ts +14 -2
  158. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  159. package/dist/modes/rpc/rpc-client.js +23 -3
  160. package/dist/modes/rpc/rpc-client.js.map +1 -1
  161. package/dist/modes/rpc/rpc-mode.d.ts +1 -1
  162. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  163. package/dist/modes/rpc/rpc-mode.js +31 -2
  164. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  165. package/dist/modes/rpc/rpc-types.d.ts +23 -0
  166. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  167. package/dist/modes/rpc/rpc-types.js.map +1 -1
  168. package/dist/package-manager-cli.d.ts.map +1 -1
  169. package/dist/package-manager-cli.js +39 -9
  170. package/dist/package-manager-cli.js.map +1 -1
  171. package/docs/custom-provider.md +4 -1
  172. package/docs/extensions.md +21 -0
  173. package/docs/json.md +3 -1
  174. package/docs/models.md +78 -2
  175. package/docs/packages.md +13 -9
  176. package/docs/providers.md +3 -0
  177. package/docs/quickstart.md +14 -0
  178. package/docs/rpc.md +80 -1
  179. package/docs/sdk.md +35 -11
  180. package/docs/session-format.md +15 -1
  181. package/docs/sessions.md +1 -1
  182. package/docs/settings.md +12 -2
  183. package/docs/themes.md +3 -1
  184. package/docs/tui.md +1 -1
  185. package/docs/usage.md +12 -9
  186. package/docs/workflows.md +34 -10
  187. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  188. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  189. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  190. package/examples/extensions/gondolin/package-lock.json +2 -2
  191. package/examples/extensions/gondolin/package.json +1 -1
  192. package/examples/extensions/preset.ts +10 -4
  193. package/examples/extensions/provider-payload.ts +5 -5
  194. package/examples/extensions/sandbox/index.ts +2 -2
  195. package/examples/extensions/sandbox/package-lock.json +3 -3
  196. package/examples/extensions/sandbox/package.json +2 -2
  197. package/examples/extensions/subagent/agents.ts +2 -2
  198. package/examples/extensions/subagent/index.ts +4 -2
  199. package/examples/extensions/with-deps/package-lock.json +2 -2
  200. package/examples/extensions/with-deps/package.json +1 -1
  201. package/package.json +5 -5
  202. package/dist/builtin/subagents/skills/browser/EXAMPLES.md +0 -151
  203. package/dist/builtin/subagents/skills/browser/LICENSE.txt +0 -21
  204. package/dist/builtin/subagents/skills/browser/REFERENCE.md +0 -451
  205. package/dist/builtin/subagents/skills/browser/SKILL.md +0 -170
@@ -23,6 +23,8 @@ import { ATOMIC_GUIDE_COMMAND_NAME, ATOMIC_GUIDE_HELP_CHOICES, atomicGuideModeFo
23
23
  import { formatNoApiKeyFoundMessage, formatNoModelSelectedMessage, formatUnresolvedModelMessage, } from "./auth-guidance.js";
24
24
  import { executeBashWithOperations } from "./bash-executor.js";
25
25
  import { calculateContextTokens, collectEntriesForBranchSummary, contextCompact as runContextCompact, estimateContextTokens, generateBranchSummary, prepareContextCompaction, shouldCompact, validateContextDeletionRequest, } from "./compaction/index.js";
26
+ import { getModelDefaultContextWindow, getSupportedContextWindows, selectContextWindow } from "./context-window.js";
27
+ import { formatCopilotProviderError, parseCopilotPromptLimitError } from "./copilot-errors.js";
26
28
  import { DEFAULT_THINKING_LEVEL } from "./defaults.js";
27
29
  import { exportSessionToHtml } from "./export-html/index.js";
28
30
  import { createToolHtmlRenderer } from "./export-html/tool-renderer.js";
@@ -82,6 +84,7 @@ export function parseSkillBlock(text) {
82
84
  userMessage: afterClosing ? afterClosing.slice(2).trim() || undefined : undefined,
83
85
  };
84
86
  }
87
+ const COPILOT_CONTEXT_WINDOW_SELECTION_OPTIONS = { allowCopilotLongContextFallback: true };
85
88
  function drainAgentMessageQueue(queue) {
86
89
  if (!queue)
87
90
  return [];
@@ -370,6 +373,7 @@ export class AgentSession {
370
373
  }
371
374
  }
372
375
  this._applyInterruptAbortMessage(event);
376
+ this._applyProviderErrorGuidance(event);
373
377
  // Emit to extensions first
374
378
  await this._emitExtensionEvent(event);
375
379
  // Notify all listeners
@@ -442,6 +446,16 @@ export class AgentSession {
442
446
  }
443
447
  }
444
448
  }
449
+ _applyProviderErrorGuidance(event) {
450
+ if (event.type !== "message_start" && event.type !== "message_update" && event.type !== "message_end")
451
+ return;
452
+ if (event.message.role !== "assistant")
453
+ return;
454
+ const assistantMessage = event.message;
455
+ if (assistantMessage.stopReason !== "error" || !assistantMessage.errorMessage)
456
+ return;
457
+ assistantMessage.errorMessage = formatCopilotProviderError(assistantMessage.provider, assistantMessage.errorMessage);
458
+ }
445
459
  /** Resolve the pending retry promise */
446
460
  _resolveRetry() {
447
461
  if (this._retryResolve) {
@@ -1366,14 +1380,16 @@ export class AgentSession {
1366
1380
  }
1367
1381
  const previousModel = this.model;
1368
1382
  const thinkingLevel = this._getThinkingLevelForModelSwitch();
1369
- this.agent.state.model = model;
1370
- this.sessionManager.appendModelChange(model.provider, model.id);
1371
- this.settingsManager.setDefaultModelAndProvider(model.provider, model.id);
1383
+ const nextModel = this._withContextWindowForModelSwitch(model);
1384
+ this.agent.state.model = nextModel;
1385
+ this.sessionManager.appendModelChange(nextModel.provider, nextModel.id);
1386
+ this._appendContextWindowChangeIfChanged(previousModel, nextModel);
1387
+ this.settingsManager.setDefaultModelAndProvider(nextModel.provider, nextModel.id);
1372
1388
  // Re-clamp thinking level for new model's capabilities
1373
1389
  this.setThinkingLevel(thinkingLevel);
1374
1390
  this._refreshBaseSystemPromptFromActiveTools();
1375
- this._emitModelChanged(model, previousModel, "set");
1376
- await this._emitModelSelect(model, previousModel, "set");
1391
+ this._emitModelChanged(nextModel, previousModel, "set");
1392
+ await this._emitModelSelect(nextModel, previousModel, "set");
1377
1393
  }
1378
1394
  /**
1379
1395
  * Cycle to next/previous model.
@@ -1399,19 +1415,21 @@ export class AgentSession {
1399
1415
  const nextIndex = direction === "forward" ? (currentIndex + 1) % len : (currentIndex - 1 + len) % len;
1400
1416
  const next = scopedModels[nextIndex];
1401
1417
  const thinkingLevel = this._getThinkingLevelForModelSwitch(next.thinkingLevel);
1418
+ const nextModel = this._withContextWindowForModelSwitch(next.model);
1402
1419
  // Apply model
1403
- this.agent.state.model = next.model;
1404
- this.sessionManager.appendModelChange(next.model.provider, next.model.id);
1405
- this.settingsManager.setDefaultModelAndProvider(next.model.provider, next.model.id);
1420
+ this.agent.state.model = nextModel;
1421
+ this.sessionManager.appendModelChange(nextModel.provider, nextModel.id);
1422
+ this._appendContextWindowChangeIfChanged(currentModel, nextModel);
1423
+ this.settingsManager.setDefaultModelAndProvider(nextModel.provider, nextModel.id);
1406
1424
  // Apply thinking level.
1407
1425
  // - Explicit scoped model thinking level overrides current session level
1408
1426
  // - Undefined scoped model thinking level inherits the current session preference
1409
1427
  // setThinkingLevel clamps to model capabilities.
1410
1428
  this.setThinkingLevel(thinkingLevel);
1411
1429
  this._refreshBaseSystemPromptFromActiveTools();
1412
- this._emitModelChanged(next.model, currentModel, "cycle");
1413
- await this._emitModelSelect(next.model, currentModel, "cycle");
1414
- return { model: next.model, thinkingLevel: this.thinkingLevel, isScoped: true };
1430
+ this._emitModelChanged(nextModel, currentModel, "cycle");
1431
+ await this._emitModelSelect(nextModel, currentModel, "cycle");
1432
+ return { model: nextModel, thinkingLevel: this.thinkingLevel, isScoped: true };
1415
1433
  }
1416
1434
  async _cycleAvailableModel(direction) {
1417
1435
  const availableModels = await this._modelRegistry.getAvailable();
@@ -1423,17 +1441,18 @@ export class AgentSession {
1423
1441
  currentIndex = 0;
1424
1442
  const len = availableModels.length;
1425
1443
  const nextIndex = direction === "forward" ? (currentIndex + 1) % len : (currentIndex - 1 + len) % len;
1426
- const nextModel = availableModels[nextIndex];
1444
+ const selectedModel = this._withContextWindowForModelSwitch(availableModels[nextIndex]);
1427
1445
  const thinkingLevel = this._getThinkingLevelForModelSwitch();
1428
- this.agent.state.model = nextModel;
1429
- this.sessionManager.appendModelChange(nextModel.provider, nextModel.id);
1430
- this.settingsManager.setDefaultModelAndProvider(nextModel.provider, nextModel.id);
1446
+ this.agent.state.model = selectedModel;
1447
+ this.sessionManager.appendModelChange(selectedModel.provider, selectedModel.id);
1448
+ this._appendContextWindowChangeIfChanged(currentModel, selectedModel);
1449
+ this.settingsManager.setDefaultModelAndProvider(selectedModel.provider, selectedModel.id);
1431
1450
  // Re-clamp thinking level for new model's capabilities
1432
1451
  this.setThinkingLevel(thinkingLevel);
1433
1452
  this._refreshBaseSystemPromptFromActiveTools();
1434
- this._emitModelChanged(nextModel, currentModel, "cycle");
1435
- await this._emitModelSelect(nextModel, currentModel, "cycle");
1436
- return { model: nextModel, thinkingLevel: this.thinkingLevel, isScoped: false };
1453
+ this._emitModelChanged(selectedModel, currentModel, "cycle");
1454
+ await this._emitModelSelect(selectedModel, currentModel, "cycle");
1455
+ return { model: selectedModel, thinkingLevel: this.thinkingLevel, isScoped: false };
1437
1456
  }
1438
1457
  // =========================================================================
1439
1458
  // Thinking Level Management
@@ -1506,6 +1525,133 @@ export class AgentSession {
1506
1525
  return this.model ? clampThinkingLevel(this.model, level) : "off";
1507
1526
  }
1508
1527
  // =========================================================================
1528
+ // Context Window Management
1529
+ // =========================================================================
1530
+ getAvailableContextWindows() {
1531
+ return this.model ? getSupportedContextWindows(this.model) : [];
1532
+ }
1533
+ supportsContextWindowSelection() {
1534
+ return this.getAvailableContextWindows().length > 1;
1535
+ }
1536
+ setContextWindow(contextWindow, options = {}) {
1537
+ if (!this.model) {
1538
+ throw new Error("No model selected");
1539
+ }
1540
+ const selected = selectContextWindow(this.model, contextWindow, COPILOT_CONTEXT_WINDOW_SELECTION_OPTIONS);
1541
+ if ("error" in selected) {
1542
+ throw new Error(selected.error);
1543
+ }
1544
+ const previousContextWindow = this.model.contextWindow;
1545
+ const isChanging = previousContextWindow !== selected.contextWindow;
1546
+ this.agent.state.model = selected.model;
1547
+ if (isChanging) {
1548
+ this.sessionManager.appendContextWindowChange(selected.contextWindow);
1549
+ this._emit({ type: "context_window_changed", contextWindow: selected.contextWindow });
1550
+ }
1551
+ if (options.persistDefault === true) {
1552
+ this.settingsManager.setDefaultContextWindowForModel(selected.model.provider, selected.model.id, selected.contextWindow);
1553
+ }
1554
+ }
1555
+ _withContextWindowForModelSwitch(model) {
1556
+ // A source model's scalar contextWindow can be its natural default (for example a 1m-default
1557
+ // model). Do not treat that alone as an opt-in to larger windows on a 400k-default target.
1558
+ const settingsDefaultContextWindow = this._getSettingsContextWindowRequestForModel(model)?.contextWindow;
1559
+ const candidates = [];
1560
+ const targetDefaultContextWindow = getModelDefaultContextWindow(model);
1561
+ if (model.contextWindow !== targetDefaultContextWindow) {
1562
+ // Preserve an explicit context-window selection already applied to the target model
1563
+ // (for example a caller passing selectContextWindow(target, 1m).model).
1564
+ candidates.push(model.contextWindow);
1565
+ }
1566
+ const currentModel = this.model;
1567
+ if (currentModel && this._shouldCarryCurrentContextWindowForModelSwitch(currentModel, settingsDefaultContextWindow)) {
1568
+ candidates.push(currentModel.contextWindow);
1569
+ }
1570
+ if (settingsDefaultContextWindow !== undefined) {
1571
+ candidates.push(settingsDefaultContextWindow);
1572
+ }
1573
+ candidates.push(targetDefaultContextWindow);
1574
+ for (const candidate of candidates) {
1575
+ const selected = selectContextWindow(model, candidate, COPILOT_CONTEXT_WINDOW_SELECTION_OPTIONS);
1576
+ if (!("error" in selected))
1577
+ return selected.model;
1578
+ }
1579
+ return model;
1580
+ }
1581
+ _shouldCarryCurrentContextWindowForModelSwitch(currentModel, settingsDefaultContextWindow) {
1582
+ if (currentModel.contextWindow !== getModelDefaultContextWindow(currentModel)) {
1583
+ return true;
1584
+ }
1585
+ if (this.sessionManager.getBranch().some((entry) => entry.type === "context_window_change")) {
1586
+ return true;
1587
+ }
1588
+ return (settingsDefaultContextWindow !== undefined &&
1589
+ currentModel.contextWindow === settingsDefaultContextWindow &&
1590
+ getSupportedContextWindows(currentModel).includes(settingsDefaultContextWindow));
1591
+ }
1592
+ _getSettingsContextWindowRequestForModel(model) {
1593
+ const modelContextWindow = this.settingsManager.getDefaultContextWindowForModel(model.provider, model.id);
1594
+ if (modelContextWindow !== undefined) {
1595
+ return { contextWindow: modelContextWindow, source: "model-settings" };
1596
+ }
1597
+ const globalContextWindow = this.settingsManager.getDefaultContextWindow();
1598
+ return globalContextWindow === undefined
1599
+ ? undefined
1600
+ : { contextWindow: globalContextWindow, source: "global-settings" };
1601
+ }
1602
+ _getContextWindowReplayForModel(model, requestedContextWindow, source) {
1603
+ if (requestedContextWindow !== undefined) {
1604
+ const selected = selectContextWindow(model, requestedContextWindow, COPILOT_CONTEXT_WINDOW_SELECTION_OPTIONS);
1605
+ if (!("error" in selected)) {
1606
+ return { model: selected.model, contextWindow: selected.contextWindow, wouldWarn: false };
1607
+ }
1608
+ return this._getDefaultContextWindowReplayForModel(model, source !== "global-settings");
1609
+ }
1610
+ return this._getDefaultContextWindowReplayForModel(model, false);
1611
+ }
1612
+ _getDefaultContextWindowReplayForModel(model, wouldWarn) {
1613
+ const defaultContextWindow = getModelDefaultContextWindow(model);
1614
+ const selected = selectContextWindow(model, defaultContextWindow, COPILOT_CONTEXT_WINDOW_SELECTION_OPTIONS);
1615
+ if (!("error" in selected)) {
1616
+ return { model: selected.model, contextWindow: selected.contextWindow, wouldWarn };
1617
+ }
1618
+ return {
1619
+ model: { ...model, contextWindow: defaultContextWindow, defaultContextWindow },
1620
+ contextWindow: defaultContextWindow,
1621
+ wouldWarn,
1622
+ };
1623
+ }
1624
+ _getResumeContextWindowReplayForModel(model) {
1625
+ const sessionContext = this.sessionManager.buildSessionContext();
1626
+ if (sessionContext.contextWindow !== undefined) {
1627
+ return this._getContextWindowReplayForModel(model, sessionContext.contextWindow, "session");
1628
+ }
1629
+ const settingsContextWindow = this._getSettingsContextWindowRequestForModel(model);
1630
+ return this._getContextWindowReplayForModel(model, settingsContextWindow?.contextWindow, settingsContextWindow?.source);
1631
+ }
1632
+ _applyContextWindowReplay(contextWindow) {
1633
+ if (!this.model)
1634
+ return;
1635
+ const previousContextWindow = this.model.contextWindow;
1636
+ const settingsContextWindow = this._getSettingsContextWindowRequestForModel(this.model);
1637
+ const requestedContextWindow = contextWindow ?? settingsContextWindow?.contextWindow;
1638
+ const source = contextWindow !== undefined ? "session" : settingsContextWindow?.source;
1639
+ const replay = this._getContextWindowReplayForModel(this.model, requestedContextWindow, source);
1640
+ this.agent.state.model = replay.model;
1641
+ if (previousContextWindow !== replay.contextWindow) {
1642
+ this._emit({ type: "context_window_changed", contextWindow: replay.contextWindow });
1643
+ }
1644
+ }
1645
+ _appendContextWindowChangeIfChanged(previousModel, nextModel) {
1646
+ const replay = this._getResumeContextWindowReplayForModel(nextModel);
1647
+ if (!replay.wouldWarn && nextModel.contextWindow === replay.contextWindow)
1648
+ return;
1649
+ this.sessionManager.appendContextWindowChange(nextModel.contextWindow);
1650
+ if (previousModel?.contextWindow !== nextModel.contextWindow) {
1651
+ this._emit({ type: "context_window_changed", contextWindow: nextModel.contextWindow });
1652
+ }
1653
+ }
1654
+ // =========================================================================
1509
1655
  // Queue Mode Management
1510
1656
  // =========================================================================
1511
1657
  /**
@@ -1812,6 +1958,12 @@ export class AgentSession {
1812
1958
  return;
1813
1959
  }
1814
1960
  // Case 1: Overflow - LLM returned context overflow error
1961
+ // When Copilot rejects a 1m client-budget prompt at a lower server cap (for example
1962
+ // because long-context/usage-based billing entitlement is missing), leave the friendly
1963
+ // error visible instead of auto-compacting down to a smaller server tier silently.
1964
+ if (sameModel && this._isCopilotServerCapBelowSelectedContextWindow(assistantMessage)) {
1965
+ return;
1966
+ }
1815
1967
  if (sameModel && isContextOverflow(assistantMessage, contextWindow)) {
1816
1968
  if (this._overflowRecoveryAttempted) {
1817
1969
  this._emit({
@@ -1861,6 +2013,12 @@ export class AgentSession {
1861
2013
  await this._runAutoCompaction("threshold", false);
1862
2014
  }
1863
2015
  }
2016
+ _isCopilotServerCapBelowSelectedContextWindow(assistantMessage) {
2017
+ if (!this.model || this.model.provider !== "github-copilot" || !assistantMessage.errorMessage)
2018
+ return false;
2019
+ const promptLimitError = parseCopilotPromptLimitError(assistantMessage.errorMessage);
2020
+ return promptLimitError !== undefined && this.model.contextWindow > promptLimitError.limitTokens;
2021
+ }
1864
2022
  /**
1865
2023
  * Internal: remove the trailing overflow error from retry context if it is still present.
1866
2024
  */
@@ -2053,7 +2211,11 @@ export class AgentSession {
2053
2211
  if (!refreshedModel || refreshedModel === currentModel) {
2054
2212
  return;
2055
2213
  }
2056
- this.agent.state.model = refreshedModel;
2214
+ const replay = this._getResumeContextWindowReplayForModel(refreshedModel);
2215
+ this.agent.state.model = replay.model;
2216
+ if (currentModel.contextWindow !== replay.contextWindow) {
2217
+ this._emit({ type: "context_window_changed", contextWindow: replay.contextWindow });
2218
+ }
2057
2219
  this._refreshBaseSystemPromptFromActiveTools();
2058
2220
  }
2059
2221
  _bindExtensionCore(runner) {
@@ -2686,6 +2848,7 @@ export class AgentSession {
2686
2848
  // Update agent state
2687
2849
  const sessionContext = this.sessionManager.buildSessionContext();
2688
2850
  this.agent.state.messages = sessionContext.messages;
2851
+ this._applyContextWindowReplay(sessionContext.contextWindow);
2689
2852
  // Emit session_tree event
2690
2853
  await this._extensionRunner.emit({
2691
2854
  type: "session_tree",