@north-light/crouter 0.3.163 → 0.3.165

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 (167) hide show
  1. package/dist/build-root.d.ts +6 -6
  2. package/dist/build-root.js +12 -13
  3. package/dist/builtin-memory/00-runtime-base.md +3 -4
  4. package/dist/builtin-memory/01-spine/01-no-manager.md +1 -1
  5. package/dist/builtin-memory/02-lifecycle/00-terminal.md +2 -0
  6. package/dist/builtin-memory/04-orchestration-kernel.md +16 -18
  7. package/dist/builtin-memory/05-kinds/advisor/00-base.md +0 -2
  8. package/dist/builtin-memory/05-kinds/advisor/01-orchestrator.md +3 -9
  9. package/dist/builtin-memory/05-kinds/developer/00-base.md +1 -3
  10. package/dist/builtin-memory/05-kinds/developer/01-orchestrator.md +2 -10
  11. package/dist/builtin-memory/05-kinds/explore/00-base.md +2 -2
  12. package/dist/builtin-memory/05-kinds/explore/01-orchestrator.md +0 -2
  13. package/dist/builtin-memory/05-kinds/general/00-base.md +3 -5
  14. package/dist/builtin-memory/05-kinds/general/01-orchestrator.md +0 -4
  15. package/dist/builtin-memory/05-kinds/plan/01-orchestrator.md +1 -3
  16. package/dist/builtin-memory/05-kinds/plan/reviewers/00-base.md +12 -0
  17. package/dist/builtin-memory/05-kinds/plan/reviewers/architecture-fit.md +0 -2
  18. package/dist/builtin-memory/05-kinds/plan/reviewers/code-smells.md +0 -2
  19. package/dist/builtin-memory/05-kinds/plan/reviewers/pattern-consistency.md +0 -2
  20. package/dist/builtin-memory/05-kinds/plan/reviewers/requirements-coverage.md +1 -1
  21. package/dist/builtin-memory/05-kinds/plan/reviewers/security.md +0 -2
  22. package/dist/builtin-memory/05-kinds/review/00-base.md +0 -2
  23. package/dist/builtin-memory/05-kinds/review/01-orchestrator.md +1 -3
  24. package/dist/builtin-memory/05-kinds/spec/00-base.md +1 -1
  25. package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +2 -4
  26. package/dist/builtin-memory/05-kinds/spec/requirements.md +1 -1
  27. package/dist/builtin-memory/advisor/council.md +40 -0
  28. package/dist/builtin-memory/design.md +8 -11
  29. package/dist/builtin-memory/development.md +6 -9
  30. package/dist/builtin-memory/internal/INDEX.md +5 -5
  31. package/dist/builtin-memory/internal/agent-shaping.md +5 -7
  32. package/dist/builtin-memory/internal/examples/imessage-assistant.md +3 -3
  33. package/dist/builtin-memory/internal/marketplaces.md +13 -14
  34. package/dist/builtin-memory/internal/memory-loading.md +45 -0
  35. package/dist/builtin-memory/internal/nodes-and-canvas.md +4 -4
  36. package/dist/builtin-memory/internal/plugins.md +61 -45
  37. package/dist/builtin-memory/planning.md +4 -7
  38. package/dist/builtin-memory/spec.md +9 -12
  39. package/dist/builtin-memory/wedged-child-on-runaway-bash.md +8 -22
  40. package/dist/cli.js +1 -1
  41. package/dist/clients/attach/__tests__/attach-keybindings.test.js +17 -4
  42. package/dist/clients/attach/__tests__/context-message.test.js +31 -20
  43. package/dist/clients/attach/__tests__/crtr-output-coverage.test.js +1 -1
  44. package/dist/clients/attach/__tests__/crtr-output.test.js +39 -30
  45. package/dist/clients/attach/__tests__/edit-diff.test.js +21 -20
  46. package/dist/clients/attach/render/chat-view.d.ts +20 -20
  47. package/dist/clients/attach/render/chat-view.js +88 -89
  48. package/dist/clients/attach/render/{frozen-history.d.ts → condensed-history.d.ts} +1 -18
  49. package/dist/clients/attach/render/condensed-history.js +60 -0
  50. package/dist/clients/attach/render/context-message.js +9 -14
  51. package/dist/clients/attach/render/crtr-output.d.ts +2 -1
  52. package/dist/clients/attach/render/crtr-output.js +4 -4
  53. package/dist/clients/attach/render/edit-diff.d.ts +21 -6
  54. package/dist/clients/attach/render/edit-diff.js +90 -91
  55. package/dist/clients/attach/render/tool-calls.d.ts +14 -18
  56. package/dist/clients/attach/render/tool-calls.js +66 -41
  57. package/dist/clients/attach/session/bindings.d.ts +5 -3
  58. package/dist/clients/attach/session/bindings.js +7 -13
  59. package/dist/clients/attach/session/keys.d.ts +2 -0
  60. package/dist/clients/attach/session/keys.js +36 -37
  61. package/dist/clients/attach/session/profile-files.d.ts +8 -0
  62. package/dist/clients/attach/session/profile-files.js +157 -0
  63. package/dist/clients/attach/viewer.js +530 -528
  64. package/dist/commands/memory/lint.js +1 -1
  65. package/dist/commands/memory/write.js +1 -1
  66. package/dist/commands/node.js +2 -2
  67. package/dist/commands/pkg/plugin-inspect.js +6 -7
  68. package/dist/commands/pkg/plugin-manage.d.ts +1 -1
  69. package/dist/commands/pkg/plugin-manage.js +131 -19
  70. package/dist/commands/pkg/plugin.js +2 -2
  71. package/dist/commands/pkg.js +6 -11
  72. package/dist/commands/profile/env.js +3 -3
  73. package/dist/commands/sys/config.js +17 -76
  74. package/dist/commands/sys/doctor.js +5 -91
  75. package/dist/commands/sys/setup-wizard.d.ts +9 -11
  76. package/dist/commands/sys/setup-wizard.js +47 -81
  77. package/dist/core/__tests__/base-worker-prompt.test.js +18 -21
  78. package/dist/core/__tests__/command-plugins-surfaces.test.js +39 -5
  79. package/dist/core/__tests__/command-plugins.test.js +36 -16
  80. package/dist/core/__tests__/review-model-floor.test.js +2 -2
  81. package/dist/core/__tests__/tmux-surface.test.js +10 -1
  82. package/dist/core/command-manifests/manifest.d.ts +24 -0
  83. package/dist/core/{configured-clis → command-manifests}/manifest.js +21 -25
  84. package/dist/core/command-manifests/registry.d.ts +1 -2
  85. package/dist/core/command-manifests/registry.js +2 -2
  86. package/dist/core/command-manifests/schema.d.ts +11 -13
  87. package/dist/core/command-manifests/schema.js +53 -192
  88. package/dist/core/command-plugins/compose.d.ts +0 -6
  89. package/dist/core/command-plugins/compose.js +28 -75
  90. package/dist/core/command-plugins/discovery.d.ts +25 -58
  91. package/dist/core/command-plugins/discovery.js +152 -259
  92. package/dist/core/command-plugins/endpoint.d.ts +24 -0
  93. package/dist/core/command-plugins/endpoint.js +48 -0
  94. package/dist/core/command-plugins/store.d.ts +16 -0
  95. package/dist/core/command-plugins/store.js +64 -0
  96. package/dist/core/command-plugins/{adapter.d.ts → transport/exec-invoke.d.ts} +3 -3
  97. package/dist/core/command-plugins/{adapter.js → transport/exec-invoke.js} +4 -4
  98. package/dist/core/{configured-clis/fetch.d.ts → command-plugins/transport/http-fetch.d.ts} +9 -18
  99. package/dist/core/{configured-clis/fetch.js → command-plugins/transport/http-fetch.js} +15 -35
  100. package/dist/core/{configured-clis/invoker.d.ts → command-plugins/transport/http-invoke.d.ts} +7 -7
  101. package/dist/core/{configured-clis/invoker.js → command-plugins/transport/http-invoke.js} +21 -23
  102. package/dist/core/command.d.ts +8 -9
  103. package/dist/core/command.js +6 -9
  104. package/dist/core/config.js +6 -10
  105. package/dist/core/env-name.d.ts +6 -0
  106. package/dist/core/env-name.js +9 -0
  107. package/dist/core/io.d.ts +1 -1
  108. package/dist/core/keybindings/__tests__/resolve.test.js +40 -3
  109. package/dist/core/keybindings/attach-control.d.ts +37 -0
  110. package/dist/core/keybindings/attach-control.js +38 -0
  111. package/dist/core/keybindings/catalog.d.ts +5 -4
  112. package/dist/core/keybindings/catalog.js +16 -8
  113. package/dist/core/keybindings/index.d.ts +1 -0
  114. package/dist/core/keybindings/index.js +1 -0
  115. package/dist/core/keybindings/types.d.ts +1 -1
  116. package/dist/core/preview-registry.js +41 -74
  117. package/dist/core/runtime/bearings.d.ts +2 -5
  118. package/dist/core/runtime/bearings.js +2 -5
  119. package/dist/core/runtime/front-door.d.ts +1 -1
  120. package/dist/core/runtime/front-door.js +2 -2
  121. package/dist/core/runtime/kickoff.d.ts +3 -3
  122. package/dist/core/runtime/kickoff.js +4 -3
  123. package/dist/core/runtime/situational-context.d.ts +1 -1
  124. package/dist/core/runtime/situational-context.js +1 -1
  125. package/dist/core/runtime/spawn.js +9 -9
  126. package/dist/core/runtime/tmux.js +29 -2
  127. package/dist/core/scope.d.ts +0 -5
  128. package/dist/core/scope.js +0 -10
  129. package/dist/core/user-settings.d.ts +193 -0
  130. package/dist/core/user-settings.js +252 -0
  131. package/dist/index.d.ts +4 -0
  132. package/dist/index.js +3 -0
  133. package/dist/pi-extensions/canvas-stophook.js +3 -2
  134. package/dist/pi-extensions/canvas-tool-guide.js +4 -1
  135. package/dist/shared/generated-context.d.ts +34 -0
  136. package/dist/shared/generated-context.js +98 -0
  137. package/dist/types.d.ts +23 -16
  138. package/dist/types.js +3 -14
  139. package/dist/web-client/assets/{index-NIuSCOHM.js → index-BMTOGuOZ.js} +19 -19
  140. package/dist/web-client/assets/index-DvA6Zw-R.css +2 -0
  141. package/dist/web-client/index.html +2 -2
  142. package/dist/web-client/sw.js +1 -1
  143. package/docs/public-api.md +1 -0
  144. package/package.json +2 -2
  145. package/runtime.lock.json +6 -6
  146. package/dist/builtin-memory/05-kinds/product/00-base.md +0 -25
  147. package/dist/builtin-memory/05-kinds/product/01-orchestrator.md +0 -15
  148. package/dist/builtin-memory/05-kinds/product/teardown.md +0 -15
  149. package/dist/builtin-memory/internal/workflow-codification.md +0 -82
  150. package/dist/builtin-memory/product.md +0 -80
  151. package/dist/clients/attach/render/frozen-history.js +0 -100
  152. package/dist/commands/pkg/cli-inspect.d.ts +0 -17
  153. package/dist/commands/pkg/cli-inspect.js +0 -190
  154. package/dist/commands/pkg/cli-manage.d.ts +0 -3
  155. package/dist/commands/pkg/cli-manage.js +0 -206
  156. package/dist/commands/pkg/cli.d.ts +0 -1
  157. package/dist/commands/pkg/cli.js +0 -14
  158. package/dist/core/configured-clis/cache.d.ts +0 -16
  159. package/dist/core/configured-clis/cache.js +0 -57
  160. package/dist/core/configured-clis/compose.d.ts +0 -14
  161. package/dist/core/configured-clis/compose.js +0 -60
  162. package/dist/core/configured-clis/discovery.d.ts +0 -47
  163. package/dist/core/configured-clis/discovery.js +0 -173
  164. package/dist/core/configured-clis/manifest.d.ts +0 -24
  165. package/dist/core/configured-clis/registration.d.ts +0 -40
  166. package/dist/core/configured-clis/registration.js +0 -201
  167. package/dist/web-client/assets/index-CqLKj8Xu.css +0 -2
@@ -1568,15 +1568,22 @@ test('node and package mutations share compact outcome-first receipts', () => {
1568
1568
  assert.match(collapsed, /ctrl\+o to expand/, command);
1569
1569
  }
1570
1570
  });
1571
- const PKG_PLUGIN_INSTALL_OUTPUT = ['- name: ai', '- scope: user', '', '/Users/silas/.crouter/plugins/ai'].join('\n');
1572
- const PKG_PLUGIN_INSTALL_SHORT_PATH_OUTPUT = ['- name: ai', '- scope: user', '- path: /a'].join('\n');
1571
+ const PKG_PLUGIN_INSTALL_OUTPUT = [
1572
+ '- name: ai',
1573
+ '- scope: user',
1574
+ '- transport: exec',
1575
+ '- commands: {"mounts":["app"],"issues":[]}',
1576
+ '',
1577
+ '/Users/silas/.crouter/plugins/ai',
1578
+ ].join('\n');
1579
+ const PKG_PLUGIN_INSTALL_SHORT_PATH_OUTPUT = ['- name: ai', '- scope: user', '- transport: http', '- path: /a'].join('\n');
1573
1580
  test('a crtr pkg plugin install card collapses to an installed status + scope/path digest, not the raw fields', () => {
1574
1581
  const def = createCrtrBashToolDefinition({ command: 'crtr pkg plugin install ai' });
1575
1582
  const collapsed = def
1576
1583
  .renderResult({ content: [{ type: 'text', text: PKG_PLUGIN_INSTALL_OUTPUT }] }, { expanded: false }, theme, {})
1577
1584
  .render(140)
1578
1585
  .join('\n');
1579
- assert.match(collapsed, /<success>installed ai<\/success>/);
1586
+ assert.match(collapsed, /<success>installed ai · exec<\/success>/);
1580
1587
  assert.match(collapsed, /<muted>user · \/Users\/silas\/\.crouter\/plugins\/ai<\/muted>/);
1581
1588
  assert.doesNotMatch(collapsed, /- name:/);
1582
1589
  const expanded = def
@@ -1588,33 +1595,34 @@ test('a crtr pkg plugin install card collapses to an installed status + scope/pa
1588
1595
  .renderResult({ content: [{ type: 'text', text: PKG_PLUGIN_INSTALL_SHORT_PATH_OUTPUT }] }, { expanded: false }, theme, {})
1589
1596
  .render(140)
1590
1597
  .join('\n');
1598
+ assert.match(shortPath, /<success>installed ai · http<\/success>/);
1591
1599
  assert.match(shortPath, /<muted>user · \/a<\/muted>/);
1592
1600
  });
1593
- const PKG_PLUGIN_UPDATE_UPDATED_OUTPUT = ['1 updated:', '', '| name | updated | sha |', '| --- | --- | --- |', '| ai | true | def5678 |'].join('\n');
1594
- const PKG_PLUGIN_UPDATE_CURRENT_OUTPUT = ['1 updated:', '', '| name | updated | sha |', '| --- | --- | --- |', '| ai | false | abc1234 |'].join('\n');
1601
+ const PKG_PLUGIN_UPDATE_UPDATED_OUTPUT = ['1 updated:', '', '| name | transport | updated | sha |', '| --- | --- | --- | --- |', '| ai | http | true | |'].join('\n');
1602
+ const PKG_PLUGIN_UPDATE_CURRENT_OUTPUT = ['1 updated:', '', '| name | transport | updated | sha |', '| --- | --- | --- | --- |', '| ai | exec | false | abc1234 |'].join('\n');
1595
1603
  const PKG_PLUGIN_UPDATE_MULTI_OUTPUT = [
1596
1604
  '3 updated:',
1597
1605
  '',
1598
- '| name | updated | sha |',
1599
- '| --- | --- | --- |',
1600
- '| ai | true | aaa1111 |',
1601
- '| beta | false | bbb2222 |',
1602
- '| gamma | true | ccc3333 |',
1606
+ '| name | transport | updated | sha |',
1607
+ '| --- | --- | --- | --- |',
1608
+ '| ai | exec | true | aaa1111 |',
1609
+ '| beta | exec | false | bbb2222 |',
1610
+ '| gamma | http | true | |',
1603
1611
  ].join('\n');
1604
- test('a crtr pkg plugin update card collapses to an updated/current status + sha, not the raw table', () => {
1612
+ test('a crtr pkg plugin update card collapses to an updated/current transport-aware status + sha, not the raw table', () => {
1605
1613
  const def = createCrtrBashToolDefinition({ command: 'crtr pkg plugin update --name ai' });
1606
1614
  const collapsed = def
1607
1615
  .renderResult({ content: [{ type: 'text', text: PKG_PLUGIN_UPDATE_UPDATED_OUTPUT }] }, { expanded: false }, theme, {})
1608
1616
  .render(140)
1609
1617
  .join('\n');
1610
- assert.match(collapsed, /<success>updated ai<\/success>/);
1611
- assert.match(collapsed, /<muted>def5678<\/muted>/);
1612
- assert.doesNotMatch(collapsed, /\| name \| updated \|/);
1618
+ assert.match(collapsed, /<success>refreshed ai<\/success>/);
1619
+ assert.match(collapsed, /<muted>http<\/muted>/);
1620
+ assert.doesNotMatch(collapsed, /\| name \| transport \| updated \|/);
1613
1621
  const expanded = def
1614
1622
  .renderResult({ content: [{ type: 'text', text: PKG_PLUGIN_UPDATE_UPDATED_OUTPUT }] }, { expanded: true }, theme, {})
1615
1623
  .render(140)
1616
1624
  .join('\n');
1617
- assert.match(expanded, /\| name \| updated \| sha \|/);
1625
+ assert.match(expanded, /\| name \| transport \| updated \| sha \|/);
1618
1626
  const current = def
1619
1627
  .renderResult({ content: [{ type: 'text', text: PKG_PLUGIN_UPDATE_CURRENT_OUTPUT }] }, { expanded: false }, theme, {})
1620
1628
  .render(140)
@@ -1626,7 +1634,7 @@ test('a crtr pkg plugin update card collapses to an updated/current status + sha
1626
1634
  .renderResult({ content: [{ type: 'text', text: PKG_PLUGIN_UPDATE_MULTI_OUTPUT }] }, { expanded: false }, theme, {})
1627
1635
  .render(140)
1628
1636
  .join('\n');
1629
- assert.match(multi, /2 updated · 1 already current/);
1637
+ assert.match(multi, /2 updated · 1 already current · 1 HTTP/);
1630
1638
  const empty = multiDef
1631
1639
  .renderResult({ content: [{ type: 'text', text: '0 updated.' }] }, { expanded: false }, theme, {})
1632
1640
  .render(140)
@@ -1638,11 +1646,11 @@ test('a crtr pkg plugin update card collapses to an updated/current status + sha
1638
1646
  const malformedUpdate = [
1639
1647
  '3 updated:',
1640
1648
  '',
1641
- '| name | updated | sha |',
1642
- '| --- | --- | --- |',
1643
- '| ai | true | aaa1111 |',
1644
- '| beta | maybe | bbb2222 |',
1645
- '| gamma | false | ccc3333 |',
1649
+ '| name | transport | updated | sha |',
1650
+ '| --- | --- | --- | --- |',
1651
+ '| ai | exec | true | aaa1111 |',
1652
+ '| beta | exec | maybe | bbb2222 |',
1653
+ '| gamma | http | false | |',
1646
1654
  ].join('\n');
1647
1655
  const malformed = multiDef
1648
1656
  .renderResult({ content: [{ type: 'text', text: malformedUpdate }] }, { expanded: false }, theme, {})
@@ -1655,11 +1663,11 @@ const PKG_PLUGIN_LIST_OUTPUT = [
1655
1663
  '',
1656
1664
  '3 items:',
1657
1665
  '',
1658
- '| name | scope | version | enabled | source_marketplace | path |',
1659
- '| --- | --- | --- | --- | --- | --- |',
1660
- '| ai | user | 0.7.1 | true | crouter-official-marketplace | /Users/silas/.crouter/plugins/ai |',
1661
- '| beta | user | 1.0.0 | false | crouter-official-marketplace | /Users/silas/.crouter/plugins/beta |',
1662
- '| gamma | project | 2.3.0 | true | custom-market | /Users/silas/Code/cli/crouter/.crouter/plugins/gamma |',
1666
+ '| name | scope | version | enabled | transport | source_marketplace | path |',
1667
+ '| --- | --- | --- | --- | --- | --- | --- |',
1668
+ '| ai | user | 0.7.1 | true | exec | crouter-official-marketplace | /Users/silas/.crouter/plugins/ai |',
1669
+ '| beta | user | 1.0.0 | false | | crouter-official-marketplace | /Users/silas/.crouter/plugins/beta |',
1670
+ '| gamma | project | 2.3.0 | true | http | custom-market | /Users/silas/Code/cli/crouter/.crouter/plugins/gamma |',
1663
1671
  ].join('\n');
1664
1672
  test('a crtr pkg plugin list card collapses to a plugin/enabled count + name digest, not the raw table', () => {
1665
1673
  const def = createCrtrBashToolDefinition({ command: 'crtr pkg plugin list' });
@@ -1668,13 +1676,13 @@ test('a crtr pkg plugin list card collapses to a plugin/enabled count + name dig
1668
1676
  .render(140)
1669
1677
  .join('\n');
1670
1678
  assert.match(collapsed, /3 plugins · 2 enabled/);
1671
- assert.match(collapsed, /<muted>ai, beta, gamma<\/muted>/);
1679
+ assert.match(collapsed, /<muted>ai \(exec\), beta, gamma \(http\)<\/muted>/);
1672
1680
  assert.doesNotMatch(collapsed, /\| name \| scope \|/);
1673
1681
  const expanded = def
1674
1682
  .renderResult({ content: [{ type: 'text', text: PKG_PLUGIN_LIST_OUTPUT }] }, { expanded: true }, theme, {})
1675
1683
  .render(140)
1676
1684
  .join('\n');
1677
- assert.match(expanded, /\| name \| scope \| version \|/);
1685
+ assert.match(expanded, /\| name \| scope \| version \| enabled \| transport \|/);
1678
1686
  const empty = def
1679
1687
  .renderResult({ content: [{ type: 'text', text: '- total: 0\n\n0 items.' }] }, { expanded: false }, theme, {})
1680
1688
  .render(140)
@@ -1693,7 +1701,8 @@ const PKG_PLUGIN_SHOW_OUTPUT = [
1693
1701
  '- scope: user',
1694
1702
  '- path: /Users/silas/.crouter/plugins/ai',
1695
1703
  '- enabled: true',
1696
- '- manifest: {"name":"ai","version":"0.7.1","description":"AI helpers"}',
1704
+ '- manifest: {"name":"ai","version":"0.7.1","description":"AI helpers","commands":"commands.json","transport":{"kind":"exec","executable":"bin/ai.js"}}',
1705
+ '- commands: {"manifestPath":"/Users/silas/.crouter/plugins/ai/commands.json","mounts":["ai"],"issues":[]}',
1697
1706
  '',
1698
1707
  '2 docs:',
1699
1708
  '',
@@ -1717,7 +1726,7 @@ test('a crtr pkg plugin show card collapses to a name@version + enabled status +
1717
1726
  .renderResult({ content: [{ type: 'text', text: PKG_PLUGIN_SHOW_OUTPUT }] }, { expanded: false }, theme, {})
1718
1727
  .render(140)
1719
1728
  .join('\n');
1720
- assert.match(collapsed, /<success>ai@0\.7\.1 · enabled<\/success>/);
1729
+ assert.match(collapsed, /<success>ai@0\.7\.1 · exec · enabled<\/success>/);
1721
1730
  assert.match(collapsed, /<muted>2 substrate docs<\/muted>/);
1722
1731
  assert.doesNotMatch(collapsed, /\| name \| path \|/);
1723
1732
  const expanded = def
@@ -1,9 +1,7 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import test from 'node:test';
3
- import { initTheme } from '@earendil-works/pi-coding-agent';
4
- import { FOLDED_STATE_KEY } from '../render/tool-calls.js';
5
3
  import { createCrtrEditToolDefinition } from '../render/edit-diff.js';
6
- initTheme(undefined, false);
4
+ import { FoldedToolCallController } from '../render/tool-calls.js';
7
5
  const theme = {
8
6
  fg: (_name, text) => text,
9
7
  bg: (_name, text) => text,
@@ -12,23 +10,26 @@ const theme = {
12
10
  getBgAnsi: (_name) => '',
13
11
  getColorMode: () => 'truecolor',
14
12
  };
15
- test('folded edit counts keep the executed diff when its speculative preview settles later', () => {
16
- const definition = createCrtrEditToolDefinition(process.cwd());
17
- const args = { path: 'example.ts', edits: [{ oldText: 'before', newText: 'after' }] };
18
- const state = {};
19
- const context = {
20
- args,
21
- argsComplete: false,
22
- cwd: process.cwd(),
23
- invalidate() { },
13
+ test('edit cards stream argument diffs, then keep the executed result authoritative', () => {
14
+ const fold = new FoldedToolCallController();
15
+ const view = createCrtrEditToolDefinition(process.cwd(), fold);
16
+ const definition = view.definition;
17
+ const context = { cwd: process.cwd(), isError: false };
18
+ const streamedArgs = { path: 'example.ts', edits: [{ oldText: 'before', newText: 'streaming' }] };
19
+ const streamed = definition.renderCall(streamedArgs, theme, context).render(80).join('\n');
20
+ assert.match(streamed, /before/);
21
+ assert.match(streamed, /streaming/);
22
+ view.observeResult({
23
+ content: [{ type: 'text', text: 'edited' }],
24
+ details: { diff: '-10 before\n+10 executed\n+11 extra' },
24
25
  isError: false,
25
- state,
26
- };
27
- definition.renderCall(args, theme, context);
28
- definition.renderResult({ content: [{ type: 'text', text: 'edited' }], details: { diff: '- 1 before\n+ 1 after' } }, { isPartial: false }, theme, context);
29
- state.callComponent.preview = { error: 'speculative preview completed after execution' };
30
- state[FOLDED_STATE_KEY] = true;
31
- const folded = definition.renderCall(args, theme, context).render(80).join('\n');
32
- assert.match(folded, /\+1/);
26
+ }, false);
27
+ const laterArgs = { path: 'example.ts', edits: [{ oldText: 'before', newText: 'stale preview' }] };
28
+ const settled = definition.renderCall(laterArgs, theme, context).render(80).join('\n');
29
+ assert.match(settled, /executed/);
30
+ assert.doesNotMatch(settled, /stale preview/);
31
+ fold.setFolded(true);
32
+ const folded = definition.renderCall(laterArgs, theme, context).render(80).join('\n');
33
+ assert.match(folded, /\+2/);
33
34
  assert.match(folded, /-1/);
34
35
  });
@@ -25,12 +25,12 @@ export interface ChatViewOptions {
25
25
  * the module defaults (faint + ANSI red) are used. */
26
26
  palette?: AttachPalette;
27
27
  /** Trailing refresh-yield cycles rendered at full fidelity; older cycles are
28
- * condensed to prose and frozen (see frozen-history.ts). Absent → the user's
29
- * `live_cycles` config setting, itself defaulting to 2. */
28
+ * condensed to lightweight, reflowing content (see condensed-history.ts).
29
+ * Absent → the user's `live_cycles` config setting, itself defaulting to 2. */
30
30
  liveCycles?: number;
31
- /** Which messages of a condensed cycle survive into the frozen block. Absent →
32
- * the user's `condensed_history` config setting, itself defaulting to `none`
33
- * (cycle dividers only). */
31
+ /** Which messages of a condensed cycle survive into the condensed region.
32
+ * Absent → the user's `condensed_history` config setting, itself defaulting
33
+ * to `none` (cycle dividers only). */
34
34
  condensedHistory?: CondensedHistoryMode;
35
35
  /** Pre-colored banner lines pinned as the FIRST child of the chat container,
36
36
  * above history (the crouton wordmark). Sits at the very top of the transcript
@@ -47,8 +47,8 @@ export declare class ChatView {
47
47
  /** Activity/status area below history. Holds working/compaction/retry loaders. */
48
48
  private readonly statusContainer;
49
49
  /** Where `append()` puts a component. Normally `historyContainer`; retargeted to
50
- * a scratch container while a frozen block is being built, so the very same
51
- * message-rendering path serves both. */
50
+ * a nested container while condensed history is being built, so the same
51
+ * message-rendering path serves both regions. */
52
52
  private appendTarget;
53
53
  /** Trailing cycles kept at full fidelity (config `live_cycles`). */
54
54
  private readonly liveCycles;
@@ -114,17 +114,17 @@ export declare class ChatView {
114
114
  * reflow-on-resize is automatic — no scrollback reconstruction needed. */
115
115
  applySnapshot(snapshot: BrokerSnapshot): Promise<void>;
116
116
  /**
117
- * Render the condensed form of the already-finished cycles ONCE and hand back a
118
- * frozen line block (or undefined when nothing survived condensation).
117
+ * Build the condensed form of the already-finished cycles as a nested component
118
+ * container, or return undefined when nothing survives condensation.
119
119
  *
120
- * Reuses `addMessageToChat` verbatim by retargeting `append()` at a scratch
121
- * container, so condensed history is styled exactly like live history — the same
122
- * renderer, with the tool traffic filtered out and the result flattened to text.
123
- * Yields on the same cadence as the live build so a very long history still lets
124
- * queued keystrokes through, and abandons itself when a newer welcome supersedes
125
- * this generation.
120
+ * Reuses `addMessageToChat` by retargeting `append()` at the nested container, so
121
+ * condensed history uses the same renderer as live history with tool traffic
122
+ * filtered out. The outer history cache keeps stable-width frames cheap, while
123
+ * preserving the components lets pane-width changes reflow their content. The
124
+ * build yields on the live cadence and abandons itself when a newer welcome
125
+ * supersedes this generation.
126
126
  */
127
- private buildFrozenBlock;
127
+ private buildCondensedBlock;
128
128
  /** Defer a live broker frame when a snapshot build is in flight. Returns true
129
129
  * (and enqueues the replay closure) while building so the caller returns
130
130
  * without mutating the half-rebuilt view; false when the caller may proceed.
@@ -141,8 +141,8 @@ export declare class ChatView {
141
141
  dispose(): void;
142
142
  /** Ctrl+O / app.tools.expand — flip global tool-output expansion and apply it to
143
143
  * every rendered component that supports it. Returns the new expanded state so
144
- * the caller can surface a notice. Condensed cycles hold no tool components and
145
- * are frozen as text, so they are unaffected by design. */
144
+ * the caller can surface a notice. Condensed cycles hold no tool components, so
145
+ * they are unaffected by design. */
146
146
  toggleToolsExpanded(): boolean;
147
147
  /** The `fold finished tool calls` view setting (`/fold-tools`, Alt+C → w → f).
148
148
  * Returns the new state so the caller can surface a notice. */
@@ -179,14 +179,14 @@ export declare class ChatView {
179
179
  /** Tool component with native viewer renderers for crouter-owned tool output. */
180
180
  private makeToolComponent;
181
181
  /** Append conversation content above the independent live status area — or into
182
- * the scratch container while a frozen block is under construction. */
182
+ * the nested container while condensed history is under construction. */
183
183
  private append;
184
184
  /** Approximate render width for inline mermaid diagrams. Only affects
185
185
  * termrender's trailing padding (stripped in the transform), so the terminal
186
186
  * column count is close enough without threading the live pane width here. */
187
187
  private renderWidth;
188
188
  /** Number of rendered conversation components in the container currently being
189
- * appended to (history, or the frozen block's scratch container). */
189
+ * appended to (live history or the nested condensed region). */
190
190
  private chatChildCount;
191
191
  /** Clear all chat content. */
192
192
  private resetChat;
@@ -26,21 +26,17 @@ import { attachMarkdownTheme } from '../config.js';
26
26
  import { ContextMessageComponent } from './context-message.js';
27
27
  import { CRTR_OUTPUT_CUSTOM_TYPE, CrtrOutputMessageComponent, createCrtrBashToolDefinition, } from './crtr-output.js';
28
28
  import { CRTR_CYCLE_DIVIDER_CUSTOM_TYPE } from '../../../core/runtime/session-cycles.js';
29
- import { SITUATIONAL_CONTEXT_CUSTOM_TYPE } from '../../../core/runtime/situational-context.js';
29
+ import { generatedContextPresentation } from '../../../shared/generated-context.js';
30
30
  import { transformMessageDiagrams } from './diagram.js';
31
31
  import { styleAttachMarkdownHeadings, styleAttachMessageMarkdown, styleAttachSummaryMarkdown, } from './markdown-headings.js';
32
32
  import { createCrtrEditToolDefinition } from './edit-diff.js';
33
- import { FOLDED_STATE_KEY, createCrtrPlainBashToolDefinition, createCrtrReadToolDefinition, createCrtrWriteToolDefinition, } from './tool-calls.js';
33
+ import { FoldedToolCallController, createCrtrPlainBashToolDefinition, createCrtrReadToolDefinition, createCrtrWriteToolDefinition, } from './tool-calls.js';
34
34
  import { ringCompletionBell } from '../chrome/completion-bell.js';
35
35
  import { extractFilePaths } from '../visible-paths.js';
36
- import { FrozenHistoryComponent, keepWhenCondensed, liveRegionStart } from './frozen-history.js';
36
+ import { keepWhenCondensed, liveRegionStart } from './condensed-history.js';
37
37
  import { ViewerAssistantMessageComponent } from './assistant-message.js';
38
38
  import { readConfig, updateRawConfigAtomically } from '../../../core/config.js';
39
39
  import { DEFAULT_CONDENSED_HISTORY, DEFAULT_LIVE_CYCLES } from '../../../types.js';
40
- /** customType stamped on the injected `<crtr-context>` bearings block (mirrors
41
- * CONTEXT_INTRO_CUSTOM_TYPE in canvas-context-intro.ts — kept as a local literal
42
- * so the viewer never imports the in-process extension). */
43
- const CONTEXT_INTRO_CUSTOM_TYPE = 'crtr-context';
44
40
  /** Theme-derived chrome colors (spinner / dim / error) are supplied by the
45
41
  * attach command via `ChatViewOptions.palette` (built from the live theme in
46
42
  * config.ts). pi does not re-export the raw `theme` instance, so when no
@@ -147,13 +143,10 @@ function stripBackground(line) {
147
143
  });
148
144
  }
149
145
  /** A tool component that can fold itself down to its CALL. pi's `ToolExecutionComponent`
150
- * only knows expanded/collapsed, so the minimized state is crtr's — and the tool's own
151
- * renderCall owns its folded form: every crtr-owned definition (read/write/edit/bash)
152
- * reads the fold flag off its shared render-state bag and emits ONLY its one-line
153
- * `<icon> <tool> <path>` header while folded. Folded render then paints just the call
154
- * component (result and Box chrome dropped), so a wrapped path keeps its wrap rows
155
- * naturally — no measuring or slicing of rendered ANSI rows. Tools without a crtr
156
- * definition are not foldable and always render in full. */
146
+ * only knows expanded/collapsed, so each crtr-owned definition receives a local fold
147
+ * controller and captures the compact call component it renders. Folded render paints
148
+ * that captured call directly, dropping result and Box chrome while letting a wrapped
149
+ * path keep its natural rows. Tools without a crtr definition remain in full. */
157
150
  /** A one-line separator that appears only while its adjacent tool group is
158
151
  * folded. It stays in the transcript so toggling folded tools reflows the same
159
152
  * message/tool boundary without rebuilding the chat. */
@@ -174,30 +167,36 @@ class FoldedToolSeparator extends Spacer {
174
167
  }
175
168
  class MinimizableToolComponent extends ToolExecutionComponent {
176
169
  minimized = false;
177
- foldable = false;
178
- /** Only tools whose renderCall is fold-aware (the crtr-owned definitions) may
179
- * fold; chat-view marks them at construction. */
180
- setFoldable(foldable) {
181
- this.foldable = foldable;
170
+ expandedState = false;
171
+ foldController;
172
+ resultObserver;
173
+ /** A foldable definition owns its folded call component; an edit definition
174
+ * may also observe results before the imported shell renders them. */
175
+ setToolView(foldController, resultObserver) {
176
+ this.foldController = foldController;
177
+ this.resultObserver = resultObserver;
182
178
  }
183
- /** Flip the fold: expose it on the definitions' shared render-state bag, then
184
- * re-run `updateDisplay()` (the same path pi's own `setExpanded` uses) so the
185
- * fold-aware renderCall rebuilds the call component in its new form. NOT
186
- * `invalidate()` — pi's `ToolExecutionComponent.invalidate` recurses through
187
- * its renderer children and killed the viewer process. */
179
+ updateResult(...args) {
180
+ this.resultObserver?.(args[0], args[1] ?? false);
181
+ super.updateResult(...args);
182
+ }
183
+ setExpanded(expanded) {
184
+ this.expandedState = expanded;
185
+ super.setExpanded(expanded);
186
+ }
187
+ /** Flip the local fold state, then use the imported component's public
188
+ * expansion setter to rebuild its call renderer at the current setting. */
188
189
  setMinimized(minimized) {
189
- if (!this.foldable || this.minimized === minimized)
190
+ if (!this.foldController || this.minimized === minimized)
190
191
  return;
191
192
  this.minimized = minimized;
192
- const internals = this;
193
- internals.rendererState[FOLDED_STATE_KEY] = minimized;
194
- internals.updateDisplay();
193
+ this.foldController.setFolded(minimized);
194
+ super.setExpanded(this.expandedState);
195
195
  }
196
196
  render(width) {
197
197
  if (!this.minimized)
198
198
  return super.render(width);
199
- const call = this
200
- .callRendererComponent;
199
+ const call = this.foldController?.callComponent();
201
200
  if (!call)
202
201
  return super.render(width);
203
202
  // trimEnd drops right-hand padding, which only existed to carry the
@@ -254,8 +253,8 @@ export class ChatView {
254
253
  /** Activity/status area below history. Holds working/compaction/retry loaders. */
255
254
  statusContainer = new Container();
256
255
  /** Where `append()` puts a component. Normally `historyContainer`; retargeted to
257
- * a scratch container while a frozen block is being built, so the very same
258
- * message-rendering path serves both. */
256
+ * a nested container while condensed history is being built, so the same
257
+ * message-rendering path serves both regions. */
259
258
  appendTarget = this.historyContainer;
260
259
  /** Trailing cycles kept at full fidelity (config `live_cycles`). */
261
260
  liveCycles;
@@ -369,18 +368,18 @@ export class ChatView {
369
368
  const renderedPendingTools = new Map();
370
369
  const messages = snapshot.messages;
371
370
  const lastIndex = messages.length - 1;
372
- // Cycles older than the trailing `live_cycles` are condensed to prose and
373
- // frozen into one flat line block BEFORE the live region is built, so the loop
374
- // below only ever constructs components for the cycles you are actually
375
- // working in. `liveStart` is 0 — condense nothing — until the node has yielded
376
- // past the configured window, so a fresh node renders exactly as it always did.
371
+ // Cycles older than the trailing `live_cycles` are condensed into one nested
372
+ // container before the live region is built. It retains only configured prose
373
+ // and cycle seams, avoiding old tool components while still reflowing on pane
374
+ // resize. `liveStart` is 0 until the node has yielded past the configured
375
+ // window, so a fresh node renders at full fidelity.
377
376
  const liveStart = liveRegionStart(messages, this.liveCycles);
378
377
  if (liveStart > 0) {
379
- const frozen = await this.buildFrozenBlock(messages.slice(0, liveStart), generation);
378
+ const condensed = await this.buildCondensedBlock(messages.slice(0, liveStart), generation);
380
379
  if (generation !== this.snapshotGeneration)
381
380
  return;
382
- if (frozen)
383
- this.append(frozen);
381
+ if (condensed)
382
+ this.append(condensed);
384
383
  }
385
384
  for (let i = liveStart; i < messages.length; i++) {
386
385
  // Yield to the event loop every SNAPSHOT_YIELD_EVERY messages so queued
@@ -480,20 +479,20 @@ export class ChatView {
480
479
  this.replayDeferredFrames();
481
480
  }
482
481
  /**
483
- * Render the condensed form of the already-finished cycles ONCE and hand back a
484
- * frozen line block (or undefined when nothing survived condensation).
482
+ * Build the condensed form of the already-finished cycles as a nested component
483
+ * container, or return undefined when nothing survives condensation.
485
484
  *
486
- * Reuses `addMessageToChat` verbatim by retargeting `append()` at a scratch
487
- * container, so condensed history is styled exactly like live history — the same
488
- * renderer, with the tool traffic filtered out and the result flattened to text.
489
- * Yields on the same cadence as the live build so a very long history still lets
490
- * queued keystrokes through, and abandons itself when a newer welcome supersedes
491
- * this generation.
485
+ * Reuses `addMessageToChat` by retargeting `append()` at the nested container, so
486
+ * condensed history uses the same renderer as live history with tool traffic
487
+ * filtered out. The outer history cache keeps stable-width frames cheap, while
488
+ * preserving the components lets pane-width changes reflow their content. The
489
+ * build yields on the live cadence and abandons itself when a newer welcome
490
+ * supersedes this generation.
492
491
  */
493
- async buildFrozenBlock(messages, generation) {
494
- const scratch = new Container();
492
+ async buildCondensedBlock(messages, generation) {
493
+ const condensed = new Container();
495
494
  const previousTarget = this.appendTarget;
496
- this.appendTarget = scratch;
495
+ this.appendTarget = condensed;
497
496
  try {
498
497
  let built = 0;
499
498
  for (const message of messages) {
@@ -515,10 +514,7 @@ export class ChatView {
515
514
  finally {
516
515
  this.appendTarget = previousTarget;
517
516
  }
518
- const width = this.renderWidth();
519
- const lines = scratch.render(width);
520
- scratch.clear();
521
- return lines.length > 0 ? new FrozenHistoryComponent(lines, width) : undefined;
517
+ return condensed.children.length > 0 ? condensed : undefined;
522
518
  }
523
519
  /** Defer a live broker frame when a snapshot build is in flight. Returns true
524
520
  * (and enqueues the replay closure) while building so the caller returns
@@ -561,8 +557,8 @@ export class ChatView {
561
557
  // -------------------------------------------------------------------------
562
558
  /** Ctrl+O / app.tools.expand — flip global tool-output expansion and apply it to
563
559
  * every rendered component that supports it. Returns the new expanded state so
564
- * the caller can surface a notice. Condensed cycles hold no tool components and
565
- * are frozen as text, so they are unaffected by design. */
560
+ * the caller can surface a notice. Condensed cycles hold no tool components, so
561
+ * they are unaffected by design. */
566
562
  toggleToolsExpanded() {
567
563
  this.toolOutputExpanded = !this.toolOutputExpanded;
568
564
  this.applyToolDisplay();
@@ -724,7 +720,7 @@ export class ChatView {
724
720
  this.pendingTools.clear();
725
721
  }
726
722
  else {
727
- // Args complete → trigger diff computation for edit tools.
723
+ // Finalize renderer caches now that every tool argument is complete.
728
724
  for (const component of this.pendingTools.values()) {
729
725
  component.setArgsComplete();
730
726
  this.historyContainer.markDirty(component);
@@ -867,6 +863,20 @@ export class ChatView {
867
863
  // Rebuild path (ports addMessageToChat, interactive-mode.js:2483).
868
864
  // -------------------------------------------------------------------------
869
865
  addMessageToChat(message) {
866
+ // Crouter-generated context retains its runtime role (user vs custom) so
867
+ // delivery to the model is unchanged, but every attached view presents it
868
+ // through one compact disclosure contract. The shared classifier uses the
869
+ // producers' exact custom types/sentinels, so ordinary user prompts cannot
870
+ // accidentally acquire this treatment and saved transcripts gain it too.
871
+ const generated = generatedContextPresentation(message);
872
+ if (generated !== null &&
873
+ (message.role !== 'custom' || message.display === true)) {
874
+ this.pushTranscriptText(generated.body);
875
+ if (message.role === 'user' && this.chatChildCount() > 0)
876
+ this.append(new Spacer(1));
877
+ this.append(new ContextMessageComponent(generated.body, this.toolOutputExpanded, this.dimStyle, (s) => this.spinnerStyle(this.labelStyle(s)), generated.label, ` ${generated.summary} — ctrl+o to expand`));
878
+ return;
879
+ }
870
880
  switch (message.role) {
871
881
  case 'bashExecution': {
872
882
  this.pushTranscriptText(message.output ?? '');
@@ -885,25 +895,6 @@ export class ChatView {
885
895
  case 'custom': {
886
896
  if (message.display) {
887
897
  this.pushTranscriptText(this.userMessageText(message));
888
- // The <crtr-context> bearings block folds to a one-liner under Ctrl+O
889
- // (the broker runs its renderer extension, so reimplement it natively).
890
- if (message.customType === CONTEXT_INTRO_CUSTOM_TYPE) {
891
- this.append(new ContextMessageComponent(this.userMessageText(message), this.toolOutputExpanded, this.dimStyle,
892
- // Bold + active accent, so the [crtr context] label reads as a
893
- // distinct color against the dim rest of the line.
894
- (s) => this.spinnerStyle(this.labelStyle(s))));
895
- break;
896
- }
897
- // The hidden ambient `<situational-context>` update (canvas-inbox-watcher's
898
- // ~non-birth wake path). Rendered collapsed exactly like `crtr-context`
899
- // (same component, distinct label) so an existing-node ambient update is
900
- // never more prominent in the transcript than the bearings block it rides
901
- // alongside on fresh birth — the LLM sees the full content either way; only
902
- // the viewer's display treatment differs.
903
- if (message.customType === SITUATIONAL_CONTEXT_CUSTOM_TYPE) {
904
- this.append(new ContextMessageComponent(this.userMessageText(message), this.toolOutputExpanded, this.dimStyle, (s) => this.spinnerStyle(this.labelStyle(s)), 'situational context', ' ambient context update — ctrl+o to expand'));
905
- break;
906
- }
907
898
  if (message.customType === CRTR_OUTPUT_CUSTOM_TYPE) {
908
899
  this.append(new CrtrOutputMessageComponent(this.userMessageText(message), this.toolOutputExpanded, this.crtrOutputTheme()));
909
900
  break;
@@ -1020,23 +1011,31 @@ export class ChatView {
1020
1011
  }
1021
1012
  /** Tool component with native viewer renderers for crouter-owned tool output. */
1022
1013
  makeToolComponent(name, id, args) {
1023
- const toolDefinition = name === 'bash'
1024
- ? (createCrtrBashToolDefinition(args) ?? createCrtrPlainBashToolDefinition(this.cwd))
1025
- : name === 'edit'
1026
- ? createCrtrEditToolDefinition(this.cwd)
1027
- : name === 'read'
1028
- ? createCrtrReadToolDefinition(this.cwd)
1029
- : name === 'write'
1030
- ? createCrtrWriteToolDefinition(this.cwd)
1031
- : undefined;
1014
+ const fold = new FoldedToolCallController();
1015
+ let resultObserver;
1016
+ let toolDefinition;
1017
+ if (name === 'bash') {
1018
+ toolDefinition = createCrtrBashToolDefinition(args, fold) ?? createCrtrPlainBashToolDefinition(this.cwd, fold);
1019
+ }
1020
+ else if (name === 'edit') {
1021
+ const edit = createCrtrEditToolDefinition(this.cwd, fold);
1022
+ toolDefinition = edit.definition;
1023
+ resultObserver = edit.observeResult;
1024
+ }
1025
+ else if (name === 'read') {
1026
+ toolDefinition = createCrtrReadToolDefinition(this.cwd, fold);
1027
+ }
1028
+ else if (name === 'write') {
1029
+ toolDefinition = createCrtrWriteToolDefinition(this.cwd, fold);
1030
+ }
1032
1031
  let component;
1033
1032
  component = new MinimizableToolComponent(name, id, args, { showImages: this.showImages, imageWidthCells: this.imageWidthCells }, toolDefinition, this.componentTui(() => component), this.cwd);
1034
- component.setFoldable(toolDefinition !== undefined);
1033
+ component.setToolView(toolDefinition === undefined ? undefined : fold, resultObserver);
1035
1034
  component.setExpanded(this.toolOutputExpanded);
1036
1035
  return component;
1037
1036
  }
1038
1037
  /** Append conversation content above the independent live status area — or into
1039
- * the scratch container while a frozen block is under construction. */
1038
+ * the nested container while condensed history is under construction. */
1040
1039
  append(child) {
1041
1040
  this.appendTarget.addChild(child);
1042
1041
  }
@@ -1047,7 +1046,7 @@ export class ChatView {
1047
1046
  return Math.max(40, process.stdout.columns ?? 80);
1048
1047
  }
1049
1048
  /** Number of rendered conversation components in the container currently being
1050
- * appended to (history, or the frozen block's scratch container). */
1049
+ * appended to (live history or the nested condensed region). */
1051
1050
  chatChildCount() {
1052
1051
  return this.appendTarget.children.length;
1053
1052
  }
@@ -1,4 +1,3 @@
1
- import { type Component } from '@earendil-works/pi-tui';
2
1
  import type { CondensedHistoryMode } from '../../../types.js';
3
2
  /** A message from the broker snapshot, structurally. */
4
3
  type Message = {
@@ -6,7 +5,7 @@ type Message = {
6
5
  customType?: string;
7
6
  };
8
7
  export declare function isCycleDivider(message: Message): boolean;
9
- /** Does this message survive condensation into the frozen block? */
8
+ /** Does this message survive into the condensed region? */
10
9
  export declare function keepWhenCondensed(message: Message, mode: CondensedHistoryMode): boolean;
11
10
  /**
12
11
  * Index into `messages` at which the LIVE (fully rendered) region begins.
@@ -19,20 +18,4 @@ export declare function keepWhenCondensed(message: Message, mode: CondensedHisto
19
18
  * single-yield node renders exactly as it always did.
20
19
  */
21
20
  export declare function liveRegionStart(messages: readonly Message[], liveCycles: number): number;
22
- /**
23
- * A settled block of pre-rendered transcript lines. Renders in O(1) at the width
24
- * it was frozen at, and clips (never reflows) when the pane is narrower. Ctrl+O /
25
- * Ctrl+T do not reach it: it holds no components to expand, only text.
26
- */
27
- export declare class FrozenHistoryComponent implements Component {
28
- private readonly lines;
29
- private readonly frozenWidth;
30
- /** Last clip result, so a stable narrow pane clips once rather than per frame. */
31
- private clipped;
32
- constructor(lines: readonly string[], frozenWidth: number);
33
- get lineCount(): number;
34
- /** Nothing to recompute — the block is text, already laid out. */
35
- invalidate(): void;
36
- render(width: number): string[];
37
- }
38
21
  export {};