@bastani/atomic 0.8.30-alpha.3 → 0.8.31-alpha.1

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 (123) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/dist/builtin/cursor/CHANGELOG.md +7 -1
  3. package/dist/builtin/cursor/package.json +2 -2
  4. package/dist/builtin/intercom/CHANGELOG.md +6 -0
  5. package/dist/builtin/intercom/package.json +2 -2
  6. package/dist/builtin/mcp/CHANGELOG.md +6 -0
  7. package/dist/builtin/mcp/package.json +3 -3
  8. package/dist/builtin/subagents/CHANGELOG.md +6 -0
  9. package/dist/builtin/subagents/package.json +4 -4
  10. package/dist/builtin/web-access/CHANGELOG.md +6 -0
  11. package/dist/builtin/web-access/package.json +2 -2
  12. package/dist/builtin/workflows/CHANGELOG.md +12 -0
  13. package/dist/builtin/workflows/builtin/deep-research-codebase.ts +1 -1
  14. package/dist/builtin/workflows/builtin/goal.ts +2 -2
  15. package/dist/builtin/workflows/builtin/open-claude-design.ts +1 -1
  16. package/dist/builtin/workflows/builtin/ralph.ts +61 -11
  17. package/dist/builtin/workflows/package.json +2 -2
  18. package/dist/builtin/workflows/src/extension/workflow-schema.ts +3 -1
  19. package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +5 -0
  20. package/dist/builtin/workflows/src/runs/shared/model-fallback.ts +95 -8
  21. package/dist/builtin/workflows/src/shared/authoring-contract.d.ts +11 -0
  22. package/dist/cli/args.d.ts +1 -0
  23. package/dist/cli/args.d.ts.map +1 -1
  24. package/dist/cli/args.js +20 -0
  25. package/dist/cli/args.js.map +1 -1
  26. package/dist/cli/list-models.d.ts.map +1 -1
  27. package/dist/cli/list-models.js +2 -1
  28. package/dist/cli/list-models.js.map +1 -1
  29. package/dist/core/agent-session-services.d.ts +2 -0
  30. package/dist/core/agent-session-services.d.ts.map +1 -1
  31. package/dist/core/agent-session-services.js +2 -0
  32. package/dist/core/agent-session-services.js.map +1 -1
  33. package/dist/core/agent-session.d.ts +17 -0
  34. package/dist/core/agent-session.d.ts.map +1 -1
  35. package/dist/core/agent-session.js +161 -18
  36. package/dist/core/agent-session.js.map +1 -1
  37. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  38. package/dist/core/compaction/branch-summarization.js +20 -5
  39. package/dist/core/compaction/branch-summarization.js.map +1 -1
  40. package/dist/core/compaction/context-compaction.d.ts.map +1 -1
  41. package/dist/core/compaction/context-compaction.js +14 -3
  42. package/dist/core/compaction/context-compaction.js.map +1 -1
  43. package/dist/core/context-window.d.ts +29 -0
  44. package/dist/core/context-window.d.ts.map +1 -0
  45. package/dist/core/context-window.js +86 -0
  46. package/dist/core/context-window.js.map +1 -0
  47. package/dist/core/copilot-errors.d.ts +9 -0
  48. package/dist/core/copilot-errors.d.ts.map +1 -0
  49. package/dist/core/copilot-errors.js +32 -0
  50. package/dist/core/copilot-errors.js.map +1 -0
  51. package/dist/core/copilot-model-catalog.d.ts +132 -0
  52. package/dist/core/copilot-model-catalog.d.ts.map +1 -0
  53. package/dist/core/copilot-model-catalog.js +254 -0
  54. package/dist/core/copilot-model-catalog.js.map +1 -0
  55. package/dist/core/export-html/template.js +10 -1
  56. package/dist/core/extensions/types.d.ts +3 -1
  57. package/dist/core/extensions/types.d.ts.map +1 -1
  58. package/dist/core/extensions/types.js.map +1 -1
  59. package/dist/core/model-registry.d.ts +10 -0
  60. package/dist/core/model-registry.d.ts.map +1 -1
  61. package/dist/core/model-registry.js +107 -4
  62. package/dist/core/model-registry.js.map +1 -1
  63. package/dist/core/model-resolver.d.ts.map +1 -1
  64. package/dist/core/model-resolver.js +4 -0
  65. package/dist/core/model-resolver.js.map +1 -1
  66. package/dist/core/provider-attribution.d.ts.map +1 -1
  67. package/dist/core/provider-attribution.js +17 -7
  68. package/dist/core/provider-attribution.js.map +1 -1
  69. package/dist/core/sdk.d.ts +8 -0
  70. package/dist/core/sdk.d.ts.map +1 -1
  71. package/dist/core/sdk.js +47 -0
  72. package/dist/core/sdk.js.map +1 -1
  73. package/dist/core/session-manager.d.ts +8 -1
  74. package/dist/core/session-manager.d.ts.map +1 -1
  75. package/dist/core/session-manager.js +19 -3
  76. package/dist/core/session-manager.js.map +1 -1
  77. package/dist/core/settings-manager.d.ts +6 -0
  78. package/dist/core/settings-manager.d.ts.map +1 -1
  79. package/dist/core/settings-manager.js +69 -0
  80. package/dist/core/settings-manager.js.map +1 -1
  81. package/dist/index.d.ts +2 -1
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +1 -0
  84. package/dist/index.js.map +1 -1
  85. package/dist/main.d.ts.map +1 -1
  86. package/dist/main.js +24 -1
  87. package/dist/main.js.map +1 -1
  88. package/dist/modes/index.d.ts +1 -1
  89. package/dist/modes/index.d.ts.map +1 -1
  90. package/dist/modes/index.js.map +1 -1
  91. package/dist/modes/interactive/components/context-window-selector.d.ts +53 -0
  92. package/dist/modes/interactive/components/context-window-selector.d.ts.map +1 -0
  93. package/dist/modes/interactive/components/context-window-selector.js +136 -0
  94. package/dist/modes/interactive/components/context-window-selector.js.map +1 -0
  95. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  96. package/dist/modes/interactive/components/tree-selector.js +7 -0
  97. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  98. package/dist/modes/interactive/interactive-mode.d.ts +5 -0
  99. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  100. package/dist/modes/interactive/interactive-mode.js +91 -1
  101. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  102. package/dist/modes/rpc/rpc-client.d.ts +14 -2
  103. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  104. package/dist/modes/rpc/rpc-client.js +23 -3
  105. package/dist/modes/rpc/rpc-client.js.map +1 -1
  106. package/dist/modes/rpc/rpc-mode.d.ts +1 -1
  107. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  108. package/dist/modes/rpc/rpc-mode.js +30 -1
  109. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  110. package/dist/modes/rpc/rpc-types.d.ts +23 -0
  111. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  112. package/dist/modes/rpc/rpc-types.js.map +1 -1
  113. package/docs/custom-provider.md +4 -1
  114. package/docs/json.md +3 -1
  115. package/docs/models.md +78 -2
  116. package/docs/providers.md +3 -0
  117. package/docs/rpc.md +80 -1
  118. package/docs/sdk.md +23 -3
  119. package/docs/session-format.md +15 -1
  120. package/docs/sessions.md +1 -1
  121. package/docs/settings.md +7 -2
  122. package/docs/workflows.md +26 -4
  123. package/package.json +5 -5
@@ -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";
@@ -370,6 +372,7 @@ export class AgentSession {
370
372
  }
371
373
  }
372
374
  this._applyInterruptAbortMessage(event);
375
+ this._applyProviderErrorGuidance(event);
373
376
  // Emit to extensions first
374
377
  await this._emitExtensionEvent(event);
375
378
  // Notify all listeners
@@ -442,6 +445,16 @@ export class AgentSession {
442
445
  }
443
446
  }
444
447
  }
448
+ _applyProviderErrorGuidance(event) {
449
+ if (event.type !== "message_start" && event.type !== "message_update" && event.type !== "message_end")
450
+ return;
451
+ if (event.message.role !== "assistant")
452
+ return;
453
+ const assistantMessage = event.message;
454
+ if (assistantMessage.stopReason !== "error" || !assistantMessage.errorMessage)
455
+ return;
456
+ assistantMessage.errorMessage = formatCopilotProviderError(assistantMessage.provider, assistantMessage.errorMessage);
457
+ }
445
458
  /** Resolve the pending retry promise */
446
459
  _resolveRetry() {
447
460
  if (this._retryResolve) {
@@ -1366,14 +1379,16 @@ export class AgentSession {
1366
1379
  }
1367
1380
  const previousModel = this.model;
1368
1381
  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);
1382
+ const nextModel = this._withContextWindowForModelSwitch(model);
1383
+ this.agent.state.model = nextModel;
1384
+ this.sessionManager.appendModelChange(nextModel.provider, nextModel.id);
1385
+ this._appendContextWindowChangeIfChanged(previousModel, nextModel);
1386
+ this.settingsManager.setDefaultModelAndProvider(nextModel.provider, nextModel.id);
1372
1387
  // Re-clamp thinking level for new model's capabilities
1373
1388
  this.setThinkingLevel(thinkingLevel);
1374
1389
  this._refreshBaseSystemPromptFromActiveTools();
1375
- this._emitModelChanged(model, previousModel, "set");
1376
- await this._emitModelSelect(model, previousModel, "set");
1390
+ this._emitModelChanged(nextModel, previousModel, "set");
1391
+ await this._emitModelSelect(nextModel, previousModel, "set");
1377
1392
  }
1378
1393
  /**
1379
1394
  * Cycle to next/previous model.
@@ -1399,19 +1414,21 @@ export class AgentSession {
1399
1414
  const nextIndex = direction === "forward" ? (currentIndex + 1) % len : (currentIndex - 1 + len) % len;
1400
1415
  const next = scopedModels[nextIndex];
1401
1416
  const thinkingLevel = this._getThinkingLevelForModelSwitch(next.thinkingLevel);
1417
+ const nextModel = this._withContextWindowForModelSwitch(next.model);
1402
1418
  // 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);
1419
+ this.agent.state.model = nextModel;
1420
+ this.sessionManager.appendModelChange(nextModel.provider, nextModel.id);
1421
+ this._appendContextWindowChangeIfChanged(currentModel, nextModel);
1422
+ this.settingsManager.setDefaultModelAndProvider(nextModel.provider, nextModel.id);
1406
1423
  // Apply thinking level.
1407
1424
  // - Explicit scoped model thinking level overrides current session level
1408
1425
  // - Undefined scoped model thinking level inherits the current session preference
1409
1426
  // setThinkingLevel clamps to model capabilities.
1410
1427
  this.setThinkingLevel(thinkingLevel);
1411
1428
  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 };
1429
+ this._emitModelChanged(nextModel, currentModel, "cycle");
1430
+ await this._emitModelSelect(nextModel, currentModel, "cycle");
1431
+ return { model: nextModel, thinkingLevel: this.thinkingLevel, isScoped: true };
1415
1432
  }
1416
1433
  async _cycleAvailableModel(direction) {
1417
1434
  const availableModels = await this._modelRegistry.getAvailable();
@@ -1423,17 +1440,18 @@ export class AgentSession {
1423
1440
  currentIndex = 0;
1424
1441
  const len = availableModels.length;
1425
1442
  const nextIndex = direction === "forward" ? (currentIndex + 1) % len : (currentIndex - 1 + len) % len;
1426
- const nextModel = availableModels[nextIndex];
1443
+ const selectedModel = this._withContextWindowForModelSwitch(availableModels[nextIndex]);
1427
1444
  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);
1445
+ this.agent.state.model = selectedModel;
1446
+ this.sessionManager.appendModelChange(selectedModel.provider, selectedModel.id);
1447
+ this._appendContextWindowChangeIfChanged(currentModel, selectedModel);
1448
+ this.settingsManager.setDefaultModelAndProvider(selectedModel.provider, selectedModel.id);
1431
1449
  // Re-clamp thinking level for new model's capabilities
1432
1450
  this.setThinkingLevel(thinkingLevel);
1433
1451
  this._refreshBaseSystemPromptFromActiveTools();
1434
- this._emitModelChanged(nextModel, currentModel, "cycle");
1435
- await this._emitModelSelect(nextModel, currentModel, "cycle");
1436
- return { model: nextModel, thinkingLevel: this.thinkingLevel, isScoped: false };
1452
+ this._emitModelChanged(selectedModel, currentModel, "cycle");
1453
+ await this._emitModelSelect(selectedModel, currentModel, "cycle");
1454
+ return { model: selectedModel, thinkingLevel: this.thinkingLevel, isScoped: false };
1437
1455
  }
1438
1456
  // =========================================================================
1439
1457
  // Thinking Level Management
@@ -1506,6 +1524,118 @@ export class AgentSession {
1506
1524
  return this.model ? clampThinkingLevel(this.model, level) : "off";
1507
1525
  }
1508
1526
  // =========================================================================
1527
+ // Context Window Management
1528
+ // =========================================================================
1529
+ getAvailableContextWindows() {
1530
+ return this.model ? getSupportedContextWindows(this.model) : [];
1531
+ }
1532
+ supportsContextWindowSelection() {
1533
+ return this.getAvailableContextWindows().length > 1;
1534
+ }
1535
+ setContextWindow(contextWindow, options = {}) {
1536
+ if (!this.model) {
1537
+ throw new Error("No model selected");
1538
+ }
1539
+ const selected = selectContextWindow(this.model, contextWindow);
1540
+ if ("error" in selected) {
1541
+ throw new Error(selected.error);
1542
+ }
1543
+ const previousContextWindow = this.model.contextWindow;
1544
+ const isChanging = previousContextWindow !== selected.contextWindow;
1545
+ this.agent.state.model = selected.model;
1546
+ if (isChanging) {
1547
+ this.sessionManager.appendContextWindowChange(selected.contextWindow);
1548
+ this._emit({ type: "context_window_changed", contextWindow: selected.contextWindow });
1549
+ }
1550
+ if (options.persistDefault === true) {
1551
+ this.settingsManager.setDefaultContextWindow(selected.contextWindow);
1552
+ }
1553
+ }
1554
+ _withContextWindowForModelSwitch(model) {
1555
+ // A source model's scalar contextWindow can be its natural default (for example a 1m-default
1556
+ // model). Do not treat that alone as an opt-in to larger windows on a 400k-default target.
1557
+ const settingsDefaultContextWindow = this.settingsManager.getDefaultContextWindow();
1558
+ const candidates = [];
1559
+ const targetDefaultContextWindow = getModelDefaultContextWindow(model);
1560
+ if (model.contextWindow !== targetDefaultContextWindow) {
1561
+ // Preserve an explicit context-window selection already applied to the target model
1562
+ // (for example a caller passing selectContextWindow(target, 1m).model).
1563
+ candidates.push(model.contextWindow);
1564
+ }
1565
+ const currentModel = this.model;
1566
+ if (currentModel && this._shouldCarryCurrentContextWindowForModelSwitch(currentModel, settingsDefaultContextWindow)) {
1567
+ candidates.push(currentModel.contextWindow);
1568
+ }
1569
+ if (settingsDefaultContextWindow !== undefined) {
1570
+ candidates.push(settingsDefaultContextWindow);
1571
+ }
1572
+ candidates.push(targetDefaultContextWindow);
1573
+ const availableContextWindows = getSupportedContextWindows(model);
1574
+ const contextWindow = candidates.find((candidate) => availableContextWindows.includes(candidate));
1575
+ if (contextWindow === undefined)
1576
+ return model;
1577
+ const selected = selectContextWindow(model, contextWindow);
1578
+ return "error" in selected ? model : selected.model;
1579
+ }
1580
+ _shouldCarryCurrentContextWindowForModelSwitch(currentModel, settingsDefaultContextWindow) {
1581
+ if (currentModel.contextWindow !== getModelDefaultContextWindow(currentModel)) {
1582
+ return true;
1583
+ }
1584
+ if (this.sessionManager.getBranch().some((entry) => entry.type === "context_window_change")) {
1585
+ return true;
1586
+ }
1587
+ return (settingsDefaultContextWindow !== undefined &&
1588
+ currentModel.contextWindow === settingsDefaultContextWindow &&
1589
+ getSupportedContextWindows(currentModel).includes(settingsDefaultContextWindow));
1590
+ }
1591
+ _getContextWindowReplayForModel(model, requestedContextWindow) {
1592
+ if (requestedContextWindow !== undefined) {
1593
+ const selected = selectContextWindow(model, requestedContextWindow);
1594
+ if (!("error" in selected)) {
1595
+ return { model: selected.model, contextWindow: selected.contextWindow, wouldWarn: false };
1596
+ }
1597
+ return this._getDefaultContextWindowReplayForModel(model, true);
1598
+ }
1599
+ return this._getDefaultContextWindowReplayForModel(model, false);
1600
+ }
1601
+ _getDefaultContextWindowReplayForModel(model, wouldWarn) {
1602
+ const defaultContextWindow = getModelDefaultContextWindow(model);
1603
+ const selected = selectContextWindow(model, defaultContextWindow);
1604
+ if (!("error" in selected)) {
1605
+ return { model: selected.model, contextWindow: selected.contextWindow, wouldWarn };
1606
+ }
1607
+ return {
1608
+ model: { ...model, contextWindow: defaultContextWindow, defaultContextWindow },
1609
+ contextWindow: defaultContextWindow,
1610
+ wouldWarn,
1611
+ };
1612
+ }
1613
+ _getResumeContextWindowReplayForModel(model) {
1614
+ const sessionContext = this.sessionManager.buildSessionContext();
1615
+ const requestedContextWindow = sessionContext.contextWindow ?? this.settingsManager.getDefaultContextWindow();
1616
+ return this._getContextWindowReplayForModel(model, requestedContextWindow);
1617
+ }
1618
+ _applyContextWindowReplay(contextWindow) {
1619
+ if (!this.model)
1620
+ return;
1621
+ const previousContextWindow = this.model.contextWindow;
1622
+ const requestedContextWindow = contextWindow ?? this.settingsManager.getDefaultContextWindow();
1623
+ const replay = this._getContextWindowReplayForModel(this.model, requestedContextWindow);
1624
+ this.agent.state.model = replay.model;
1625
+ if (previousContextWindow !== replay.contextWindow) {
1626
+ this._emit({ type: "context_window_changed", contextWindow: replay.contextWindow });
1627
+ }
1628
+ }
1629
+ _appendContextWindowChangeIfChanged(previousModel, nextModel) {
1630
+ const replay = this._getResumeContextWindowReplayForModel(nextModel);
1631
+ if (!replay.wouldWarn && nextModel.contextWindow === replay.contextWindow)
1632
+ return;
1633
+ this.sessionManager.appendContextWindowChange(nextModel.contextWindow);
1634
+ if (previousModel?.contextWindow !== nextModel.contextWindow) {
1635
+ this._emit({ type: "context_window_changed", contextWindow: nextModel.contextWindow });
1636
+ }
1637
+ }
1638
+ // =========================================================================
1509
1639
  // Queue Mode Management
1510
1640
  // =========================================================================
1511
1641
  /**
@@ -1812,6 +1942,12 @@ export class AgentSession {
1812
1942
  return;
1813
1943
  }
1814
1944
  // Case 1: Overflow - LLM returned context overflow error
1945
+ // When Copilot rejects a 1m client-budget prompt at a lower server cap (for example
1946
+ // because long-context/usage-based billing entitlement is missing), leave the friendly
1947
+ // error visible instead of auto-compacting down to a smaller server tier silently.
1948
+ if (sameModel && this._isCopilotServerCapBelowSelectedContextWindow(assistantMessage)) {
1949
+ return;
1950
+ }
1815
1951
  if (sameModel && isContextOverflow(assistantMessage, contextWindow)) {
1816
1952
  if (this._overflowRecoveryAttempted) {
1817
1953
  this._emit({
@@ -1861,6 +1997,12 @@ export class AgentSession {
1861
1997
  await this._runAutoCompaction("threshold", false);
1862
1998
  }
1863
1999
  }
2000
+ _isCopilotServerCapBelowSelectedContextWindow(assistantMessage) {
2001
+ if (!this.model || this.model.provider !== "github-copilot" || !assistantMessage.errorMessage)
2002
+ return false;
2003
+ const promptLimitError = parseCopilotPromptLimitError(assistantMessage.errorMessage);
2004
+ return promptLimitError !== undefined && this.model.contextWindow > promptLimitError.limitTokens;
2005
+ }
1864
2006
  /**
1865
2007
  * Internal: remove the trailing overflow error from retry context if it is still present.
1866
2008
  */
@@ -2686,6 +2828,7 @@ export class AgentSession {
2686
2828
  // Update agent state
2687
2829
  const sessionContext = this.sessionManager.buildSessionContext();
2688
2830
  this.agent.state.messages = sessionContext.messages;
2831
+ this._applyContextWindowReplay(sessionContext.contextWindow);
2689
2832
  // Emit session_tree event
2690
2833
  await this._extensionRunner.emit({
2691
2834
  type: "session_tree",