@bastani/atomic 0.8.26-alpha.7 → 0.8.26-alpha.8

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 (67) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +5 -8
  3. package/dist/builtin/intercom/CHANGELOG.md +6 -0
  4. package/dist/builtin/intercom/package.json +1 -1
  5. package/dist/builtin/mcp/CHANGELOG.md +6 -0
  6. package/dist/builtin/mcp/package.json +1 -1
  7. package/dist/builtin/subagents/CHANGELOG.md +6 -0
  8. package/dist/builtin/subagents/package.json +1 -1
  9. package/dist/builtin/web-access/CHANGELOG.md +6 -0
  10. package/dist/builtin/web-access/package.json +1 -1
  11. package/dist/builtin/workflows/CHANGELOG.md +6 -0
  12. package/dist/builtin/workflows/package.json +1 -1
  13. package/dist/builtin/workflows/src/extension/wiring.ts +13 -1
  14. package/dist/builtin/workflows/src/runs/foreground/executor.ts +12 -6
  15. package/dist/builtin/workflows/src/runs/foreground/stage-runner.ts +2 -2
  16. package/dist/builtin/workflows/src/shared/authoring-contract.d.ts +2 -2
  17. package/dist/builtin/workflows/src/shared/types.ts +3 -3
  18. package/dist/builtin/workflows/src/tui/stage-chat-view.ts +1 -9
  19. package/dist/core/agent-session.d.ts +5 -5
  20. package/dist/core/agent-session.d.ts.map +1 -1
  21. package/dist/core/agent-session.js +64 -173
  22. package/dist/core/agent-session.js.map +1 -1
  23. package/dist/core/atomic-guide-command.d.ts.map +1 -1
  24. package/dist/core/atomic-guide-command.js +1 -1
  25. package/dist/core/atomic-guide-command.js.map +1 -1
  26. package/dist/core/extensions/types.d.ts +3 -2
  27. package/dist/core/extensions/types.d.ts.map +1 -1
  28. package/dist/core/extensions/types.js.map +1 -1
  29. package/dist/core/session-manager.d.ts.map +1 -1
  30. package/dist/core/session-manager.js +1 -1
  31. package/dist/core/session-manager.js.map +1 -1
  32. package/dist/core/slash-commands.d.ts.map +1 -1
  33. package/dist/core/slash-commands.js +1 -2
  34. package/dist/core/slash-commands.js.map +1 -1
  35. package/dist/modes/interactive/components/chat-session-host.d.ts.map +1 -1
  36. package/dist/modes/interactive/components/chat-session-host.js +1 -1
  37. package/dist/modes/interactive/components/chat-session-host.js.map +1 -1
  38. package/dist/modes/interactive/components/context-compaction-summary-message.d.ts +17 -0
  39. package/dist/modes/interactive/components/context-compaction-summary-message.d.ts.map +1 -0
  40. package/dist/modes/interactive/components/context-compaction-summary-message.js +83 -0
  41. package/dist/modes/interactive/components/context-compaction-summary-message.js.map +1 -0
  42. package/dist/modes/interactive/components/index.d.ts +1 -0
  43. package/dist/modes/interactive/components/index.d.ts.map +1 -1
  44. package/dist/modes/interactive/components/index.js +1 -0
  45. package/dist/modes/interactive/components/index.js.map +1 -1
  46. package/dist/modes/interactive/interactive-mode.d.ts +1 -1
  47. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  48. package/dist/modes/interactive/interactive-mode.js +28 -38
  49. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  50. package/dist/modes/rpc/rpc-client.d.ts +3 -3
  51. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  52. package/dist/modes/rpc/rpc-client.js +1 -1
  53. package/dist/modes/rpc/rpc-client.js.map +1 -1
  54. package/dist/modes/rpc/rpc-types.d.ts +2 -2
  55. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  56. package/dist/modes/rpc/rpc-types.js.map +1 -1
  57. package/docs/compaction.md +71 -38
  58. package/docs/extensions.md +9 -5
  59. package/docs/index.md +1 -1
  60. package/docs/json.md +2 -2
  61. package/docs/rpc.md +19 -40
  62. package/docs/sdk.md +2 -2
  63. package/docs/session-format.md +3 -3
  64. package/docs/sessions.md +2 -3
  65. package/docs/settings.md +2 -2
  66. package/docs/usage.md +2 -4
  67. package/package.json +1 -1
@@ -22,7 +22,7 @@ import { sleep } from "../utils/sleep.js";
22
22
  import { ATOMIC_GUIDE_COMMAND_NAME, ATOMIC_GUIDE_HELP_CHOICES, atomicGuideModeForChoice, getAtomicGuideMessage, isAtomicGuideHelpChoice, normalizeAtomicGuideMode, } from "./atomic-guide-command.js";
23
23
  import { formatNoApiKeyFoundMessage, formatNoModelSelectedMessage } from "./auth-guidance.js";
24
24
  import { executeBashWithOperations } from "./bash-executor.js";
25
- import { calculateContextTokens, collectEntriesForBranchSummary, compact, contextCompact as runContextCompact, estimateContextTokens, generateBranchSummary, prepareCompaction, prepareContextCompaction, shouldCompact, } from "./compaction/index.js";
25
+ import { calculateContextTokens, collectEntriesForBranchSummary, contextCompact as runContextCompact, estimateContextTokens, generateBranchSummary, prepareContextCompaction, shouldCompact, } from "./compaction/index.js";
26
26
  import { DEFAULT_THINKING_LEVEL } from "./defaults.js";
27
27
  import { exportSessionToHtml } from "./export-html/index.js";
28
28
  import { createToolHtmlRenderer } from "./export-html/tool-renderer.js";
@@ -1476,11 +1476,41 @@ export class AgentSession {
1476
1476
  // Compaction
1477
1477
  // =========================================================================
1478
1478
  /**
1479
- * Manually compact the session context.
1480
- * Aborts current agent operation first.
1481
- * @param customInstructions Optional instructions for the compaction summary
1479
+ * Apply validated logical deletions and rebuild active agent context.
1480
+ * Retained transcript entries/content blocks stay verbatim.
1481
+ */
1482
+ async _applyContextVerbatimCompaction(options) {
1483
+ if (!this.model) {
1484
+ throw new Error(formatNoModelSelectedMessage());
1485
+ }
1486
+ const pathEntries = this.sessionManager.getBranch();
1487
+ const settings = this.settingsManager.getCompactionSettings();
1488
+ const preparation = prepareContextCompaction(pathEntries, settings);
1489
+ if (!preparation) {
1490
+ return undefined;
1491
+ }
1492
+ const validated = await runContextCompact(preparation, this.model, options.apiKey, options.headers, options.abortController.signal, this.thinkingLevel);
1493
+ if (options.abortController.signal.aborted) {
1494
+ throw new Error("Compaction cancelled");
1495
+ }
1496
+ const backupPath = this.sessionManager.writeBackupSnapshot(options.backupLabel);
1497
+ this.sessionManager.appendContextCompaction(validated.deletedTargets, validated.protectedEntryIds, validated.stats, backupPath);
1498
+ const sessionContext = this.sessionManager.buildSessionContext();
1499
+ this.agent.state.messages = sessionContext.messages;
1500
+ return {
1501
+ ...validated,
1502
+ promptVersion: 1,
1503
+ ...(backupPath ? { backupPath } : {}),
1504
+ };
1505
+ }
1506
+ /**
1507
+ * Manually compact the session context using deletion-only verbatim context compaction.
1508
+ * Aborts current agent operation first. Custom summary instructions are not accepted.
1482
1509
  */
1483
1510
  async compact(customInstructions) {
1511
+ if (customInstructions?.trim()) {
1512
+ throw new Error("Custom compaction instructions are not supported; use /compact without arguments");
1513
+ }
1484
1514
  this._disconnectFromAgent();
1485
1515
  await this.abort();
1486
1516
  this._compactionAbortController = new AbortController();
@@ -1490,84 +1520,23 @@ export class AgentSession {
1490
1520
  throw new Error(formatNoModelSelectedMessage());
1491
1521
  }
1492
1522
  const { apiKey, headers } = await this._getRequiredRequestAuth(this.model);
1493
- const pathEntries = this.sessionManager.getBranch();
1494
- const settings = this.settingsManager.getCompactionSettings();
1495
- const preparation = prepareCompaction(pathEntries, settings);
1496
- if (!preparation) {
1497
- // Check why we can't compact
1498
- const lastEntry = pathEntries[pathEntries.length - 1];
1499
- if (lastEntry?.type === "compaction") {
1500
- throw new Error("Already compacted");
1501
- }
1523
+ const result = await this._applyContextVerbatimCompaction({
1524
+ apiKey,
1525
+ headers,
1526
+ abortController: this._compactionAbortController,
1527
+ backupLabel: "compact",
1528
+ });
1529
+ if (!result) {
1502
1530
  throw new Error("Nothing to compact (session too small)");
1503
1531
  }
1504
- let extensionCompaction;
1505
- let fromExtension = false;
1506
- if (this._extensionRunner.hasHandlers("session_before_compact")) {
1507
- const result = (await this._extensionRunner.emit({
1508
- type: "session_before_compact",
1509
- preparation,
1510
- branchEntries: pathEntries,
1511
- customInstructions,
1512
- signal: this._compactionAbortController.signal,
1513
- }));
1514
- if (result?.cancel) {
1515
- throw new Error("Compaction cancelled");
1516
- }
1517
- if (result?.compaction) {
1518
- extensionCompaction = result.compaction;
1519
- fromExtension = true;
1520
- }
1521
- }
1522
- let summary;
1523
- let firstKeptEntryId;
1524
- let tokensBefore;
1525
- let details;
1526
- if (extensionCompaction) {
1527
- // Extension provided compaction content
1528
- summary = extensionCompaction.summary;
1529
- firstKeptEntryId = extensionCompaction.firstKeptEntryId;
1530
- tokensBefore = extensionCompaction.tokensBefore;
1531
- details = extensionCompaction.details;
1532
- }
1533
- else {
1534
- // Generate compaction result
1535
- const result = await compact(preparation, this.model, apiKey, headers, customInstructions, this._compactionAbortController.signal, this.thinkingLevel);
1536
- summary = result.summary;
1537
- firstKeptEntryId = result.firstKeptEntryId;
1538
- tokensBefore = result.tokensBefore;
1539
- details = result.details;
1540
- }
1541
- if (this._compactionAbortController.signal.aborted) {
1542
- throw new Error("Compaction cancelled");
1543
- }
1544
- this.sessionManager.appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromExtension);
1545
- const newEntries = this.sessionManager.getEntries();
1546
- const sessionContext = this.sessionManager.buildSessionContext();
1547
- this.agent.state.messages = sessionContext.messages;
1548
- // Get the saved compaction entry for the extension event
1549
- const savedCompactionEntry = newEntries.find((e) => e.type === "compaction" && e.summary === summary);
1550
- if (this._extensionRunner && savedCompactionEntry) {
1551
- await this._extensionRunner.emit({
1552
- type: "session_compact",
1553
- compactionEntry: savedCompactionEntry,
1554
- fromExtension,
1555
- });
1556
- }
1557
- const compactionResult = {
1558
- summary,
1559
- firstKeptEntryId,
1560
- tokensBefore,
1561
- details,
1562
- };
1563
1532
  this._emit({
1564
1533
  type: "compaction_end",
1565
1534
  reason: "manual",
1566
- result: compactionResult,
1535
+ result,
1567
1536
  aborted: false,
1568
1537
  willRetry: false,
1569
1538
  });
1570
- return compactionResult;
1539
+ return result;
1571
1540
  }
1572
1541
  catch (error) {
1573
1542
  const message = error instanceof Error ? error.message : String(error);
@@ -1601,25 +1570,15 @@ export class AgentSession {
1601
1570
  throw new Error(formatNoModelSelectedMessage());
1602
1571
  }
1603
1572
  const { apiKey, headers } = await this._getRequiredRequestAuth(this.model);
1604
- const pathEntries = this.sessionManager.getBranch();
1605
- const settings = this.settingsManager.getCompactionSettings();
1606
- const preparation = prepareContextCompaction(pathEntries, settings);
1607
- if (!preparation) {
1573
+ const result = await this._applyContextVerbatimCompaction({
1574
+ apiKey,
1575
+ headers,
1576
+ abortController: this._compactionAbortController,
1577
+ backupLabel: "context-compact",
1578
+ });
1579
+ if (!result) {
1608
1580
  throw new Error("Nothing to context-compact (session too small)");
1609
1581
  }
1610
- const validated = await runContextCompact(preparation, this.model, apiKey, headers, this._compactionAbortController.signal, this.thinkingLevel);
1611
- if (this._compactionAbortController.signal.aborted) {
1612
- throw new Error("Compaction cancelled");
1613
- }
1614
- const backupPath = this.sessionManager.writeBackupSnapshot("context-compact");
1615
- this.sessionManager.appendContextCompaction(validated.deletedTargets, validated.protectedEntryIds, validated.stats, backupPath);
1616
- const sessionContext = this.sessionManager.buildSessionContext();
1617
- this.agent.state.messages = sessionContext.messages;
1618
- const result = {
1619
- ...validated,
1620
- promptVersion: 1,
1621
- backupPath,
1622
- };
1623
1582
  this._emit({
1624
1583
  type: "context_compaction_end",
1625
1584
  reason: "manual",
@@ -1781,7 +1740,6 @@ export class AgentSession {
1781
1740
  * Internal: Run auto-compaction with events.
1782
1741
  */
1783
1742
  async _runAutoCompaction(reason, willRetry) {
1784
- const settings = this.settingsManager.getCompactionSettings();
1785
1743
  this._emit({ type: "compaction_start", reason });
1786
1744
  this._autoCompactionAbortController = new AbortController();
1787
1745
  try {
@@ -1806,10 +1764,13 @@ export class AgentSession {
1806
1764
  });
1807
1765
  return;
1808
1766
  }
1809
- const { apiKey, headers } = authResult;
1810
- const pathEntries = this.sessionManager.getBranch();
1811
- const preparation = prepareCompaction(pathEntries, settings);
1812
- if (!preparation) {
1767
+ const result = await this._applyContextVerbatimCompaction({
1768
+ apiKey: authResult.apiKey,
1769
+ headers: authResult.headers,
1770
+ abortController: this._autoCompactionAbortController,
1771
+ backupLabel: reason === "overflow" ? "overflow-auto-compact" : "auto-compact",
1772
+ });
1773
+ if (!result) {
1813
1774
  this._emit({
1814
1775
  type: "compaction_end",
1815
1776
  reason,
@@ -1819,96 +1780,26 @@ export class AgentSession {
1819
1780
  });
1820
1781
  return;
1821
1782
  }
1822
- let extensionCompaction;
1823
- let fromExtension = false;
1824
- if (this._extensionRunner.hasHandlers("session_before_compact")) {
1825
- const extensionResult = (await this._extensionRunner.emit({
1826
- type: "session_before_compact",
1827
- preparation,
1828
- branchEntries: pathEntries,
1829
- customInstructions: undefined,
1830
- signal: this._autoCompactionAbortController.signal,
1831
- }));
1832
- if (extensionResult?.cancel) {
1833
- this._emit({
1834
- type: "compaction_end",
1835
- reason,
1836
- result: undefined,
1837
- aborted: true,
1838
- willRetry: false,
1839
- });
1840
- return;
1841
- }
1842
- if (extensionResult?.compaction) {
1843
- extensionCompaction = extensionResult.compaction;
1844
- fromExtension = true;
1845
- }
1846
- }
1847
- let summary;
1848
- let firstKeptEntryId;
1849
- let tokensBefore;
1850
- let details;
1851
- if (extensionCompaction) {
1852
- // Extension provided compaction content
1853
- summary = extensionCompaction.summary;
1854
- firstKeptEntryId = extensionCompaction.firstKeptEntryId;
1855
- tokensBefore = extensionCompaction.tokensBefore;
1856
- details = extensionCompaction.details;
1857
- }
1858
- else {
1859
- // Generate compaction result
1860
- const compactResult = await compact(preparation, this.model, apiKey, headers, undefined, this._autoCompactionAbortController.signal, this.thinkingLevel);
1861
- summary = compactResult.summary;
1862
- firstKeptEntryId = compactResult.firstKeptEntryId;
1863
- tokensBefore = compactResult.tokensBefore;
1864
- details = compactResult.details;
1865
- }
1866
- if (this._autoCompactionAbortController.signal.aborted) {
1867
- this._emit({
1868
- type: "compaction_end",
1869
- reason,
1870
- result: undefined,
1871
- aborted: true,
1872
- willRetry: false,
1873
- });
1874
- return;
1875
- }
1876
- this.sessionManager.appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromExtension);
1877
- const newEntries = this.sessionManager.getEntries();
1878
- const sessionContext = this.sessionManager.buildSessionContext();
1879
- this.agent.state.messages = sessionContext.messages;
1880
1783
  if (reason === "overflow" && willRetry) {
1881
1784
  this._dropTrailingOverflowAssistantErrorIfPresent();
1882
1785
  }
1883
- // Get the saved compaction entry for the extension event
1884
- const savedCompactionEntry = newEntries.find((e) => e.type === "compaction" && e.summary === summary);
1885
- if (this._extensionRunner && savedCompactionEntry) {
1886
- await this._extensionRunner.emit({
1887
- type: "session_compact",
1888
- compactionEntry: savedCompactionEntry,
1889
- fromExtension,
1890
- });
1891
- }
1892
- const result = {
1893
- summary,
1894
- firstKeptEntryId,
1895
- tokensBefore,
1896
- details,
1897
- };
1898
1786
  this._emit({ type: "compaction_end", reason, result, aborted: false, willRetry });
1899
1787
  this._schedulePostAutoCompactionContinuationProbe(reason, willRetry);
1900
1788
  }
1901
1789
  catch (error) {
1902
1790
  const errorMessage = error instanceof Error ? error.message : "compaction failed";
1791
+ const aborted = errorMessage === "Compaction cancelled" || (error instanceof Error && error.name === "AbortError");
1903
1792
  this._emit({
1904
1793
  type: "compaction_end",
1905
1794
  reason,
1906
1795
  result: undefined,
1907
- aborted: false,
1796
+ aborted,
1908
1797
  willRetry: false,
1909
- errorMessage: reason === "overflow"
1910
- ? `Context overflow recovery failed: ${errorMessage}`
1911
- : `Auto-compaction failed: ${errorMessage}`,
1798
+ errorMessage: aborted
1799
+ ? undefined
1800
+ : reason === "overflow"
1801
+ ? `Context overflow recovery failed: ${errorMessage}`
1802
+ : `Auto-compaction failed: ${errorMessage}`,
1912
1803
  });
1913
1804
  }
1914
1805
  finally {