@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.
- package/dist/build-root.d.ts +6 -6
- package/dist/build-root.js +12 -13
- package/dist/builtin-memory/00-runtime-base.md +3 -4
- package/dist/builtin-memory/01-spine/01-no-manager.md +1 -1
- package/dist/builtin-memory/02-lifecycle/00-terminal.md +2 -0
- package/dist/builtin-memory/04-orchestration-kernel.md +16 -18
- package/dist/builtin-memory/05-kinds/advisor/00-base.md +0 -2
- package/dist/builtin-memory/05-kinds/advisor/01-orchestrator.md +3 -9
- package/dist/builtin-memory/05-kinds/developer/00-base.md +1 -3
- package/dist/builtin-memory/05-kinds/developer/01-orchestrator.md +2 -10
- package/dist/builtin-memory/05-kinds/explore/00-base.md +2 -2
- package/dist/builtin-memory/05-kinds/explore/01-orchestrator.md +0 -2
- package/dist/builtin-memory/05-kinds/general/00-base.md +3 -5
- package/dist/builtin-memory/05-kinds/general/01-orchestrator.md +0 -4
- package/dist/builtin-memory/05-kinds/plan/01-orchestrator.md +1 -3
- package/dist/builtin-memory/05-kinds/plan/reviewers/00-base.md +12 -0
- package/dist/builtin-memory/05-kinds/plan/reviewers/architecture-fit.md +0 -2
- package/dist/builtin-memory/05-kinds/plan/reviewers/code-smells.md +0 -2
- package/dist/builtin-memory/05-kinds/plan/reviewers/pattern-consistency.md +0 -2
- package/dist/builtin-memory/05-kinds/plan/reviewers/requirements-coverage.md +1 -1
- package/dist/builtin-memory/05-kinds/plan/reviewers/security.md +0 -2
- package/dist/builtin-memory/05-kinds/review/00-base.md +0 -2
- package/dist/builtin-memory/05-kinds/review/01-orchestrator.md +1 -3
- package/dist/builtin-memory/05-kinds/spec/00-base.md +1 -1
- package/dist/builtin-memory/05-kinds/spec/01-orchestrator.md +2 -4
- package/dist/builtin-memory/05-kinds/spec/requirements.md +1 -1
- package/dist/builtin-memory/advisor/council.md +40 -0
- package/dist/builtin-memory/design.md +8 -11
- package/dist/builtin-memory/development.md +6 -9
- package/dist/builtin-memory/internal/INDEX.md +5 -5
- package/dist/builtin-memory/internal/agent-shaping.md +5 -7
- package/dist/builtin-memory/internal/examples/imessage-assistant.md +3 -3
- package/dist/builtin-memory/internal/marketplaces.md +13 -14
- package/dist/builtin-memory/internal/memory-loading.md +45 -0
- package/dist/builtin-memory/internal/nodes-and-canvas.md +4 -4
- package/dist/builtin-memory/internal/plugins.md +61 -45
- package/dist/builtin-memory/planning.md +4 -7
- package/dist/builtin-memory/spec.md +9 -12
- package/dist/builtin-memory/wedged-child-on-runaway-bash.md +8 -22
- package/dist/cli.js +1 -1
- package/dist/clients/attach/__tests__/attach-keybindings.test.js +17 -4
- package/dist/clients/attach/__tests__/context-message.test.js +31 -20
- package/dist/clients/attach/__tests__/crtr-output-coverage.test.js +1 -1
- package/dist/clients/attach/__tests__/crtr-output.test.js +39 -30
- package/dist/clients/attach/__tests__/edit-diff.test.js +21 -20
- package/dist/clients/attach/render/chat-view.d.ts +20 -20
- package/dist/clients/attach/render/chat-view.js +88 -89
- package/dist/clients/attach/render/{frozen-history.d.ts → condensed-history.d.ts} +1 -18
- package/dist/clients/attach/render/condensed-history.js +60 -0
- package/dist/clients/attach/render/context-message.js +9 -14
- package/dist/clients/attach/render/crtr-output.d.ts +2 -1
- package/dist/clients/attach/render/crtr-output.js +4 -4
- package/dist/clients/attach/render/edit-diff.d.ts +21 -6
- package/dist/clients/attach/render/edit-diff.js +90 -91
- package/dist/clients/attach/render/tool-calls.d.ts +14 -18
- package/dist/clients/attach/render/tool-calls.js +66 -41
- package/dist/clients/attach/session/bindings.d.ts +5 -3
- package/dist/clients/attach/session/bindings.js +7 -13
- package/dist/clients/attach/session/keys.d.ts +2 -0
- package/dist/clients/attach/session/keys.js +36 -37
- package/dist/clients/attach/session/profile-files.d.ts +8 -0
- package/dist/clients/attach/session/profile-files.js +157 -0
- package/dist/clients/attach/viewer.js +530 -528
- package/dist/commands/memory/lint.js +1 -1
- package/dist/commands/memory/write.js +1 -1
- package/dist/commands/node.js +2 -2
- package/dist/commands/pkg/plugin-inspect.js +6 -7
- package/dist/commands/pkg/plugin-manage.d.ts +1 -1
- package/dist/commands/pkg/plugin-manage.js +131 -19
- package/dist/commands/pkg/plugin.js +2 -2
- package/dist/commands/pkg.js +6 -11
- package/dist/commands/profile/env.js +3 -3
- package/dist/commands/sys/config.js +17 -76
- package/dist/commands/sys/doctor.js +5 -91
- package/dist/commands/sys/setup-wizard.d.ts +9 -11
- package/dist/commands/sys/setup-wizard.js +47 -81
- package/dist/core/__tests__/base-worker-prompt.test.js +18 -21
- package/dist/core/__tests__/command-plugins-surfaces.test.js +39 -5
- package/dist/core/__tests__/command-plugins.test.js +36 -16
- package/dist/core/__tests__/review-model-floor.test.js +2 -2
- package/dist/core/__tests__/tmux-surface.test.js +10 -1
- package/dist/core/command-manifests/manifest.d.ts +24 -0
- package/dist/core/{configured-clis → command-manifests}/manifest.js +21 -25
- package/dist/core/command-manifests/registry.d.ts +1 -2
- package/dist/core/command-manifests/registry.js +2 -2
- package/dist/core/command-manifests/schema.d.ts +11 -13
- package/dist/core/command-manifests/schema.js +53 -192
- package/dist/core/command-plugins/compose.d.ts +0 -6
- package/dist/core/command-plugins/compose.js +28 -75
- package/dist/core/command-plugins/discovery.d.ts +25 -58
- package/dist/core/command-plugins/discovery.js +152 -259
- package/dist/core/command-plugins/endpoint.d.ts +24 -0
- package/dist/core/command-plugins/endpoint.js +48 -0
- package/dist/core/command-plugins/store.d.ts +16 -0
- package/dist/core/command-plugins/store.js +64 -0
- package/dist/core/command-plugins/{adapter.d.ts → transport/exec-invoke.d.ts} +3 -3
- package/dist/core/command-plugins/{adapter.js → transport/exec-invoke.js} +4 -4
- package/dist/core/{configured-clis/fetch.d.ts → command-plugins/transport/http-fetch.d.ts} +9 -18
- package/dist/core/{configured-clis/fetch.js → command-plugins/transport/http-fetch.js} +15 -35
- package/dist/core/{configured-clis/invoker.d.ts → command-plugins/transport/http-invoke.d.ts} +7 -7
- package/dist/core/{configured-clis/invoker.js → command-plugins/transport/http-invoke.js} +21 -23
- package/dist/core/command.d.ts +8 -9
- package/dist/core/command.js +6 -9
- package/dist/core/config.js +6 -10
- package/dist/core/env-name.d.ts +6 -0
- package/dist/core/env-name.js +9 -0
- package/dist/core/io.d.ts +1 -1
- package/dist/core/keybindings/__tests__/resolve.test.js +40 -3
- package/dist/core/keybindings/attach-control.d.ts +37 -0
- package/dist/core/keybindings/attach-control.js +38 -0
- package/dist/core/keybindings/catalog.d.ts +5 -4
- package/dist/core/keybindings/catalog.js +16 -8
- package/dist/core/keybindings/index.d.ts +1 -0
- package/dist/core/keybindings/index.js +1 -0
- package/dist/core/keybindings/types.d.ts +1 -1
- package/dist/core/preview-registry.js +41 -74
- package/dist/core/runtime/bearings.d.ts +2 -5
- package/dist/core/runtime/bearings.js +2 -5
- package/dist/core/runtime/front-door.d.ts +1 -1
- package/dist/core/runtime/front-door.js +2 -2
- package/dist/core/runtime/kickoff.d.ts +3 -3
- package/dist/core/runtime/kickoff.js +4 -3
- package/dist/core/runtime/situational-context.d.ts +1 -1
- package/dist/core/runtime/situational-context.js +1 -1
- package/dist/core/runtime/spawn.js +9 -9
- package/dist/core/runtime/tmux.js +29 -2
- package/dist/core/scope.d.ts +0 -5
- package/dist/core/scope.js +0 -10
- package/dist/core/user-settings.d.ts +193 -0
- package/dist/core/user-settings.js +252 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/pi-extensions/canvas-stophook.js +3 -2
- package/dist/pi-extensions/canvas-tool-guide.js +4 -1
- package/dist/shared/generated-context.d.ts +34 -0
- package/dist/shared/generated-context.js +98 -0
- package/dist/types.d.ts +23 -16
- package/dist/types.js +3 -14
- package/dist/web-client/assets/{index-NIuSCOHM.js → index-BMTOGuOZ.js} +19 -19
- package/dist/web-client/assets/index-DvA6Zw-R.css +2 -0
- package/dist/web-client/index.html +2 -2
- package/dist/web-client/sw.js +1 -1
- package/docs/public-api.md +1 -0
- package/package.json +2 -2
- package/runtime.lock.json +6 -6
- package/dist/builtin-memory/05-kinds/product/00-base.md +0 -25
- package/dist/builtin-memory/05-kinds/product/01-orchestrator.md +0 -15
- package/dist/builtin-memory/05-kinds/product/teardown.md +0 -15
- package/dist/builtin-memory/internal/workflow-codification.md +0 -82
- package/dist/builtin-memory/product.md +0 -80
- package/dist/clients/attach/render/frozen-history.js +0 -100
- package/dist/commands/pkg/cli-inspect.d.ts +0 -17
- package/dist/commands/pkg/cli-inspect.js +0 -190
- package/dist/commands/pkg/cli-manage.d.ts +0 -3
- package/dist/commands/pkg/cli-manage.js +0 -206
- package/dist/commands/pkg/cli.d.ts +0 -1
- package/dist/commands/pkg/cli.js +0 -14
- package/dist/core/configured-clis/cache.d.ts +0 -16
- package/dist/core/configured-clis/cache.js +0 -57
- package/dist/core/configured-clis/compose.d.ts +0 -14
- package/dist/core/configured-clis/compose.js +0 -60
- package/dist/core/configured-clis/discovery.d.ts +0 -47
- package/dist/core/configured-clis/discovery.js +0 -173
- package/dist/core/configured-clis/manifest.d.ts +0 -24
- package/dist/core/configured-clis/registration.d.ts +0 -40
- package/dist/core/configured-clis/registration.js +0 -201
- 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 = [
|
|
1572
|
-
|
|
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 |
|
|
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 |
|
|
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>
|
|
1611
|
-
assert.match(collapsed, /<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 |
|
|
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
|
-
|
|
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('
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
19
|
-
const context = {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
26
|
-
};
|
|
27
|
-
definition.renderCall(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const folded = definition.renderCall(
|
|
32
|
-
assert.match(folded, /\+
|
|
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
|
|
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
|
|
32
|
-
* the user's `condensed_history` config setting, itself defaulting
|
|
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
|
|
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
|
-
*
|
|
118
|
-
*
|
|
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`
|
|
121
|
-
*
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
*
|
|
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
|
|
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
|
|
145
|
-
*
|
|
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
|
|
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
|
|
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 {
|
|
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 {
|
|
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 {
|
|
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
|
|
151
|
-
*
|
|
152
|
-
*
|
|
153
|
-
*
|
|
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
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
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.
|
|
190
|
+
if (!this.foldController || this.minimized === minimized)
|
|
190
191
|
return;
|
|
191
192
|
this.minimized = minimized;
|
|
192
|
-
|
|
193
|
-
|
|
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
|
|
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
|
|
373
|
-
//
|
|
374
|
-
//
|
|
375
|
-
//
|
|
376
|
-
//
|
|
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
|
|
378
|
+
const condensed = await this.buildCondensedBlock(messages.slice(0, liveStart), generation);
|
|
380
379
|
if (generation !== this.snapshotGeneration)
|
|
381
380
|
return;
|
|
382
|
-
if (
|
|
383
|
-
this.append(
|
|
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
|
-
*
|
|
484
|
-
*
|
|
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`
|
|
487
|
-
*
|
|
488
|
-
*
|
|
489
|
-
*
|
|
490
|
-
*
|
|
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
|
|
494
|
-
const
|
|
492
|
+
async buildCondensedBlock(messages, generation) {
|
|
493
|
+
const condensed = new Container();
|
|
495
494
|
const previousTarget = this.appendTarget;
|
|
496
|
-
this.appendTarget =
|
|
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
|
-
|
|
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
|
|
565
|
-
*
|
|
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
|
-
//
|
|
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
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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 {};
|