@north-light/crouter 0.3.318 → 0.3.320
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/README.md +0 -3
- package/dist/api/client.js +2 -912
- package/dist/api/dto/attach.js +0 -13
- package/dist/api/dto/bash-jobs.js +1 -9
- package/dist/api/dto/broker-ops.js +0 -6
- package/dist/api/dto/broker.js +0 -20
- package/dist/api/dto/canvas.js +0 -2
- package/dist/api/dto/chat-inventory.js +0 -11
- package/dist/api/dto/common.js +1 -15
- package/dist/api/dto/config.js +0 -3
- package/dist/api/dto/crons.js +1 -10
- package/dist/api/dto/files.js +0 -7
- package/dist/api/dto/focus.js +0 -10
- package/dist/api/dto/health.js +0 -2
- package/dist/api/dto/human-requests.js +0 -4
- package/dist/api/dto/human.js +0 -4
- package/dist/api/dto/inbox.js +0 -4
- package/dist/api/dto/lifecycle.js +0 -3
- package/dist/api/dto/mail.js +0 -1
- package/dist/api/dto/memory.js +0 -6
- package/dist/api/dto/messages.js +0 -2
- package/dist/api/dto/model-config.js +0 -1
- package/dist/api/dto/modelauth.js +0 -4
- package/dist/api/dto/node-outcomes.js +0 -2
- package/dist/api/dto/nodes.js +0 -3
- package/dist/api/dto/profiles.js +1 -4
- package/dist/api/dto/recovery.js +0 -1
- package/dist/api/dto/reports.js +0 -2
- package/dist/api/dto/review-comments.js +0 -5
- package/dist/api/dto/reviews.js +0 -5
- package/dist/api/dto/subscriptions.js +0 -2
- package/dist/api/dto/worktree.js +0 -6
- package/dist/api/errors.js +1 -40
- package/dist/api/index.js +1 -33
- package/dist/api/plugin-manifest-schema.js +0 -23
- package/dist/api/routes.js +1 -147
- package/dist/build-root.js +1 -198
- package/dist/cli.js +3 -99
- package/dist/clients/attach/ansi-cells.js +1 -137
- package/dist/clients/attach/chrome/bash-jobs.js +1 -31
- package/dist/clients/attach/chrome/canvas-panels.js +1 -194
- package/dist/clients/attach/chrome/completion-bell.js +1 -89
- package/dist/clients/attach/chrome/cron-wait.js +1 -34
- package/dist/clients/attach/chrome/git-info.js +2 -44
- package/dist/clients/attach/chrome/header.js +1 -30
- package/dist/clients/attach/chrome/inbox-strip.js +1 -199
- package/dist/clients/attach/chrome/recap.js +1 -19
- package/dist/clients/attach/chrome/review-wait.js +1 -22
- package/dist/clients/attach/chrome/roster.js +4 -275
- package/dist/clients/attach/chrome/status-line.js +1 -117
- package/dist/clients/attach/chrome/ticket-panel.js +1 -280
- package/dist/clients/attach/chrome/widgets.js +1 -51
- package/dist/clients/attach/command.js +1 -107
- package/dist/clients/attach/config.js +1 -274
- package/dist/clients/attach/input/capabilities.js +1 -104
- package/dist/clients/attach/input/clipboard-image.js +3 -220
- package/dist/clients/attach/input/completion-frecency.js +1 -141
- package/dist/clients/attach/input/controller.js +7 -377
- package/dist/clients/attach/input/overlay-owner.js +1 -199
- package/dist/clients/attach/input/ref-autocomplete.js +2 -176
- package/dist/clients/attach/input/titled-editor.js +4 -859
- package/dist/clients/attach/overlays/auth.js +2 -271
- package/dist/clients/attach/overlays/dialogs.js +2 -102
- package/dist/clients/attach/overlays/file-review.js +2 -128
- package/dist/clients/attach/overlays/graph.js +1 -661
- package/dist/clients/attach/overlays/help.js +1 -211
- package/dist/clients/attach/overlays/mcp.js +1 -302
- package/dist/clients/attach/overlays/pickers.js +1 -163
- package/dist/clients/attach/render/activity-slot.js +1 -13
- package/dist/clients/attach/render/assistant-message.js +1 -56
- package/dist/clients/attach/render/card-presentation.js +5 -218
- package/dist/clients/attach/render/chat-view.js +5 -1708
- package/dist/clients/attach/render/condensed-history.js +1 -60
- package/dist/clients/attach/render/context-message.js +1 -63
- package/dist/clients/attach/render/crtr-output.js +17 -905
- package/dist/clients/attach/render/diagram.js +7 -111
- package/dist/clients/attach/render/edit-diff.js +5 -304
- package/dist/clients/attach/render/glyph-codepoints.js +1 -42
- package/dist/clients/attach/render/group-activity.js +2 -263
- package/dist/clients/attach/render/group-recap.js +1 -152
- package/dist/clients/attach/render/markdown-source.js +5 -266
- package/dist/clients/attach/render/measured-container.js +1 -322
- package/dist/clients/attach/render/page-block.js +1 -183
- package/dist/clients/attach/render/scroll-animation.js +1 -80
- package/dist/clients/attach/render/tool-calls.js +3 -361
- package/dist/clients/attach/render/transcript-copy.js +2 -81
- package/dist/clients/attach/render/transcript-search.js +1 -152
- package/dist/clients/attach/render/viewport.js +1 -184
- package/dist/clients/attach/session/banner.js +1 -29
- package/dist/clients/attach/session/bindings.js +1 -71
- package/dist/clients/attach/session/chrome-refresh.js +1 -94
- package/dist/clients/attach/session/connection.js +1 -186
- package/dist/clients/attach/session/context.js +0 -16
- package/dist/clients/attach/session/editor-frame.js +1 -142
- package/dist/clients/attach/session/editor-inventory.js +6 -160
- package/dist/clients/attach/session/file-links.js +1 -68
- package/dist/clients/attach/session/focus-events.js +1 -12
- package/dist/clients/attach/session/frame.js +1 -214
- package/dist/clients/attach/session/frames.js +1 -188
- package/dist/clients/attach/session/identity.js +1 -26
- package/dist/clients/attach/session/input-wiring.js +1 -140
- package/dist/clients/attach/session/invariant.js +1 -15
- package/dist/clients/attach/session/keys.js +1 -77
- package/dist/clients/attach/session/layout.js +1 -59
- package/dist/clients/attach/session/mouse.js +1 -78
- package/dist/clients/attach/session/pane-focus.js +1 -42
- package/dist/clients/attach/session/pane-tag.js +1 -112
- package/dist/clients/attach/session/pi-assets.js +1 -24
- package/dist/clients/attach/session/pi-oauth-flows.js +1 -21
- package/dist/clients/attach/session/profile-files.js +1 -228
- package/dist/clients/attach/session/reconnect.js +1 -175
- package/dist/clients/attach/session/selection.js +3 -108
- package/dist/clients/attach/session/state-sync.js +1 -67
- package/dist/clients/attach/session/surface-frame.js +1 -73
- package/dist/clients/attach/session/surface-host.js +1 -255
- package/dist/clients/attach/session/teardown.js +5 -94
- package/dist/clients/attach/session/transcript-search.js +3 -151
- package/dist/clients/attach/session/whip-achievements.js +2 -145
- package/dist/clients/attach/session/whip.js +1 -362
- package/dist/clients/attach/slash/dispatch.js +1 -706
- package/dist/clients/attach/slash/prompt-preview.js +1 -121
- package/dist/clients/attach/viewer.js +441 -441
- package/dist/clients/conversation/projection.js +1 -324
- package/dist/clients/conversation/submit.js +1 -51
- package/dist/clients/inbox/controller.js +1 -701
- package/dist/clients/inbox/dto-adapt.js +1 -93
- package/dist/clients/inbox/layout.js +1 -9
- package/dist/clients/inbox/page-adapter.js +1 -55
- package/dist/clients/inbox/resolve.js +1 -35
- package/dist/clients/inbox/review/anchors.js +1 -89
- package/dist/clients/inbox/review/comments-client.js +1 -98
- package/dist/clients/inbox/review/companion-pane.js +1 -82
- package/dist/clients/inbox/review/document-surface.js +2 -1188
- package/dist/clients/inbox/review/frame.js +1 -216
- package/dist/clients/inbox/review/keys.js +1 -123
- package/dist/clients/inbox/review/launch.js +1 -151
- package/dist/clients/inbox/review/live-source.js +1 -160
- package/dist/clients/inbox/review/nvim.js +1 -44
- package/dist/clients/inbox/review/remap.js +1 -157
- package/dist/clients/inbox/review/review-client.js +1 -123
- package/dist/clients/inbox/review/roundtrip.js +3 -36
- package/dist/clients/inbox/review/state.js +4 -315
- package/dist/clients/inbox/review-adapter.js +1 -43
- package/dist/clients/inbox/surface.js +1 -152
- package/dist/clients/inbox/tui/ansi.js +3 -321
- package/dist/clients/inbox/tui/input.js +5 -392
- package/dist/clients/inbox/tui/keys.js +1 -104
- package/dist/clients/inbox/tui/page-body.js +1 -66
- package/dist/clients/inbox/tui/panel.js +1 -84
- package/dist/clients/inbox/tui/render.js +2 -368
- package/dist/clients/inbox/tui/slots.js +3 -134
- package/dist/clients/inbox/tui/types.js +0 -1
- package/dist/clients/inbox/tui.js +1 -86
- package/dist/clients/surfaces/host.js +0 -1
- package/dist/commands/api-client.js +4 -290
- package/dist/commands/attention.js +1 -215
- package/dist/commands/canvas-browse.js +1 -70
- package/dist/commands/canvas-config.js +2 -192
- package/dist/commands/canvas-history/grep.js +7 -85
- package/dist/commands/canvas-history/read.js +3 -50
- package/dist/commands/canvas-history/search.js +10 -99
- package/dist/commands/canvas-history/shared.js +1 -139
- package/dist/commands/canvas-history/stats.js +6 -68
- package/dist/commands/canvas-history.js +1 -32
- package/dist/commands/canvas-issue.js +14 -149
- package/dist/commands/canvas-prune.js +1 -108
- package/dist/commands/canvas-roster.js +1 -69
- package/dist/commands/canvas-snapshot.js +1 -34
- package/dist/commands/canvas-use.js +1 -61
- package/dist/commands/canvas.js +1 -49
- package/dist/commands/chord.js +1 -241
- package/dist/commands/cron.js +11 -534
- package/dist/commands/dashboard.js +1 -85
- package/dist/commands/human/components.js +3 -77
- package/dist/commands/human/feedback.js +1 -112
- package/dist/commands/human/prompts.js +1 -331
- package/dist/commands/human/queue.js +1 -191
- package/dist/commands/human/request.js +1 -266
- package/dist/commands/human/review.js +1 -288
- package/dist/commands/human/shared.js +1 -67
- package/dist/commands/human.js +4 -60
- package/dist/commands/memory/delete.js +1 -100
- package/dist/commands/memory/edit.js +21 -219
- package/dist/commands/memory/find.js +2 -244
- package/dist/commands/memory/history.js +5 -199
- package/dist/commands/memory/lint.js +1 -107
- package/dist/commands/memory/list.js +1 -142
- package/dist/commands/memory/move.js +1 -223
- package/dist/commands/memory/origin.js +1 -130
- package/dist/commands/memory/read.js +6 -232
- package/dist/commands/memory/shared.js +12 -802
- package/dist/commands/memory/write.js +13 -235
- package/dist/commands/memory.js +1 -30
- package/dist/commands/node/bash.js +5 -245
- package/dist/commands/node/create.js +3 -332
- package/dist/commands/node/inspect.js +12 -300
- package/dist/commands/node/lifecycle.js +2 -453
- package/dist/commands/node/message.js +1 -161
- package/dist/commands/node/outcome.js +4 -134
- package/dist/commands/node/pyramid.js +2 -79
- package/dist/commands/node/subscription.js +1 -78
- package/dist/commands/node/wait.js +7 -163
- package/dist/commands/node-context.js +2 -159
- package/dist/commands/node-inspect-artifacts.js +8 -109
- package/dist/commands/node-lifecycle-revive.js +1 -217
- package/dist/commands/node-snapshot.js +1 -37
- package/dist/commands/node-transcript.js +1 -62
- package/dist/commands/node-worktree.js +1 -138
- package/dist/commands/node.js +1 -29
- package/dist/commands/pkg/browse/actions.js +1 -198
- package/dist/commands/pkg/browse/catalog.js +1 -466
- package/dist/commands/pkg/browse/command-view.js +1 -191
- package/dist/commands/pkg/browse/detail-panel.js +1 -402
- package/dist/commands/pkg/browse/doc-view.js +1 -89
- package/dist/commands/pkg/browse/list-panel.js +2 -168
- package/dist/commands/pkg/browse/model.js +1 -36
- package/dist/commands/pkg/browse/shell.js +1 -640
- package/dist/commands/pkg/browse.js +1 -27
- package/dist/commands/pkg/market-inspect.js +1 -141
- package/dist/commands/pkg/market-manage.js +1 -327
- package/dist/commands/pkg/market.js +1 -14
- package/dist/commands/pkg/plugin-inspect.js +1 -168
- package/dist/commands/pkg/plugin-manage.js +17 -1109
- package/dist/commands/pkg/plugin.js +1 -14
- package/dist/commands/pkg/shared.js +1 -62
- package/dist/commands/pkg.js +1 -21
- package/dist/commands/profile/default.js +1 -139
- package/dist/commands/profile/delete.js +1 -66
- package/dist/commands/profile/env.js +3 -188
- package/dist/commands/profile/kind.js +2 -35
- package/dist/commands/profile/list.js +1 -43
- package/dist/commands/profile/meta.js +1 -67
- package/dist/commands/profile/new.js +1 -115
- package/dist/commands/profile/pause.js +1 -59
- package/dist/commands/profile/project.js +1 -113
- package/dist/commands/profile/rename.js +1 -38
- package/dist/commands/profile/show.js +1 -52
- package/dist/commands/profile.js +1 -35
- package/dist/commands/push.js +9 -265
- package/dist/commands/revive.js +10 -181
- package/dist/commands/surface/node/cycle.js +1 -83
- package/dist/commands/surface/node/focus.js +1 -81
- package/dist/commands/surface/node/id.js +1 -38
- package/dist/commands/surface/node/pin.js +1 -42
- package/dist/commands/surface/node/placement.js +1 -134
- package/dist/commands/surface-edit.js +1 -157
- package/dist/commands/surface-inbox.js +1 -98
- package/dist/commands/surface-inspect.js +1 -39
- package/dist/commands/surface-node.js +1 -19
- package/dist/commands/surface-reload.js +2 -134
- package/dist/commands/surface-tmux-spread.js +1 -214
- package/dist/commands/surface.js +1 -28
- package/dist/commands/sys/branch.js +1 -19
- package/dist/commands/sys/config.js +1 -353
- package/dist/commands/sys/context/admin/actions.js +2 -246
- package/dist/commands/sys/context/admin/detail-panel.js +1 -247
- package/dist/commands/sys/context/admin/docs-panel.js +1 -191
- package/dist/commands/sys/context/admin/list-view.js +1 -183
- package/dist/commands/sys/context/admin/model.js +1 -229
- package/dist/commands/sys/context/admin/rail-panel.js +1 -227
- package/dist/commands/sys/context/admin/read-view.js +2 -194
- package/dist/commands/sys/context/admin/shell.js +1 -910
- package/dist/commands/sys/context/admin.js +2 -126
- package/dist/commands/sys/context/doc.js +3 -197
- package/dist/commands/sys/context/prompt-review.js +11 -291
- package/dist/commands/sys/context/resolve.js +10 -489
- package/dist/commands/sys/context/sysprompt.js +5 -96
- package/dist/commands/sys/context.js +1 -20
- package/dist/commands/sys/daemon.js +1 -313
- package/dist/commands/sys/doctor.js +1 -617
- package/dist/commands/sys/feedback.js +7 -228
- package/dist/commands/sys/logs.js +3 -129
- package/dist/commands/sys/migrate.js +1 -94
- package/dist/commands/sys/panels/broker-limits-panel.js +2 -110
- package/dist/commands/sys/panels/dependencies-panel.js +1 -80
- package/dist/commands/sys/panels/keybindings-panel.js +1 -703
- package/dist/commands/sys/panels/models-panel.js +1 -1133
- package/dist/commands/sys/panels/plugins-panel.js +1 -80
- package/dist/commands/sys/panels/prefs-panel.js +1 -85
- package/dist/commands/sys/panels/profiles-panel.js +1 -601
- package/dist/commands/sys/panels/provider-panel.js +1 -538
- package/dist/commands/sys/settings-shell.js +1 -400
- package/dist/commands/sys/settings.js +1 -46
- package/dist/commands/sys/setup-core.js +6 -579
- package/dist/commands/sys/setup-settings-runner.js +1 -16
- package/dist/commands/sys/setup-wizard.js +1 -279
- package/dist/commands/sys/setup.js +1 -34
- package/dist/commands/sys/shared.js +1 -81
- package/dist/commands/sys/support/prepare.js +3 -239
- package/dist/commands/sys/support/submit.js +6 -524
- package/dist/commands/sys/support.js +1 -18
- package/dist/commands/sys/sync-deps.js +15 -498
- package/dist/commands/sys/sync-project-guidance.js +4 -481
- package/dist/commands/sys/sync-shared.js +1 -49
- package/dist/commands/sys/sync-skills.js +2 -311
- package/dist/commands/sys/sync.js +1 -18
- package/dist/commands/sys/update.js +1 -147
- package/dist/commands/sys/worktrees.js +5 -53
- package/dist/commands/sys.js +1 -18
- package/dist/core/activity-signal.js +2 -38
- package/dist/core/asset-root.js +1 -18
- package/dist/core/auth-file.js +2 -179
- package/dist/core/auth-interaction.js +3 -94
- package/dist/core/auto-update.js +4 -94
- package/dist/core/bash-guard.js +11 -393
- package/dist/core/bash-jobs.js +7 -411
- package/dist/core/bootstrap.js +2 -53
- package/dist/core/broker-client/client.js +1 -184
- package/dist/core/broker-client/index.js +1 -13
- package/dist/core/broker-client/transport-relay.js +1 -157
- package/dist/core/broker-client/transport-socket.js +1 -179
- package/dist/core/broker-client/transport.js +1 -26
- package/dist/core/canvas/attention.js +1 -47
- package/dist/core/canvas/boot-id.js +1 -26
- package/dist/core/canvas/boot.js +1 -186
- package/dist/core/canvas/browse/app.js +3 -919
- package/dist/core/canvas/browse/model.js +1 -477
- package/dist/core/canvas/browse/pins.js +1 -29
- package/dist/core/canvas/browse/render.js +3 -1055
- package/dist/core/canvas/canvas.js +15 -922
- package/dist/core/canvas/crons.js +11 -481
- package/dist/core/canvas/daemon-owner.js +2 -146
- package/dist/core/canvas/db.js +2 -100
- package/dist/core/canvas/deliveries.js +22 -283
- package/dist/core/canvas/delivery-contract.js +1 -8
- package/dist/core/canvas/executions.js +1 -68
- package/dist/core/canvas/extensions.js +1 -83
- package/dist/core/canvas/focuses.js +1 -77
- package/dist/core/canvas/history.js +24 -860
- package/dist/core/canvas/index.js +1 -15
- package/dist/core/canvas/install-id.js +1 -84
- package/dist/core/canvas/labels.js +1 -43
- package/dist/core/canvas/meta-file.js +1 -89
- package/dist/core/canvas/migrations.js +41 -1150
- package/dist/core/canvas/nav-model.js +1 -231
- package/dist/core/canvas/nav-render.js +1 -260
- package/dist/core/canvas/node-order.js +1 -37
- package/dist/core/canvas/node-recap.js +2 -67
- package/dist/core/canvas/node-sql-migration.js +2 -209
- package/dist/core/canvas/paths.js +1 -153
- package/dist/core/canvas/pid.js +4 -683
- package/dist/core/canvas/recovery.js +3 -565
- package/dist/core/canvas/remote-canvas-source.js +1 -288
- package/dist/core/canvas/remote-transport.js +1 -57
- package/dist/core/canvas/render-source.js +10 -635
- package/dist/core/canvas/sessions.js +1 -78
- package/dist/core/canvas/source.js +1 -47
- package/dist/core/canvas/status-glyph.js +1 -132
- package/dist/core/canvas/telemetry.js +1 -35
- package/dist/core/canvas/types.js +1 -6
- package/dist/core/canvas/waits.js +4 -68
- package/dist/core/canvas/worktrees.js +1 -93
- package/dist/core/clipboard-text.js +1 -57
- package/dist/core/command-hooks/artifact.js +1 -145
- package/dist/core/command-hooks/catalog.js +1 -38
- package/dist/core/command-hooks/compose.js +1 -99
- package/dist/core/command-hooks/discovery.js +1 -228
- package/dist/core/command-hooks/help.js +1 -18
- package/dist/core/command-hooks/index.js +1 -7
- package/dist/core/command-hooks/lifecycle-catalog.js +1 -9
- package/dist/core/command-hooks/lifecycle-create.js +1 -51
- package/dist/core/command-hooks/report.js +1 -28
- package/dist/core/command-hooks/schema.js +1 -157
- package/dist/core/command-hooks/transport/exec-invoke.js +1 -276
- package/dist/core/command-hooks/transport/exec-lifecycle.js +1 -211
- package/dist/core/command-manifests/manifest.js +1 -324
- package/dist/core/command-manifests/registry.js +1 -118
- package/dist/core/command-manifests/schema.js +1 -736
- package/dist/core/command-plugins/bundle.js +1 -261
- package/dist/core/command-plugins/compose.js +1 -65
- package/dist/core/command-plugins/discovery.js +1 -245
- package/dist/core/command-plugins/endpoint.js +1 -48
- package/dist/core/command-plugins/extensions.js +1 -166
- package/dist/core/command-plugins/help-addenda.js +1 -44
- package/dist/core/command-plugins/presence.js +1 -17
- package/dist/core/command-plugins/revalidate.js +2 -152
- package/dist/core/command-plugins/transport/exec-invoke.js +1 -215
- package/dist/core/command-plugins/transport/http-fetch.js +1 -68
- package/dist/core/command-plugins/transport/http-invoke.js +3 -546
- package/dist/core/command.js +10 -739
- package/dist/core/config.js +1 -1059
- package/dist/core/document-lines.js +3 -6
- package/dist/core/env-name.js +1 -9
- package/dist/core/errors.js +1 -52
- package/dist/core/events/emit.js +1 -17
- package/dist/core/events/envelope.js +1 -84
- package/dist/core/events/errors.js +1 -69
- package/dist/core/events/index.js +1 -4
- package/dist/core/events/operation-id.js +1 -24
- package/dist/core/events/read.js +1 -623
- package/dist/core/events/serialize.js +1 -199
- package/dist/core/events/source.js +1 -31
- package/dist/core/events/types.js +1 -11
- package/dist/core/exclusive-lock.js +1 -197
- package/dist/core/fault-classifier.js +1 -96
- package/dist/core/feed/feed.js +7 -202
- package/dist/core/feed/inbox-migrate.js +3 -135
- package/dist/core/feed/inbox.js +10 -122
- package/dist/core/feed/messages.js +6 -212
- package/dist/core/frontmatter.js +1 -35
- package/dist/core/fs-utils.js +3 -202
- package/dist/core/git.js +2 -103
- package/dist/core/help.js +9 -310
- package/dist/core/host-exports/builtins.js +9 -68
- package/dist/core/host-exports/export.js +3 -124
- package/dist/core/human/action-binding.js +1 -40
- package/dist/core/human/answer-text.js +5 -100
- package/dist/core/human/answer.js +1 -119
- package/dist/core/human/claim.js +3 -67
- package/dist/core/human/completion.js +1 -27
- package/dist/core/human/component-docs.js +78 -272
- package/dist/core/human/convention.js +2 -82
- package/dist/core/human/feedback-companion.js +1 -106
- package/dist/core/human/feedback.js +1 -88
- package/dist/core/human/page-authoring.js +1 -19
- package/dist/core/human/page-catalog.js +1 -172
- package/dist/core/human/page-errors.js +1 -7
- package/dist/core/human/page-eval.js +1 -125
- package/dist/core/human/page-html-markdown.js +8 -260
- package/dist/core/human/page-markdown.js +17 -295
- package/dist/core/human/page-schema.js +1 -373
- package/dist/core/human/page-synth.js +8 -27
- package/dist/core/human/page.js +1 -198
- package/dist/core/human/requests.js +15 -466
- package/dist/core/human/review-schema.js +1 -34
- package/dist/core/human/root.js +1 -11
- package/dist/core/human/scan.js +1 -69
- package/dist/core/human/summary.js +1 -5
- package/dist/core/human/tickets.js +1 -171
- package/dist/core/human/types.js +0 -1
- package/dist/core/human/visible-paths.js +1 -77
- package/dist/core/human-actions.js +1 -101
- package/dist/core/inspector/chrome.js +1 -14
- package/dist/core/inspector/contract.js +0 -1
- package/dist/core/inspector/core.js +2 -295
- package/dist/core/inspector/host.js +4 -538
- package/dist/core/inspector/model.js +2 -226
- package/dist/core/inspector/text.js +6 -45
- package/dist/core/inspector/transport.js +1 -36
- package/dist/core/inspector/tui.js +2 -295
- package/dist/core/installed-plugins.js +1 -78
- package/dist/core/io.js +7 -356
- package/dist/core/keybindings/attach-control.js +1 -42
- package/dist/core/keybindings/background-bash.js +1 -33
- package/dist/core/keybindings/catalog.js +1 -256
- package/dist/core/keybindings/inbox.js +1 -25
- package/dist/core/keybindings/index.js +1 -7
- package/dist/core/keybindings/match.js +1 -127
- package/dist/core/keybindings/persistence.js +1 -49
- package/dist/core/keybindings/resolve.js +1 -348
- package/dist/core/keybindings/types.js +0 -1
- package/dist/core/locked-file.js +1 -118
- package/dist/core/log.js +3 -27
- package/dist/core/manifest-recovery.js +1 -72
- package/dist/core/manifest-stale.js +1 -39
- package/dist/core/manifest.js +1 -20
- package/dist/core/memory/doc-link-grammar.js +2 -109
- package/dist/core/memory/extensions.js +1 -221
- package/dist/core/memory/history.js +6 -268
- package/dist/core/memory/identity.js +1 -181
- package/dist/core/memory/inline-ref-grammar.js +1 -98
- package/dist/core/memory/inline-ref-guidance.js +2 -35
- package/dist/core/memory/inline-ref-inventory.js +1 -59
- package/dist/core/memory/lint.js +2 -671
- package/dist/core/memory/project-namespace.js +2 -85
- package/dist/core/memory/repository-association.js +1 -129
- package/dist/core/memory/tree.js +1 -93
- package/dist/core/memory-resolver.js +2 -611
- package/dist/core/model-config.js +1 -107
- package/dist/core/model-routes.js +1 -201
- package/dist/core/nested-stores.js +2 -166
- package/dist/core/output.js +7 -99
- package/dist/core/pagination.js +1 -88
- package/dist/core/plugin-swap-lock.js +1 -31
- package/dist/core/pool-credential-store.js +1 -116
- package/dist/core/predicate.js +1 -191
- package/dist/core/preview-registry.js +2 -411
- package/dist/core/preview-result-path.js +1 -26
- package/dist/core/profiles/default-binding.js +1 -24
- package/dist/core/profiles/deletion-reservation.js +1 -42
- package/dist/core/profiles/env-store.js +2 -162
- package/dist/core/profiles/fuzzy-match.js +1 -92
- package/dist/core/profiles/manifest.js +1 -574
- package/dist/core/profiles/select.js +35 -741
- package/dist/core/profiles/state-block.js +3 -17
- package/dist/core/provider-error-recognition.js +1 -74
- package/dist/core/provider-failure.js +1 -86
- package/dist/core/provider-management.js +1 -22
- package/dist/core/remote-canvas-target.js +1 -30
- package/dist/core/render.js +18 -138
- package/dist/core/resolver.js +1 -111
- package/dist/core/review/birth.js +1 -52
- package/dist/core/review/comments.js +5 -279
- package/dist/core/review/companion.js +1 -215
- package/dist/core/review/document.js +2 -138
- package/dist/core/review/project.js +1 -36
- package/dist/core/review/realize.js +1 -71
- package/dist/core/review/remap.js +4 -141
- package/dist/core/review/signal.js +1 -12
- package/dist/core/review/stage.js +1 -184
- package/dist/core/review/store.js +1 -168
- package/dist/core/review/types.js +1 -23
- package/dist/core/runtime/advertised-command-invocation.js +1 -233
- package/dist/core/runtime/auth-reload.js +1 -67
- package/dist/core/runtime/banner.js +1 -51
- package/dist/core/runtime/bearings-render.js +18 -250
- package/dist/core/runtime/bearings.js +7 -194
- package/dist/core/runtime/bin-contributions.js +2 -186
- package/dist/core/runtime/boot-root.js +1 -107
- package/dist/core/runtime/branded-host.js +2 -264
- package/dist/core/runtime/broker/auth-reload.js +1 -157
- package/dist/core/runtime/broker/client-registry.js +1 -179
- package/dist/core/runtime/broker/daemon-ops.js +1 -88
- package/dist/core/runtime/broker/engine-drive.js +1 -354
- package/dist/core/runtime/broker/engine-routing.js +1 -211
- package/dist/core/runtime/broker/event-projection.js +1 -193
- package/dist/core/runtime/broker/extension-abort.js +1 -36
- package/dist/core/runtime/broker/fault-retry.js +1 -588
- package/dist/core/runtime/broker/frame-client.js +1 -132
- package/dist/core/runtime/broker/frame-dispatch.js +1 -183
- package/dist/core/runtime/broker/frame-engine-control.js +1 -231
- package/dist/core/runtime/broker/frame-memory-refs.js +1 -41
- package/dist/core/runtime/broker/frame-model-query.js +1 -69
- package/dist/core/runtime/broker/frame-read.js +1 -116
- package/dist/core/runtime/broker/frame-replies.js +1 -64
- package/dist/core/runtime/broker/frame-session.js +4 -203
- package/dist/core/runtime/broker/held-deferred-inbox.js +1 -13
- package/dist/core/runtime/broker/inbox.js +13 -163
- package/dist/core/runtime/broker/node-named.js +1 -27
- package/dist/core/runtime/broker/read-ops.js +1 -171
- package/dist/core/runtime/broker/rebind.js +1 -318
- package/dist/core/runtime/broker/tool-groups.js +1 -246
- package/dist/core/runtime/broker/turn-admission.js +1 -31
- package/dist/core/runtime/broker/turn-ignition.js +1 -84
- package/dist/core/runtime/broker-cli.js +3 -81
- package/dist/core/runtime/broker-extension-render.js +5 -135
- package/dist/core/runtime/broker-inventory.js +1 -116
- package/dist/core/runtime/broker-persona-guidance.js +4 -154
- package/dist/core/runtime/broker-protocol.js +3 -152
- package/dist/core/runtime/broker-request.js +1 -85
- package/dist/core/runtime/broker-sdk.js +1 -129
- package/dist/core/runtime/broker.js +1 -1214
- package/dist/core/runtime/canvas-extensions.js +1 -96
- package/dist/core/runtime/chat-inventory-rows.js +1 -105
- package/dist/core/runtime/close.js +1 -265
- package/dist/core/runtime/command-expansion.js +9 -104
- package/dist/core/runtime/command-surface.js +1 -117
- package/dist/core/runtime/connectivity.js +1 -73
- package/dist/core/runtime/deliver-live.js +1 -88
- package/dist/core/runtime/fault-recovery.js +1 -83
- package/dist/core/runtime/fault.js +1 -17
- package/dist/core/runtime/fleet.js +1 -58
- package/dist/core/runtime/front-door-env.js +1 -16
- package/dist/core/runtime/front-door.js +7 -183
- package/dist/core/runtime/headless-pi.js +1 -161
- package/dist/core/runtime/host.js +1 -457
- package/dist/core/runtime/interactive-deliver.js +1 -51
- package/dist/core/runtime/invocation.js +0 -10
- package/dist/core/runtime/kickoff.js +30 -327
- package/dist/core/runtime/launch-config-worker.js +1 -12
- package/dist/core/runtime/launch-prompt.js +4 -13
- package/dist/core/runtime/launch-target.js +1 -55
- package/dist/core/runtime/launch.js +1 -483
- package/dist/core/runtime/lifecycle.js +2 -213
- package/dist/core/runtime/managed-provider-cooling.js +1 -62
- package/dist/core/runtime/memory.js +1 -17
- package/dist/core/runtime/model-registry.js +1 -13
- package/dist/core/runtime/model-selection.js +1 -135
- package/dist/core/runtime/model-swap.js +1 -86
- package/dist/core/runtime/naming.js +14 -298
- package/dist/core/runtime/nerd-font.js +2 -127
- package/dist/core/runtime/node-read.js +2 -386
- package/dist/core/runtime/nodes.js +1 -331
- package/dist/core/runtime/outcome-document.js +1 -97
- package/dist/core/runtime/package-health.js +4 -99
- package/dist/core/runtime/persona.js +2 -55
- package/dist/core/runtime/pi-cli.js +1 -65
- package/dist/core/runtime/pi-vendored.js +1 -66
- package/dist/core/runtime/placement-tmux.js +1 -81
- package/dist/core/runtime/placement.js +1 -386
- package/dist/core/runtime/promote.js +1 -174
- package/dist/core/runtime/prospective-inventory-cli.js +3 -61
- package/dist/core/runtime/prospective-inventory.js +2 -88
- package/dist/core/runtime/recap.js +27 -103
- package/dist/core/runtime/recycle.js +1 -190
- package/dist/core/runtime/reopen.js +1 -138
- package/dist/core/runtime/reset.js +1 -245
- package/dist/core/runtime/resume-root.js +10 -290
- package/dist/core/runtime/revive-all.js +1 -107
- package/dist/core/runtime/revive.js +4 -544
- package/dist/core/runtime/roadmap.js +4 -38
- package/dist/core/runtime/session-branch.js +1 -46
- package/dist/core/runtime/session-cycles.js +1 -110
- package/dist/core/runtime/session-list-cache.js +1 -406
- package/dist/core/runtime/session-visibility.js +1 -99
- package/dist/core/runtime/shell-expansion.js +9 -100
- package/dist/core/runtime/situational-context.js +2 -67
- package/dist/core/runtime/situational-live.js +1 -41
- package/dist/core/runtime/spawn-env.js +1 -255
- package/dist/core/runtime/spawn.js +3 -577
- package/dist/core/runtime/stamp/channel.js +1 -76
- package/dist/core/runtime/stamp/protocol.js +1 -113
- package/dist/core/runtime/stop-guard.js +7 -116
- package/dist/core/runtime/stop-signals.js +1 -46
- package/dist/core/runtime/stream-watchdog.js +1 -134
- package/dist/core/runtime/structured-output.js +4 -156
- package/dist/core/runtime/surface-bg.js +1 -85
- package/dist/core/runtime/tmux-bindings.js +4 -730
- package/dist/core/runtime/tmux-chrome.js +1 -5
- package/dist/core/runtime/tmux-driver.js +7 -637
- package/dist/core/runtime/tool-group-summary.js +6 -85
- package/dist/core/runtime/turn-visibility.js +1 -31
- package/dist/core/runtime/view-socket.js +1 -83
- package/dist/core/runtime/warm-pool.js +1 -395
- package/dist/core/scope.js +1 -254
- package/dist/core/scoped-state/db.js +1 -135
- package/dist/core/scoped-state/migrate.js +3 -181
- package/dist/core/scoped-state/paths.js +1 -27
- package/dist/core/scoped-state/profiles.js +1 -62
- package/dist/core/scoped-state/providers.js +1 -8
- package/dist/core/scoped-state/schema.js +3 -16
- package/dist/core/scoped-state/settings.js +1 -82
- package/dist/core/secrets.js +2 -55
- package/dist/core/self-update.js +1 -71
- package/dist/core/session-model/session-state.js +1 -180
- package/dist/core/shell-segments.js +4 -169
- package/dist/core/spawn.js +1 -26
- package/dist/core/stdout-errors.js +1 -14
- package/dist/core/subscription-state.js +3 -193
- package/dist/core/substrate/frontmatter-validation.js +1 -105
- package/dist/core/substrate/gate-explain.js +1 -424
- package/dist/core/substrate/gate.js +1 -26
- package/dist/core/substrate/index.js +1 -30
- package/dist/core/substrate/injected-store.js +1 -249
- package/dist/core/substrate/listings.js +1 -115
- package/dist/core/substrate/on-read-node.js +1 -36
- package/dist/core/substrate/on-read.js +9 -315
- package/dist/core/substrate/plan.js +1 -266
- package/dist/core/substrate/render-node.js +1 -30
- package/dist/core/substrate/render.js +65 -689
- package/dist/core/substrate/schema.js +1 -186
- package/dist/core/substrate/session-cache.js +1 -83
- package/dist/core/substrate/subject-fields.js +1 -35
- package/dist/core/substrate/subject.js +1 -47
- package/dist/core/substrate/surface-match.js +1 -242
- package/dist/core/termrender/code-doc.js +5 -92
- package/dist/core/termrender/display.js +2 -56
- package/dist/core/termrender/termrender.js +14 -719
- package/dist/core/termrender/version.js +1 -1
- package/dist/core/timing.js +2 -94
- package/dist/core/tui/draw.js +2 -378
- package/dist/core/tui/fuzzy.js +1 -38
- package/dist/core/tui/markdown.js +3 -407
- package/dist/core/tui/page-host.js +1 -74
- package/dist/core/tui/panel.js +1 -137
- package/dist/core/tui/terminal.js +2 -100
- package/dist/core/user-settings.js +1 -454
- package/dist/core/wake.js +1 -296
- package/dist/core/worktree-close.js +6 -228
- package/dist/core/worktree-containment.js +3 -48
- package/dist/core/worktree-landing.js +4 -56
- package/dist/core/worktree-mutation-async.js +10 -280
- package/dist/core/worktree-quarantine.js +1 -54
- package/dist/core/worktree-sweep.js +6 -453
- package/dist/core/worktree.js +18 -899
- package/dist/daemon/api/bridge.js +8 -418
- package/dist/daemon/api/handlers/attach.js +1 -65
- package/dist/daemon/api/handlers/bash-jobs.js +2 -91
- package/dist/daemon/api/handlers/broker-ops.js +1 -447
- package/dist/daemon/api/handlers/broker-recovery.js +1 -251
- package/dist/daemon/api/handlers/canvas.js +6 -490
- package/dist/daemon/api/handlers/chat-inventory.js +1 -25
- package/dist/daemon/api/handlers/crons.js +1 -373
- package/dist/daemon/api/handlers/daemon.js +1 -76
- package/dist/daemon/api/handlers/feedback-comments.js +3 -199
- package/dist/daemon/api/handlers/files.js +1 -63
- package/dist/daemon/api/handlers/focus.js +1 -92
- package/dist/daemon/api/handlers/health.js +1 -76
- package/dist/daemon/api/handlers/human-requests.js +1 -379
- package/dist/daemon/api/handlers/human.js +1 -3
- package/dist/daemon/api/handlers/inbox-page.js +1 -89
- package/dist/daemon/api/handlers/inbox.js +1 -301
- package/dist/daemon/api/handlers/memory.js +1 -50
- package/dist/daemon/api/handlers/messages.js +2 -506
- package/dist/daemon/api/handlers/model-config.js +1 -44
- package/dist/daemon/api/handlers/modelauth.js +1 -165
- package/dist/daemon/api/handlers/node-outcomes.js +1 -181
- package/dist/daemon/api/handlers/nodes.js +1 -939
- package/dist/daemon/api/handlers/profiles.js +1 -140
- package/dist/daemon/api/handlers/prospective-chat-inventory.js +1 -59
- package/dist/daemon/api/handlers/reports.js +16 -332
- package/dist/daemon/api/handlers/review-comments.js +1 -465
- package/dist/daemon/api/handlers/reviews.js +1 -200
- package/dist/daemon/api/handlers/subscriptions.js +1 -53
- package/dist/daemon/api/handlers/validate.js +1 -58
- package/dist/daemon/api/handlers/worktree.js +1 -39
- package/dist/daemon/api/map.js +2 -735
- package/dist/daemon/api/router.js +1 -190
- package/dist/daemon/api/server.js +11 -408
- package/dist/daemon/boot-migrations.js +1 -31
- package/dist/daemon/companion-retire.js +1 -34
- package/dist/daemon/control.js +1 -22
- package/dist/daemon/cron/armed-context.js +1 -100
- package/dist/daemon/cron/capture.js +2 -45
- package/dist/daemon/cron/disposition.js +1 -55
- package/dist/daemon/cron/escalation.js +3 -124
- package/dist/daemon/cron/held.js +1 -20
- package/dist/daemon/cron/lease-recovery.js +1 -119
- package/dist/daemon/cron/live-runs.js +1 -23
- package/dist/daemon/cron/passes.js +1 -58
- package/dist/daemon/cron/settle.js +1 -61
- package/dist/daemon/cron/sinks.js +2 -59
- package/dist/daemon/cron-run.js +1 -405
- package/dist/daemon/crtrd-cli.js +1 -23
- package/dist/daemon/crtrd.js +8 -854
- package/dist/daemon/delivery/run-delivery.js +1 -164
- package/dist/daemon/fleet.js +17 -475
- package/dist/daemon/human/finish.js +10 -179
- package/dist/daemon/human/settle.js +1 -89
- package/dist/daemon/human/sweep.js +1 -66
- package/dist/daemon/manage.js +2 -595
- package/dist/daemon/messaging/node-message.js +1 -99
- package/dist/daemon/park-activity.js +1 -30
- package/dist/daemon/park-pending.js +1 -52
- package/dist/daemon/pidfile.js +1 -37
- package/dist/daemon/profile-delete.js +1 -306
- package/dist/daemon/reconcilers/bash-deadline.js +1 -80
- package/dist/daemon/reconcilers/broker-supervision.js +4 -761
- package/dist/daemon/reconcilers/controller-death.js +1 -14
- package/dist/daemon/reconcilers/cron-lane.js +1 -29
- package/dist/daemon/reconcilers/delivery-lane.js +1 -130
- package/dist/daemon/reconcilers/live-obligation.js +1 -87
- package/dist/daemon/reconcilers/managed-worktree-sweep.js +1 -202
- package/dist/daemon/reconcilers/node-deadline.js +1 -82
- package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -172
- package/dist/daemon/reconcilers/node-lifecycle/respawn-policy.js +1 -59
- package/dist/daemon/reconcilers/node-lifecycle/terminating.js +1 -12
- package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -146
- package/dist/daemon/reconcilers/node-lifecycle/wants-execution.js +1 -11
- package/dist/daemon/reconcilers/pending-review-submit.js +1 -36
- package/dist/daemon/reconcilers/storage-maintenance.js +1 -207
- package/dist/daemon/review/comment-notify.js +2 -109
- package/dist/daemon/review/companion.js +1 -29
- package/dist/daemon/review/deliver.js +3 -8
- package/dist/daemon/review/finish.js +1 -122
- package/dist/daemon/review/sweep.js +1 -18
- package/dist/daemon/startup-policy.js +1 -1
- package/dist/daemon/supervise-cadence.js +1 -6
- package/dist/hook-authoring.js +5 -447
- package/dist/hook-process.js +1 -34
- package/dist/index.js +1 -52
- package/dist/migrations/001-surfaces-frontmatter.js +1 -161
- package/dist/migrations/002-profile-project-memory.js +1 -72
- package/dist/migrations/003-repository-root-memory-identity/front-door.js +11 -231
- package/dist/migrations/003-repository-root-memory-identity/index.js +5 -513
- package/dist/migrations/003-repository-root-memory-identity/references.js +5 -469
- package/dist/migrations/003-repository-root-memory-identity/repository-facts.js +3 -349
- package/dist/migrations/activation.js +2 -89
- package/dist/migrations/convergent.js +2 -82
- package/dist/migrations/corpus.js +3 -483
- package/dist/migrations/frontmatter-splice.js +8 -176
- package/dist/migrations/profile-manifests.js +2 -70
- package/dist/migrations/registry.js +1 -42
- package/dist/migrations/runner.js +1 -85
- package/dist/migrations/types.js +0 -24
- package/dist/pi-extensions/broker-local.js +2 -106
- package/dist/pi-extensions/canvas-bash-valve.js +7 -461
- package/dist/pi-extensions/canvas-context-intro.js +2 -113
- package/dist/pi-extensions/canvas-doc-substrate.js +9 -178
- package/dist/pi-extensions/canvas-goal-capture.js +1 -83
- package/dist/pi-extensions/canvas-inbox-watcher.js +1 -1010
- package/dist/pi-extensions/canvas-passive-context.js +14 -203
- package/dist/pi-extensions/canvas-preview-result.js +2 -72
- package/dist/pi-extensions/canvas-prompt-scrub.js +2 -54
- package/dist/pi-extensions/canvas-recap.js +11 -405
- package/dist/pi-extensions/canvas-review-boundary.js +3 -63
- package/dist/pi-extensions/canvas-stamp.js +2 -77
- package/dist/pi-extensions/canvas-stophook.js +1 -643
- package/dist/pi-extensions/canvas-structured-output.js +13 -35
- package/dist/pi-extensions/canvas-tool-guide.js +9 -78
- package/dist/pi-extensions/envelope-merge.js +8 -29
- package/dist/prompts/review.js +20 -42
- package/dist/shared/birth-announcement.js +1 -25
- package/dist/shared/crtr-version.js +1 -18
- package/dist/shared/env.js +1 -214
- package/dist/shared/generated-context.js +11 -226
- package/dist/shared/predicates.js +1 -4
- package/dist/shared/shell-quote.js +1 -5
- package/dist/shared/tool-groups.js +1 -64
- package/dist/shared/working-activity.js +1 -27
- package/dist/suppress-experimental-warnings.js +1 -15
- package/dist/types.js +1 -185
- package/docs/public-api.md +10 -9
- package/package.json +6 -4
- package/runtime.lock.json +5 -5
- package/scripts/pack-minify.mjs +108 -0
- package/dist/api/__tests__/integration/client.test.d.ts +0 -1
- package/dist/api/__tests__/integration/client.test.js +0 -163
- package/dist/builtin-pi-packages/pi-crtr-extensions/__tests__/insights-active-init.test.ts +0 -98
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/crtr-commands.test.ts +0 -93
- package/dist/builtin-pi-packages/pi-crtr-extensions/extensions/__tests__/integration/provider-rotation.test.ts +0 -2530
- package/dist/clients/__tests__/helpers/human-daemon.d.ts +0 -11
- package/dist/clients/__tests__/helpers/human-daemon.js +0 -60
- package/dist/clients/attach/__tests__/attach-remote-readonly.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/attach-remote-readonly.test.js +0 -97
- package/dist/clients/attach/__tests__/bash-call-width.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/bash-call-width.test.js +0 -38
- package/dist/clients/attach/__tests__/chat-view-snapshot-ordering.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/chat-view-snapshot-ordering.test.js +0 -175
- package/dist/clients/attach/__tests__/completion-frecency.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/completion-frecency.test.js +0 -35
- package/dist/clients/attach/__tests__/context-message.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/context-message.test.js +0 -130
- package/dist/clients/attach/__tests__/crtr-output.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/crtr-output.test.js +0 -68
- package/dist/clients/attach/__tests__/diagram.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/diagram.test.js +0 -42
- package/dist/clients/attach/__tests__/edit-diff.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/edit-diff.test.js +0 -31
- package/dist/clients/attach/__tests__/frame-selection.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/frame-selection.test.js +0 -84
- package/dist/clients/attach/__tests__/group-activity.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/group-activity.test.js +0 -165
- package/dist/clients/attach/__tests__/oauth-dialog-lifecycle.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/oauth-dialog-lifecycle.test.js +0 -83
- package/dist/clients/attach/__tests__/pane-tag-successor.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/pane-tag-successor.test.js +0 -56
- package/dist/clients/attach/__tests__/profile-files.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/profile-files.test.js +0 -21
- package/dist/clients/attach/__tests__/prompt-preview.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/prompt-preview.test.js +0 -21
- package/dist/clients/attach/__tests__/ref-autocomplete.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/ref-autocomplete.test.js +0 -64
- package/dist/clients/attach/__tests__/titled-editor-paste.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/titled-editor-paste.test.js +0 -114
- package/dist/clients/attach/__tests__/titled-editor-preview.test.d.ts +0 -1
- package/dist/clients/attach/__tests__/titled-editor-preview.test.js +0 -83
- package/dist/clients/inbox/__tests__/integration/inbox-controller.test.d.ts +0 -1
- package/dist/clients/inbox/__tests__/integration/inbox-controller.test.js +0 -81
- package/dist/clients/inbox/__tests__/integration/mount-panel.test.d.ts +0 -1
- package/dist/clients/inbox/__tests__/integration/mount-panel.test.js +0 -135
- package/dist/clients/inbox/__tests__/integration/stale-row-activation.test.d.ts +0 -1
- package/dist/clients/inbox/__tests__/integration/stale-row-activation.test.js +0 -66
- package/dist/clients/inbox/review/__tests__/editor-roundtrip.test.d.ts +0 -1
- package/dist/clients/inbox/review/__tests__/editor-roundtrip.test.js +0 -35
- package/dist/clients/inbox/review/__tests__/review-core.test.d.ts +0 -1
- package/dist/clients/inbox/review/__tests__/review-core.test.js +0 -52
- package/dist/clients/inbox/review/__tests__/teardown-notice.test.d.ts +0 -1
- package/dist/clients/inbox/review/__tests__/teardown-notice.test.js +0 -100
- package/dist/commands/__tests__/api-client-cold-start-diagnostic.test.d.ts +0 -1
- package/dist/commands/__tests__/api-client-cold-start-diagnostic.test.js +0 -69
- package/dist/commands/__tests__/human.test.d.ts +0 -1
- package/dist/commands/__tests__/human.test.js +0 -172
- package/dist/commands/__tests__/integration/dashboard-snapshot.test.d.ts +0 -1
- package/dist/commands/__tests__/integration/dashboard-snapshot.test.js +0 -237
- package/dist/commands/__tests__/integration/migrate.test.d.ts +0 -1
- package/dist/commands/__tests__/integration/migrate.test.js +0 -1330
- package/dist/commands/__tests__/node-message.test.d.ts +0 -1
- package/dist/commands/__tests__/node-message.test.js +0 -112
- package/dist/commands/__tests__/node-new.test.d.ts +0 -1
- package/dist/commands/__tests__/node-new.test.js +0 -58
- package/dist/commands/__tests__/revive-now-gate.test.d.ts +0 -1
- package/dist/commands/__tests__/revive-now-gate.test.js +0 -62
- package/dist/commands/__tests__/seam/daemon-status.test.d.ts +0 -1
- package/dist/commands/__tests__/seam/daemon-status.test.js +0 -29
- package/dist/commands/__tests__/surface-reload-target.test.d.ts +0 -1
- package/dist/commands/__tests__/surface-reload-target.test.js +0 -21
- package/dist/commands/memory/__tests__/command-selector-and-mutation-guards.test.d.ts +0 -1
- package/dist/commands/memory/__tests__/command-selector-and-mutation-guards.test.js +0 -379
- package/dist/commands/memory/__tests__/memory-list-and-lint-ignore.test.d.ts +0 -1
- package/dist/commands/memory/__tests__/memory-list-and-lint-ignore.test.js +0 -124
- package/dist/commands/memory/__tests__/repository-root-lint.test.d.ts +0 -1
- package/dist/commands/memory/__tests__/repository-root-lint.test.js +0 -148
- package/dist/commands/sys/__tests__/config-model-ladders.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/config-model-ladders.test.js +0 -114
- package/dist/commands/sys/__tests__/setup-core.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/setup-core.test.js +0 -45
- package/dist/commands/sys/__tests__/sync-project-guidance.test.d.ts +0 -1
- package/dist/commands/sys/__tests__/sync-project-guidance.test.js +0 -244
- package/dist/core/__tests__/bash-guard.test.d.ts +0 -1
- package/dist/core/__tests__/bash-guard.test.js +0 -190
- package/dist/core/__tests__/boot-fault-attempt.test.d.ts +0 -1
- package/dist/core/__tests__/boot-fault-attempt.test.js +0 -105
- package/dist/core/__tests__/boot.test.d.ts +0 -1
- package/dist/core/__tests__/boot.test.js +0 -274
- package/dist/core/__tests__/branded-host-concurrency.test.d.ts +0 -1
- package/dist/core/__tests__/branded-host-concurrency.test.js +0 -72
- package/dist/core/__tests__/broker-extension-canvas-db-boundary.test.d.ts +0 -1
- package/dist/core/__tests__/broker-extension-canvas-db-boundary.test.js +0 -75
- package/dist/core/__tests__/broker-launch-candidates.test.d.ts +0 -1
- package/dist/core/__tests__/broker-launch-candidates.test.js +0 -311
- package/dist/core/__tests__/broker-preflight.test.d.ts +0 -1
- package/dist/core/__tests__/broker-preflight.test.js +0 -95
- package/dist/core/__tests__/broker-stream-watchdog-floor.test.d.ts +0 -1
- package/dist/core/__tests__/broker-stream-watchdog-floor.test.js +0 -82
- package/dist/core/__tests__/broker-turn-admission.test.d.ts +0 -1
- package/dist/core/__tests__/broker-turn-admission.test.js +0 -44
- package/dist/core/__tests__/canvas-db-boundary.test.d.ts +0 -1
- package/dist/core/__tests__/canvas-db-boundary.test.js +0 -46
- package/dist/core/__tests__/canvas-inbox-watcher-hold.test.d.ts +0 -1
- package/dist/core/__tests__/canvas-inbox-watcher-hold.test.js +0 -710
- package/dist/core/__tests__/canvas-inbox-watcher-naming.test.d.ts +0 -1
- package/dist/core/__tests__/canvas-inbox-watcher-naming.test.js +0 -310
- package/dist/core/__tests__/canvas-inbox-watcher.test.d.ts +0 -1
- package/dist/core/__tests__/canvas-inbox-watcher.test.js +0 -397
- package/dist/core/__tests__/canvas.test.d.ts +0 -1
- package/dist/core/__tests__/canvas.test.js +0 -138
- package/dist/core/__tests__/child-death-wake.test.d.ts +0 -1
- package/dist/core/__tests__/child-death-wake.test.js +0 -153
- package/dist/core/__tests__/cli-help-contract.test.d.ts +0 -1
- package/dist/core/__tests__/cli-help-contract.test.js +0 -152
- package/dist/core/__tests__/close.test.d.ts +0 -1
- package/dist/core/__tests__/close.test.js +0 -284
- package/dist/core/__tests__/collectible.test.d.ts +0 -1
- package/dist/core/__tests__/collectible.test.js +0 -89
- package/dist/core/__tests__/config-change-delta.test.d.ts +0 -1
- package/dist/core/__tests__/config-change-delta.test.js +0 -108
- package/dist/core/__tests__/context-intro.test.d.ts +0 -1
- package/dist/core/__tests__/context-intro.test.js +0 -123
- package/dist/core/__tests__/cron-armed-context-failure.test.d.ts +0 -1
- package/dist/core/__tests__/cron-armed-context-failure.test.js +0 -150
- package/dist/core/__tests__/cron-held-settlement.test.d.ts +0 -1
- package/dist/core/__tests__/cron-held-settlement.test.js +0 -240
- package/dist/core/__tests__/cron-node-sink-parked-root.test.d.ts +0 -1
- package/dist/core/__tests__/cron-node-sink-parked-root.test.js +0 -166
- package/dist/core/__tests__/cron-self-cancel-delivery.test.d.ts +0 -1
- package/dist/core/__tests__/cron-self-cancel-delivery.test.js +0 -84
- package/dist/core/__tests__/cron-timeout-descendants.test.d.ts +0 -1
- package/dist/core/__tests__/cron-timeout-descendants.test.js +0 -114
- package/dist/core/__tests__/daemon-boot.test.d.ts +0 -1
- package/dist/core/__tests__/daemon-boot.test.js +0 -422
- package/dist/core/__tests__/daemon-wedge.test.d.ts +0 -1
- package/dist/core/__tests__/daemon-wedge.test.js +0 -106
- package/dist/core/__tests__/dead-node-policy-table.test.d.ts +0 -1
- package/dist/core/__tests__/dead-node-policy-table.test.js +0 -77
- package/dist/core/__tests__/events-contract.test.d.ts +0 -1
- package/dist/core/__tests__/events-contract.test.js +0 -76
- package/dist/core/__tests__/extension-abort.test.d.ts +0 -1
- package/dist/core/__tests__/extension-abort.test.js +0 -21
- package/dist/core/__tests__/fault-classifier.test.d.ts +0 -1
- package/dist/core/__tests__/fault-classifier.test.js +0 -138
- package/dist/core/__tests__/fixtures/api-server-host.d.ts +0 -1
- package/dist/core/__tests__/fixtures/api-server-host.js +0 -47
- package/dist/core/__tests__/fixtures/c3-custom-provider-ext.d.ts +0 -2
- package/dist/core/__tests__/fixtures/c3-custom-provider-ext.js +0 -34
- package/dist/core/__tests__/fixtures/c5-command-boundary-ext.d.ts +0 -2
- package/dist/core/__tests__/fixtures/c5-command-boundary-ext.js +0 -32
- package/dist/core/__tests__/fixtures/fake-engine.d.ts +0 -347
- package/dist/core/__tests__/fixtures/fake-engine.js +0 -1509
- package/dist/core/__tests__/fixtures/fake-pi-host.d.ts +0 -2
- package/dist/core/__tests__/fixtures/fake-pi-host.js +0 -311
- package/dist/core/__tests__/fixtures/memory-slash-live-probe.d.ts +0 -1
- package/dist/core/__tests__/fixtures/memory-slash-live-probe.js +0 -75
- package/dist/core/__tests__/fixtures/metadata-migration-race.d.ts +0 -1
- package/dist/core/__tests__/fixtures/metadata-migration-race.js +0 -49
- package/dist/core/__tests__/focuses.test.d.ts +0 -1
- package/dist/core/__tests__/focuses.test.js +0 -113
- package/dist/core/__tests__/fs-utils.test.d.ts +0 -1
- package/dist/core/__tests__/fs-utils.test.js +0 -50
- package/dist/core/__tests__/helpers/broker-clients.d.ts +0 -43
- package/dist/core/__tests__/helpers/broker-clients.js +0 -174
- package/dist/core/__tests__/helpers/fleet.d.ts +0 -12
- package/dist/core/__tests__/helpers/fleet.js +0 -50
- package/dist/core/__tests__/helpers/harness.d.ts +0 -124
- package/dist/core/__tests__/helpers/harness.js +0 -806
- package/dist/core/__tests__/helpers/viewer-panes.d.ts +0 -12
- package/dist/core/__tests__/helpers/viewer-panes.js +0 -133
- package/dist/core/__tests__/history-inbox.test.d.ts +0 -1
- package/dist/core/__tests__/history-inbox.test.js +0 -121
- package/dist/core/__tests__/human-action-delivery.test.d.ts +0 -1
- package/dist/core/__tests__/human-action-delivery.test.js +0 -162
- package/dist/core/__tests__/human-actions.test.d.ts +0 -1
- package/dist/core/__tests__/human-actions.test.js +0 -120
- package/dist/core/__tests__/inline-memory-refs.test.d.ts +0 -1
- package/dist/core/__tests__/inline-memory-refs.test.js +0 -225
- package/dist/core/__tests__/integration/broker-fork-seam.test.d.ts +0 -1
- package/dist/core/__tests__/integration/broker-fork-seam.test.js +0 -193
- package/dist/core/__tests__/integration/broker-sdk-wiring.test.d.ts +0 -1
- package/dist/core/__tests__/integration/broker-sdk-wiring.test.js +0 -750
- package/dist/core/__tests__/integration/broker-snapshot-history.test.d.ts +0 -1
- package/dist/core/__tests__/integration/broker-snapshot-history.test.js +0 -288
- package/dist/core/__tests__/integration/broker-wedge-supervision.test.d.ts +0 -1
- package/dist/core/__tests__/integration/broker-wedge-supervision.test.js +0 -103
- package/dist/core/__tests__/integration/command-plugins.test.d.ts +0 -1
- package/dist/core/__tests__/integration/command-plugins.test.js +0 -1200
- package/dist/core/__tests__/integration/deferred-no-wake.test.d.ts +0 -1
- package/dist/core/__tests__/integration/deferred-no-wake.test.js +0 -610
- package/dist/core/__tests__/integration/flagship-lifecycle.test.d.ts +0 -1
- package/dist/core/__tests__/integration/flagship-lifecycle.test.js +0 -264
- package/dist/core/__tests__/integration/fresh-home-commands.test.d.ts +0 -1
- package/dist/core/__tests__/integration/fresh-home-commands.test.js +0 -49
- package/dist/core/__tests__/integration/git-optional-locks.test.d.ts +0 -1
- package/dist/core/__tests__/integration/git-optional-locks.test.js +0 -81
- package/dist/core/__tests__/integration/host-teardown-process-group.test.d.ts +0 -1
- package/dist/core/__tests__/integration/host-teardown-process-group.test.js +0 -480
- package/dist/core/__tests__/integration/lifecycle-hooks.test.d.ts +0 -1
- package/dist/core/__tests__/integration/lifecycle-hooks.test.js +0 -498
- package/dist/core/__tests__/integration/live-mutation-verbs.test.d.ts +0 -1
- package/dist/core/__tests__/integration/live-mutation-verbs.test.js +0 -180
- package/dist/core/__tests__/integration/live-mutation.test.d.ts +0 -1
- package/dist/core/__tests__/integration/live-mutation.test.js +0 -173
- package/dist/core/__tests__/integration/plugin-revalidate.test.d.ts +0 -1
- package/dist/core/__tests__/integration/plugin-revalidate.test.js +0 -359
- package/dist/core/__tests__/integration/profile-pause.test.d.ts +0 -1
- package/dist/core/__tests__/integration/profile-pause.test.js +0 -115
- package/dist/core/__tests__/integration/refresh-stall-recycle.test.d.ts +0 -1
- package/dist/core/__tests__/integration/refresh-stall-recycle.test.js +0 -151
- package/dist/core/__tests__/integration/revive.test.d.ts +0 -1
- package/dist/core/__tests__/integration/revive.test.js +0 -615
- package/dist/core/__tests__/integration/spawn-root.test.d.ts +0 -1
- package/dist/core/__tests__/integration/spawn-root.test.js +0 -536
- package/dist/core/__tests__/integration/subscription-delivery.test.d.ts +0 -1
- package/dist/core/__tests__/integration/subscription-delivery.test.js +0 -132
- package/dist/core/__tests__/integration/tmux-surface.test.d.ts +0 -1
- package/dist/core/__tests__/integration/tmux-surface.test.js +0 -330
- package/dist/core/__tests__/integration/worktree-land.test.d.ts +0 -1
- package/dist/core/__tests__/integration/worktree-land.test.js +0 -607
- package/dist/core/__tests__/integration/worktree-reap.test.d.ts +0 -1
- package/dist/core/__tests__/integration/worktree-reap.test.js +0 -842
- package/dist/core/__tests__/kickoff.test.d.ts +0 -1
- package/dist/core/__tests__/kickoff.test.js +0 -196
- package/dist/core/__tests__/lifecycle-terminal-reasons.test.d.ts +0 -1
- package/dist/core/__tests__/lifecycle-terminal-reasons.test.js +0 -62
- package/dist/core/__tests__/lifecycle.test.d.ts +0 -1
- package/dist/core/__tests__/lifecycle.test.js +0 -176
- package/dist/core/__tests__/live-lifecycle-prompt.test.d.ts +0 -1
- package/dist/core/__tests__/live-lifecycle-prompt.test.js +0 -63
- package/dist/core/__tests__/memory-resolver-precedence.test.d.ts +0 -1
- package/dist/core/__tests__/memory-resolver-precedence.test.js +0 -228
- package/dist/core/__tests__/migration.test.d.ts +0 -1
- package/dist/core/__tests__/migration.test.js +0 -946
- package/dist/core/__tests__/model-pin-durability.test.d.ts +0 -1
- package/dist/core/__tests__/model-pin-durability.test.js +0 -195
- package/dist/core/__tests__/model-routes-config.test.d.ts +0 -1
- package/dist/core/__tests__/model-routes-config.test.js +0 -150
- package/dist/core/__tests__/nested-store-discovery.test.d.ts +0 -1
- package/dist/core/__tests__/nested-store-discovery.test.js +0 -89
- package/dist/core/__tests__/node-outcome.test.d.ts +0 -1
- package/dist/core/__tests__/node-outcome.test.js +0 -246
- package/dist/core/__tests__/on-read-crouter-home-fence.test.d.ts +0 -1
- package/dist/core/__tests__/on-read-crouter-home-fence.test.js +0 -66
- package/dist/core/__tests__/on-read-dedup-resume.test.d.ts +0 -1
- package/dist/core/__tests__/on-read-dedup-resume.test.js +0 -132
- package/dist/core/__tests__/on-read-nested-store.test.d.ts +0 -1
- package/dist/core/__tests__/on-read-nested-store.test.js +0 -135
- package/dist/core/__tests__/parse-argv-stdin-secret.test.d.ts +0 -1
- package/dist/core/__tests__/parse-argv-stdin-secret.test.js +0 -68
- package/dist/core/__tests__/passive-subscription.test.d.ts +0 -1
- package/dist/core/__tests__/passive-subscription.test.js +0 -120
- package/dist/core/__tests__/pid-identity-match.test.d.ts +0 -1
- package/dist/core/__tests__/pid-identity-match.test.js +0 -145
- package/dist/core/__tests__/pid-zombie.test.d.ts +0 -1
- package/dist/core/__tests__/pid-zombie.test.js +0 -42
- package/dist/core/__tests__/plugin-kinds.test.d.ts +0 -1
- package/dist/core/__tests__/plugin-kinds.test.js +0 -182
- package/dist/core/__tests__/plugin-link-symlinked-scope-root.test.d.ts +0 -1
- package/dist/core/__tests__/plugin-link-symlinked-scope-root.test.js +0 -43
- package/dist/core/__tests__/plugin-page-components.test.d.ts +0 -1
- package/dist/core/__tests__/plugin-page-components.test.js +0 -159
- package/dist/core/__tests__/preview-mirror-cap.test.d.ts +0 -1
- package/dist/core/__tests__/preview-mirror-cap.test.js +0 -53
- package/dist/core/__tests__/preview-registry-sync.test.d.ts +0 -1
- package/dist/core/__tests__/preview-registry-sync.test.js +0 -107
- package/dist/core/__tests__/profile-project-memory-delivery.test.d.ts +0 -1
- package/dist/core/__tests__/profile-project-memory-delivery.test.js +0 -644
- package/dist/core/__tests__/prospective-inventory-capability-parity.test.d.ts +0 -1
- package/dist/core/__tests__/prospective-inventory-capability-parity.test.js +0 -91
- package/dist/core/__tests__/prune.test.d.ts +0 -1
- package/dist/core/__tests__/prune.test.js +0 -243
- package/dist/core/__tests__/push-final-guard.test.d.ts +0 -1
- package/dist/core/__tests__/push-final-guard.test.js +0 -191
- package/dist/core/__tests__/relaunch-root.test.d.ts +0 -1
- package/dist/core/__tests__/relaunch-root.test.js +0 -249
- package/dist/core/__tests__/remote-canvas-target.test.d.ts +0 -1
- package/dist/core/__tests__/remote-canvas-target.test.js +0 -93
- package/dist/core/__tests__/repository-association.test.d.ts +0 -1
- package/dist/core/__tests__/repository-association.test.js +0 -153
- package/dist/core/__tests__/repository-root-identity.test.d.ts +0 -1
- package/dist/core/__tests__/repository-root-identity.test.js +0 -223
- package/dist/core/__tests__/respawn-throttle.test.d.ts +0 -1
- package/dist/core/__tests__/respawn-throttle.test.js +0 -20
- package/dist/core/__tests__/review-model-floor.test.d.ts +0 -1
- package/dist/core/__tests__/review-model-floor.test.js +0 -83
- package/dist/core/__tests__/revive-all.test.d.ts +0 -1
- package/dist/core/__tests__/revive-all.test.js +0 -157
- package/dist/core/__tests__/revive-capacity.test.d.ts +0 -1
- package/dist/core/__tests__/revive-capacity.test.js +0 -184
- package/dist/core/__tests__/revive-parked-fresh.test.d.ts +0 -1
- package/dist/core/__tests__/revive-parked-fresh.test.js +0 -176
- package/dist/core/__tests__/scope-crouter-home-fence.test.d.ts +0 -1
- package/dist/core/__tests__/scope-crouter-home-fence.test.js +0 -55
- package/dist/core/__tests__/seam/broker-attach-multiclient.test.d.ts +0 -1
- package/dist/core/__tests__/seam/broker-attach-multiclient.test.js +0 -262
- package/dist/core/__tests__/seam/broker-attach-stream.test.d.ts +0 -1
- package/dist/core/__tests__/seam/broker-attach-stream.test.js +0 -176
- package/dist/core/__tests__/seam/broker-cap-freeze.test.d.ts +0 -1
- package/dist/core/__tests__/seam/broker-cap-freeze.test.js +0 -155
- package/dist/core/__tests__/seam/broker-crash-teardown.test.d.ts +0 -1
- package/dist/core/__tests__/seam/broker-crash-teardown.test.js +0 -131
- package/dist/core/__tests__/seam/broker-pane-resolution.test.d.ts +0 -1
- package/dist/core/__tests__/seam/broker-pane-resolution.test.js +0 -204
- package/dist/core/__tests__/seam/broker-provider-retry.test.d.ts +0 -1
- package/dist/core/__tests__/seam/broker-provider-retry.test.js +0 -686
- package/dist/core/__tests__/seam/broker-startup-diagnostics.test.d.ts +0 -1
- package/dist/core/__tests__/seam/broker-startup-diagnostics.test.js +0 -82
- package/dist/core/__tests__/seam/broker-whip-interrupt.test.d.ts +0 -1
- package/dist/core/__tests__/seam/broker-whip-interrupt.test.js +0 -50
- package/dist/core/__tests__/seam/deadline-wake-delivery.test.d.ts +0 -1
- package/dist/core/__tests__/seam/deadline-wake-delivery.test.js +0 -138
- package/dist/core/__tests__/seam/dormancy-release.test.d.ts +0 -1
- package/dist/core/__tests__/seam/dormancy-release.test.js +0 -516
- package/dist/core/__tests__/seam/held-deferred-human-prompt.test.d.ts +0 -1
- package/dist/core/__tests__/seam/held-deferred-human-prompt.test.js +0 -65
- package/dist/core/__tests__/seam/inbox-reference-guidance.test.d.ts +0 -1
- package/dist/core/__tests__/seam/inbox-reference-guidance.test.js +0 -84
- package/dist/core/__tests__/seam/memory-slash-node-relative-inventory.test.d.ts +0 -1
- package/dist/core/__tests__/seam/memory-slash-node-relative-inventory.test.js +0 -160
- package/dist/core/__tests__/seam/node-outcome-delivery.test.d.ts +0 -1
- package/dist/core/__tests__/seam/node-outcome-delivery.test.js +0 -177
- package/dist/core/__tests__/seam/prospective-inventory-stdout.test.d.ts +0 -1
- package/dist/core/__tests__/seam/prospective-inventory-stdout.test.js +0 -31
- package/dist/core/__tests__/seam/reopen-invalidated-worktree.test.d.ts +0 -1
- package/dist/core/__tests__/seam/reopen-invalidated-worktree.test.js +0 -60
- package/dist/core/__tests__/seam/self-close-teardown.test.d.ts +0 -1
- package/dist/core/__tests__/seam/self-close-teardown.test.js +0 -49
- package/dist/core/__tests__/seam/yield-refresh-transaction.test.d.ts +0 -1
- package/dist/core/__tests__/seam/yield-refresh-transaction.test.js +0 -100
- package/dist/core/__tests__/secrets.test.d.ts +0 -1
- package/dist/core/__tests__/secrets.test.js +0 -49
- package/dist/core/__tests__/self-update.test.d.ts +0 -1
- package/dist/core/__tests__/self-update.test.js +0 -46
- package/dist/core/__tests__/session-branch.test.d.ts +0 -1
- package/dist/core/__tests__/session-branch.test.js +0 -61
- package/dist/core/__tests__/session-cycles.test.d.ts +0 -1
- package/dist/core/__tests__/session-cycles.test.js +0 -133
- package/dist/core/__tests__/session-model.test.d.ts +0 -1
- package/dist/core/__tests__/session-model.test.js +0 -111
- package/dist/core/__tests__/spawn-worktree-id-conflict.test.d.ts +0 -1
- package/dist/core/__tests__/spawn-worktree-id-conflict.test.js +0 -71
- package/dist/core/__tests__/stdin-body-no-discard.test.d.ts +0 -1
- package/dist/core/__tests__/stdin-body-no-discard.test.js +0 -33
- package/dist/core/__tests__/stdout-errors.test.d.ts +0 -1
- package/dist/core/__tests__/stdout-errors.test.js +0 -16
- package/dist/core/__tests__/stop-guard.test.d.ts +0 -1
- package/dist/core/__tests__/stop-guard.test.js +0 -237
- package/dist/core/__tests__/stream-watchdog.test.d.ts +0 -1
- package/dist/core/__tests__/stream-watchdog.test.js +0 -154
- package/dist/core/__tests__/subscription-pool-credential-guard.test.d.ts +0 -1
- package/dist/core/__tests__/subscription-pool-credential-guard.test.js +0 -95
- package/dist/core/__tests__/tmux-driver-boundary.test.d.ts +0 -1
- package/dist/core/__tests__/tmux-driver-boundary.test.js +0 -50
- package/dist/core/__tests__/warm-claim-preference-snapshot.test.d.ts +0 -1
- package/dist/core/__tests__/warm-claim-preference-snapshot.test.js +0 -54
- package/dist/core/__tests__/worktree-landing.test.d.ts +0 -1
- package/dist/core/__tests__/worktree-landing.test.js +0 -11
- package/dist/core/__tests__/yield-ensures-daemon.test.d.ts +0 -1
- package/dist/core/__tests__/yield-ensures-daemon.test.js +0 -55
- package/dist/core/broker-client/__tests__/transport-relay.test.d.ts +0 -1
- package/dist/core/broker-client/__tests__/transport-relay.test.js +0 -214
- package/dist/core/broker-client/__tests__/transport-socket.test.d.ts +0 -1
- package/dist/core/broker-client/__tests__/transport-socket.test.js +0 -73
- package/dist/core/canvas/__tests__/attention.test.d.ts +0 -1
- package/dist/core/canvas/__tests__/attention.test.js +0 -83
- package/dist/core/canvas/__tests__/history-transcript.test.d.ts +0 -1
- package/dist/core/canvas/__tests__/history-transcript.test.js +0 -102
- package/dist/core/canvas/__tests__/remote-canvas-source.test.d.ts +0 -1
- package/dist/core/canvas/__tests__/remote-canvas-source.test.js +0 -328
- package/dist/core/canvas/__tests__/remote-transport.test.d.ts +0 -1
- package/dist/core/canvas/__tests__/remote-transport.test.js +0 -97
- package/dist/core/canvas/__tests__/render-remote.test.d.ts +0 -1
- package/dist/core/canvas/__tests__/render-remote.test.js +0 -243
- package/dist/core/canvas/__tests__/session-window.test.d.ts +0 -1
- package/dist/core/canvas/__tests__/session-window.test.js +0 -70
- package/dist/core/feed/__tests__/inbox-migrate.test.d.ts +0 -1
- package/dist/core/feed/__tests__/inbox-migrate.test.js +0 -49
- package/dist/core/human/__tests__/page-catalog.test.d.ts +0 -1
- package/dist/core/human/__tests__/page-catalog.test.js +0 -20
- package/dist/core/human/__tests__/page-html-markdown.test.d.ts +0 -1
- package/dist/core/human/__tests__/page-html-markdown.test.js +0 -48
- package/dist/core/human/__tests__/page.test.d.ts +0 -1
- package/dist/core/human/__tests__/page.test.js +0 -92
- package/dist/core/keybindings/__tests__/resolve.test.d.ts +0 -1
- package/dist/core/keybindings/__tests__/resolve.test.js +0 -171
- package/dist/core/profiles/__tests__/env-store.test.d.ts +0 -1
- package/dist/core/profiles/__tests__/env-store.test.js +0 -99
- package/dist/core/profiles/__tests__/fuzzy-match.test.d.ts +0 -1
- package/dist/core/profiles/__tests__/fuzzy-match.test.js +0 -51
- package/dist/core/profiles/__tests__/root-profile.test.d.ts +0 -1
- package/dist/core/profiles/__tests__/root-profile.test.js +0 -59
- package/dist/core/review/__tests__/capture-origin.test.d.ts +0 -1
- package/dist/core/review/__tests__/capture-origin.test.js +0 -150
- package/dist/core/review/__tests__/comments.test.d.ts +0 -1
- package/dist/core/review/__tests__/comments.test.js +0 -116
- package/dist/core/review/__tests__/remap.test.d.ts +0 -1
- package/dist/core/review/__tests__/remap.test.js +0 -177
- package/dist/core/review/__tests__/stage-identity.test.d.ts +0 -1
- package/dist/core/review/__tests__/stage-identity.test.js +0 -150
- package/dist/core/runtime/__tests__/engine-route.test.d.ts +0 -1
- package/dist/core/runtime/__tests__/engine-route.test.js +0 -36
- package/dist/core/runtime/__tests__/install-id-cache-scoping.test.d.ts +0 -1
- package/dist/core/runtime/__tests__/install-id-cache-scoping.test.js +0 -45
- package/dist/core/runtime/__tests__/node-env.test.d.ts +0 -1
- package/dist/core/runtime/__tests__/node-env.test.js +0 -73
- package/dist/core/runtime/__tests__/spawn-env.test.d.ts +0 -1
- package/dist/core/runtime/__tests__/spawn-env.test.js +0 -259
- package/dist/core/substrate/__tests__/surface-match-command.test.d.ts +0 -1
- package/dist/core/substrate/__tests__/surface-match-command.test.js +0 -89
- package/dist/core/substrate/__tests__/surface-match-memory-read.test.d.ts +0 -1
- package/dist/core/substrate/__tests__/surface-match-memory-read.test.js +0 -28
- package/dist/core/substrate/__tests__/surface-match-pre-command.test.d.ts +0 -1
- package/dist/core/substrate/__tests__/surface-match-pre-command.test.js +0 -92
- package/dist/daemon/__tests__/autostart-storm.test.d.ts +0 -1
- package/dist/daemon/__tests__/autostart-storm.test.js +0 -128
- package/dist/daemon/__tests__/broker-ownership.test.d.ts +0 -1
- package/dist/daemon/__tests__/broker-ownership.test.js +0 -25
- package/dist/daemon/__tests__/daemon-ownership.test.d.ts +0 -1
- package/dist/daemon/__tests__/daemon-ownership.test.js +0 -27
- package/dist/daemon/__tests__/helpers/source-daemon.d.ts +0 -30
- package/dist/daemon/__tests__/helpers/source-daemon.js +0 -176
- package/dist/daemon/__tests__/integration/api-startup-readiness.test.d.ts +0 -1
- package/dist/daemon/__tests__/integration/api-startup-readiness.test.js +0 -83
- package/dist/daemon/__tests__/integration/migration-startup.test.d.ts +0 -1
- package/dist/daemon/__tests__/integration/migration-startup.test.js +0 -127
- package/dist/daemon/__tests__/node-deadline-lane.test.d.ts +0 -1
- package/dist/daemon/__tests__/node-deadline-lane.test.js +0 -77
- package/dist/daemon/__tests__/node-outcome-birth-invariants.test.d.ts +0 -1
- package/dist/daemon/__tests__/node-outcome-birth-invariants.test.js +0 -146
- package/dist/daemon/__tests__/node-outcome-delivery.test.d.ts +0 -1
- package/dist/daemon/__tests__/node-outcome-delivery.test.js +0 -116
- package/dist/daemon/__tests__/reconciler-signature.test.d.ts +0 -1
- package/dist/daemon/__tests__/reconciler-signature.test.js +0 -37
- package/dist/daemon/__tests__/subtree-filter-freshness.test.d.ts +0 -1
- package/dist/daemon/__tests__/subtree-filter-freshness.test.js +0 -63
- package/dist/daemon/__tests__/thaw-order.test.d.ts +0 -1
- package/dist/daemon/__tests__/thaw-order.test.js +0 -55
- package/dist/daemon/api/__tests__/bridge-heartbeat.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/bridge-heartbeat.test.js +0 -58
- package/dist/daemon/api/__tests__/broker-settle-park.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/broker-settle-park.test.js +0 -175
- package/dist/daemon/api/__tests__/canvas-snapshot-fields.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/canvas-snapshot-fields.test.js +0 -216
- package/dist/daemon/api/__tests__/error-seam.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/error-seam.test.js +0 -83
- package/dist/daemon/api/__tests__/model-config.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/model-config.test.js +0 -73
- package/dist/daemon/api/__tests__/node-create-description.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/node-create-description.test.js +0 -127
- package/dist/daemon/api/__tests__/node-model-validation.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/node-model-validation.test.js +0 -183
- package/dist/daemon/api/__tests__/nodes-activity-query.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/nodes-activity-query.test.js +0 -99
- package/dist/daemon/api/__tests__/profile-launch-gates.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/profile-launch-gates.test.js +0 -172
- package/dist/daemon/api/__tests__/profile-metadata-route.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/profile-metadata-route.test.js +0 -95
- package/dist/daemon/api/__tests__/reopen-delivery.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/reopen-delivery.test.js +0 -260
- package/dist/daemon/api/__tests__/seam/api-server.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/seam/api-server.test.js +0 -442
- package/dist/daemon/api/__tests__/seam/b10-attach-modelauth.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/seam/b10-attach-modelauth.test.js +0 -310
- package/dist/daemon/api/__tests__/seam/leaf-api-parity.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/seam/leaf-api-parity.test.js +0 -351
- package/dist/daemon/api/__tests__/seam/node-outcome-api.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/seam/node-outcome-api.test.js +0 -159
- package/dist/daemon/api/__tests__/seam/profile-delete.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/seam/profile-delete.test.js +0 -372
- package/dist/daemon/api/__tests__/submit-result.test.d.ts +0 -1
- package/dist/daemon/api/__tests__/submit-result.test.js +0 -215
- package/dist/migrations/__tests__/activation-concurrency.test.d.ts +0 -1
- package/dist/migrations/__tests__/activation-concurrency.test.js +0 -146
- package/dist/migrations/__tests__/activation.test.d.ts +0 -1
- package/dist/migrations/__tests__/activation.test.js +0 -152
- package/dist/migrations/__tests__/deletion-and-root-declaration.test.d.ts +0 -1
- package/dist/migrations/__tests__/deletion-and-root-declaration.test.js +0 -149
- package/dist/pi-extensions/__tests__/canvas-bash-valve.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/canvas-bash-valve.test.js +0 -86
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/canvas-context-intro.test.js +0 -364
- package/dist/pi-extensions/__tests__/canvas-goal-capture-envelope.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/canvas-goal-capture-envelope.test.js +0 -106
- package/dist/pi-extensions/__tests__/canvas-recap.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/canvas-recap.test.js +0 -62
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/canvas-stophook-agentend.test.js +0 -432
- package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/canvas-stophook-context-nudge.test.js +0 -152
- package/dist/pi-extensions/__tests__/canvas-structured-output.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/canvas-structured-output.test.js +0 -88
- package/dist/pi-extensions/__tests__/canvas-tool-guide.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/canvas-tool-guide.test.js +0 -96
- package/dist/pi-extensions/__tests__/integration/canvas-bash-valve.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/integration/canvas-bash-valve.test.js +0 -133
- package/dist/pi-extensions/__tests__/pre-command-gate.test.d.ts +0 -1
- package/dist/pi-extensions/__tests__/pre-command-gate.test.js +0 -232
- package/dist/shared/__tests__/env-boundary.test.d.ts +0 -1
- package/dist/shared/__tests__/env-boundary.test.js +0 -95
- package/dist/shared/__tests__/generated-context-grammar.test.d.ts +0 -1
- package/dist/shared/__tests__/generated-context-grammar.test.js +0 -80
- package/docs/compat/hearth-crtr-v1.md +0 -179
- package/docs/compat/hearth-crtr-v2.md +0 -177
- package/docs/compat/hearth-crtr-v3.md +0 -176
- package/docs/compat/hearth-crtr-v4.md +0 -182
- package/docs/compat/hearth-crtr-v5.md +0 -169
|
@@ -1,1708 +1,5 @@
|
|
|
1
|
-
// render/chat-view.ts — the render half of `crtr surface attach`.
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
// exported TUI components rather than reimplementing them. The viewer never
|
|
7
|
-
// spawns pi and never opens the session — it only consumes the relayed
|
|
8
|
-
// `AgentSessionEvent` stream + the `welcome` snapshot over `view.sock`.
|
|
9
|
-
//
|
|
10
|
-
// Ownership boundary: ChatView owns the chat scroll `Container` it is handed.
|
|
11
|
-
// Its activity state (working spinner, compaction/retry indicators) is signaled
|
|
12
|
-
// to the viewer-owned fixed slot when one is supplied. It does NOT own the
|
|
13
|
-
// editor, the footer, or the terminal title — those are chrome laid out by the
|
|
14
|
-
// attach command. Events that only affect that chrome
|
|
15
|
-
// (queue_update / session_info_changed / thinking_level_changed) are forwarded
|
|
16
|
-
// to the optional `onFooterEvent` sink instead of rendered here.
|
|
17
|
-
//
|
|
18
|
-
// Custom-tool rendering: extensions run in the broker, so the viewer generally
|
|
19
|
-
// has no extension `ToolDefinition`. The viewer supplies native renderers only
|
|
20
|
-
// for crouter-owned message/tool types it understands; other extension
|
|
21
|
-
// `renderCall`/`renderResult` hooks degrade to the default ToolExecutionComponent
|
|
22
|
-
// path while builtin tools, diffs, and partial-result streaming keep working.
|
|
23
|
-
import { Container, Loader, Spacer, Text } from '@earendil-works/pi-tui';
|
|
24
|
-
import { AssistantMessageComponent, BashExecutionComponent, BranchSummaryMessageComponent, CompactionSummaryMessageComponent, CustomMessageComponent, parseSkillBlock, SkillInvocationMessageComponent, ToolExecutionComponent, UserMessageComponent, } from '@earendil-works/pi-coding-agent';
|
|
25
|
-
import { attachMarkdownTheme } from '../config.js';
|
|
26
|
-
import { ContextMessageComponent } from './context-message.js';
|
|
27
|
-
import { presentationFor } from './card-presentation.js';
|
|
28
|
-
import { detectInlinePageResult, PageBlockComponent } from './page-block.js';
|
|
29
|
-
import { CRTR_OUTPUT_CUSTOM_TYPE, CrtrOutputMessageComponent, createCrtrBashToolDefinition, } from './crtr-output.js';
|
|
30
|
-
import { CRTR_CYCLE_DIVIDER_CUSTOM_TYPE, endedByAbort } from '../../../core/runtime/session-cycles.js';
|
|
31
|
-
import { parseCard } from '../../../shared/generated-context.js';
|
|
32
|
-
import { assistantVisibleText, isGroupBoundaryKind, isTrueUserMessage, } from '../../../shared/tool-groups.js';
|
|
33
|
-
import { transformDiagramFences } from './diagram.js';
|
|
34
|
-
import { styleAttachAgentMarkdown, styleAttachMarkdownSource, styleAttachMessageMarkdown, styleAttachSummaryMarkdown, } from './markdown-source.js';
|
|
35
|
-
import { createCrtrEditToolDefinition } from './edit-diff.js';
|
|
36
|
-
import { GroupActivityRecorder } from './group-activity.js';
|
|
37
|
-
import { GroupRecapComponent } from './group-recap.js';
|
|
38
|
-
import { FoldedToolCallController, bashCallBackgroundHintLines, createCrtrPlainBashToolDefinition, createCrtrReadToolDefinition, createCrtrWriteToolDefinition, } from './tool-calls.js';
|
|
39
|
-
import { ringCompletionBell } from '../chrome/completion-bell.js';
|
|
40
|
-
import { extractFilePaths } from '#core/human/visible-paths';
|
|
41
|
-
import { keepWhenCondensed, liveRegionStart } from './condensed-history.js';
|
|
42
|
-
import { ViewerAssistantMessageComponent } from './assistant-message.js';
|
|
43
|
-
import { CompositeViewportSource, MeasuredContainer, } from './measured-container.js';
|
|
44
|
-
import { readConfig, updateRawConfigAtomically } from '../../../core/config.js';
|
|
45
|
-
import { DEFAULT_CONDENSED_HISTORY, DEFAULT_LIVE_CYCLES } from '../../../types.js';
|
|
46
|
-
import { applySnapshot as projectSnapshot, applyToolGroupSummary as projectToolGroupSummary, applyWorkingActivity as projectWorkingActivity, bashEnd as projectBashEnd, bashOutput as projectBashOutput, bashStart as projectBashStart, initialConvState, reduce as projectEvent, } from '../../conversation/projection.js';
|
|
47
|
-
/** Theme-derived chrome colors (spinner / dim / error) are supplied by the
|
|
48
|
-
* attach command via `ChatViewOptions.palette` (built from the live theme in
|
|
49
|
-
* config.ts). pi does not re-export the raw `theme` instance, so standalone
|
|
50
|
-
* ChatViews receive the same semantic ANSI fallback palette. The message components
|
|
51
|
-
* use the attach Markdown theme, which preserves the user's pi theme while making
|
|
52
|
-
* fenced code visually distinct. */
|
|
53
|
-
const defaultDimStyle = (s) => `\x1b[2m${s}\x1b[22m`;
|
|
54
|
-
/** How many catch-up messages `applySnapshot` builds between event-loop yields.
|
|
55
|
-
* Keeps large non-streaming snapshots from monopolizing the main thread so
|
|
56
|
-
* queued keystrokes are serviced during construction. */
|
|
57
|
-
const SNAPSHOT_YIELD_EVERY = 50;
|
|
58
|
-
/** The user's `live_cycles` setting — how many trailing refresh-yield cycles the
|
|
59
|
-
* transcript renders at full fidelity. Read per ChatView (i.e. per attach), so
|
|
60
|
-
* `crtr sys config set live_cycles --value N` takes effect on the next attach
|
|
61
|
-
* without a daemon restart. A missing/unreadable config falls back to the
|
|
62
|
-
* shipped default. */
|
|
63
|
-
function readLiveCycles() {
|
|
64
|
-
try {
|
|
65
|
-
return readConfig('user').live_cycles;
|
|
66
|
-
}
|
|
67
|
-
catch {
|
|
68
|
-
return DEFAULT_LIVE_CYCLES;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
/** The user's `condensed_history` setting — which messages of an already-condensed
|
|
72
|
-
* cycle still render (the cycle dividers always do). Read per attach, like
|
|
73
|
-
* `live_cycles`. */
|
|
74
|
-
function readCondensedHistory() {
|
|
75
|
-
try {
|
|
76
|
-
return readConfig('user').condensed_history;
|
|
77
|
-
}
|
|
78
|
-
catch {
|
|
79
|
-
return DEFAULT_CONDENSED_HISTORY;
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
/** The user's `fold_finished_tools` setting — the persisted starting state of the
|
|
83
|
-
* fold view setting. Toggling it in a viewer writes it back (`persistFoldFinishedTools`),
|
|
84
|
-
* so the choice carries into later chats and later viewers. */
|
|
85
|
-
function readFoldFinishedTools() {
|
|
86
|
-
try {
|
|
87
|
-
return readConfig('user').fold_finished_tools;
|
|
88
|
-
}
|
|
89
|
-
catch {
|
|
90
|
-
return false;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
/** Whether this attach should start folded tool groups on their broker-generated
|
|
94
|
-
* summaries. The setting is deliberately attach-local: the broker remains the
|
|
95
|
-
* single summary producer and every viewer independently chooses its display. */
|
|
96
|
-
function readSummarizeToolCalls() {
|
|
97
|
-
try {
|
|
98
|
-
return readConfig('user').summarize_tool_calls;
|
|
99
|
-
}
|
|
100
|
-
catch {
|
|
101
|
-
return false;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
/** Whether folded tool recaps list their actual activity or use compact counts.
|
|
105
|
-
* The detailed form is the default; each attach reads its own presentation choice. */
|
|
106
|
-
function readDetailedToolRecaps() {
|
|
107
|
-
try {
|
|
108
|
-
return readConfig('user').detailed_tool_recaps;
|
|
109
|
-
}
|
|
110
|
-
catch {
|
|
111
|
-
return true;
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
/** Persist the fold view setting to user config. Best-effort: a viewer must never
|
|
115
|
-
* die because the config file is unwritable — the in-viewer toggle still applies. */
|
|
116
|
-
function persistFoldFinishedTools(value) {
|
|
117
|
-
try {
|
|
118
|
-
updateRawConfigAtomically('user', (latest) => ({ ...latest, fold_finished_tools: value }));
|
|
119
|
-
}
|
|
120
|
-
catch {
|
|
121
|
-
// ignored — the fold still applies to this viewer.
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
/** A component supports the Ctrl+O global tool-output toggle. Mirrors pi's
|
|
125
|
-
* `isExpandable` duck-type (interactive-mode.js): any rendered child carrying a
|
|
126
|
-
* `setExpanded(boolean)` method — tool executions, custom/compaction/branch/skill
|
|
127
|
-
* message components — participates; everything else (the status container, plain
|
|
128
|
-
* text, assistant/user bubbles) is skipped. */
|
|
129
|
-
function isExpandable(obj) {
|
|
130
|
-
return (typeof obj === 'object' &&
|
|
131
|
-
obj !== null &&
|
|
132
|
-
'setExpanded' in obj &&
|
|
133
|
-
typeof obj.setExpanded === 'function');
|
|
134
|
-
}
|
|
135
|
-
/** Every SGR escape, for measuring a line's visible content. */
|
|
136
|
-
const ANSI_RE = /\x1b\[[0-9;]*m/g;
|
|
137
|
-
/** Same match, with the SGR parameter list captured for rewriting. */
|
|
138
|
-
const SGR_PARAMS_RE = /\x1b\[([0-9;]*)m/g;
|
|
139
|
-
/** Drop every background-color SGR parameter from a line, keeping foreground and
|
|
140
|
-
* text styles. The minimized fold is a dense index of what ran, so the tool's
|
|
141
|
-
* pending/success/error background band (pi paints it across the full pane width)
|
|
142
|
-
* reads as noise there — one call per line, unhighlighted. `0` (full reset) is
|
|
143
|
-
* kept: it clears the background too, and nothing follows it to re-set one. */
|
|
144
|
-
function stripBackground(line) {
|
|
145
|
-
return line.replace(SGR_PARAMS_RE, (_whole, params) => {
|
|
146
|
-
const parts = params.split(';');
|
|
147
|
-
const kept = [];
|
|
148
|
-
for (let i = 0; i < parts.length; i++) {
|
|
149
|
-
const code = Number(parts[i] === '' ? 0 : parts[i]);
|
|
150
|
-
// Extended colors (`38` foreground, `48` background, `58` underline):
|
|
151
|
-
// consume the full sequence atomically so an RGB channel in the 40-47 or
|
|
152
|
-
// 100-107 range is not mistaken for a standalone background code.
|
|
153
|
-
if (code === 38 || code === 48 || code === 58) {
|
|
154
|
-
const mode = Number(parts[i + 1]);
|
|
155
|
-
const end = i + (mode === 5 ? 2 : mode === 2 ? 4 : 1);
|
|
156
|
-
if (code !== 48)
|
|
157
|
-
kept.push(...parts.slice(i, end + 1));
|
|
158
|
-
i = end;
|
|
159
|
-
continue;
|
|
160
|
-
}
|
|
161
|
-
// Standard (40-47) and bright (100-107) backgrounds. `49` (reset to the
|
|
162
|
-
// default background) is KEPT — it is the thing we want, and dropping it
|
|
163
|
-
// would let a neighbouring row's background bleed into this line.
|
|
164
|
-
if ((code >= 40 && code <= 47) || (code >= 100 && code <= 107))
|
|
165
|
-
continue;
|
|
166
|
-
kept.push(String(code));
|
|
167
|
-
}
|
|
168
|
-
return kept.length > 0 ? `\x1b[${kept.join(';')}m` : '';
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
/** Sender sections of an inbox card body; `parseCard` already read their entries.
|
|
172
|
-
* Whatever remains is other content riding the same digest. */
|
|
173
|
-
const INBOX_SENDER_SECTIONS = /<from\b[^>]*>[\s\S]*?<\/from>/g;
|
|
174
|
-
/** A tool component that can fold itself down to its CALL. pi's `ToolExecutionComponent`
|
|
175
|
-
* only knows expanded/collapsed, so each crtr-owned definition receives a local fold
|
|
176
|
-
* controller and captures the compact call component it renders. Folded render paints
|
|
177
|
-
* that captured call directly, dropping result and Box chrome while letting a wrapped
|
|
178
|
-
* path keep its natural rows. Tools without a crtr definition remain in full. */
|
|
179
|
-
/** A one-line separator that appears only while its adjacent tool group is
|
|
180
|
-
* folded. It stays in the transcript so toggling folded tools reflows the same
|
|
181
|
-
* message/tool boundary without rebuilding the chat. */
|
|
182
|
-
class FoldedToolSeparator extends Spacer {
|
|
183
|
-
folded = false;
|
|
184
|
-
separatesToolGroup = false;
|
|
185
|
-
setFolded(folded) {
|
|
186
|
-
this.folded = folded;
|
|
187
|
-
this.refresh();
|
|
188
|
-
}
|
|
189
|
-
setSeparatesToolGroup(separatesToolGroup) {
|
|
190
|
-
this.separatesToolGroup = separatesToolGroup;
|
|
191
|
-
this.refresh();
|
|
192
|
-
}
|
|
193
|
-
refresh() {
|
|
194
|
-
this.setLines(this.folded && this.separatesToolGroup ? 1 : 0);
|
|
195
|
-
}
|
|
196
|
-
}
|
|
197
|
-
class MinimizableToolComponent extends ToolExecutionComponent {
|
|
198
|
-
/** Bound by ChatView at append time; pi's base component does not expose it. */
|
|
199
|
-
activityCallId;
|
|
200
|
-
minimized = false;
|
|
201
|
-
expandedState = false;
|
|
202
|
-
foldController;
|
|
203
|
-
resultObserver;
|
|
204
|
-
/** A foldable definition owns its folded call component; it may also observe
|
|
205
|
-
* results before the imported shell renders them. */
|
|
206
|
-
setToolView(foldController, resultObserver) {
|
|
207
|
-
this.foldController = foldController;
|
|
208
|
-
this.resultObserver = resultObserver;
|
|
209
|
-
}
|
|
210
|
-
updateResult(...args) {
|
|
211
|
-
this.resultObserver?.(args[0], args[1] ?? false);
|
|
212
|
-
super.updateResult(...args);
|
|
213
|
-
}
|
|
214
|
-
setExpanded(expanded) {
|
|
215
|
-
this.expandedState = expanded;
|
|
216
|
-
super.setExpanded(expanded);
|
|
217
|
-
}
|
|
218
|
-
/** Flip the local fold state, then use the imported component's public
|
|
219
|
-
* expansion setter to rebuild its call renderer at the current setting. */
|
|
220
|
-
setMinimized(minimized) {
|
|
221
|
-
if (!this.foldController || this.minimized === minimized)
|
|
222
|
-
return;
|
|
223
|
-
this.minimized = minimized;
|
|
224
|
-
this.foldController.setFolded(minimized);
|
|
225
|
-
super.setExpanded(this.expandedState);
|
|
226
|
-
}
|
|
227
|
-
render(width) {
|
|
228
|
-
// The backgrounding row is appended HERE, by the component that owns the
|
|
229
|
-
// whole tool block, so it renders after the block's highlighted band ends
|
|
230
|
-
// instead of inside it. It is empty unless this is a bash call still running
|
|
231
|
-
// past the threshold.
|
|
232
|
-
if (!this.minimized) {
|
|
233
|
-
return [...super.render(width), ...bashCallBackgroundHintLines(this.foldController?.callComponent(), width)];
|
|
234
|
-
}
|
|
235
|
-
const call = this.foldController?.callComponent();
|
|
236
|
-
if (!call)
|
|
237
|
-
return super.render(width);
|
|
238
|
-
// trimEnd drops right-hand padding, which only existed to carry the
|
|
239
|
-
// background band these lines no longer paint.
|
|
240
|
-
return call.render(width)
|
|
241
|
-
.filter((line) => line.replace(ANSI_RE, '').trim().length > 0)
|
|
242
|
-
.map((line) => stripBackground(line).trimEnd());
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
const defaultErrorStyle = (s) => `\x1b[31m${s}\x1b[39m`;
|
|
246
|
-
const defaultAttachPalette = {
|
|
247
|
-
accent: (s) => `\x1b[33m${s}\x1b[39m`,
|
|
248
|
-
active: (s) => `\x1b[36m${s}\x1b[39m`,
|
|
249
|
-
info: (s) => `\x1b[34m${s}\x1b[39m`,
|
|
250
|
-
muted: defaultDimStyle,
|
|
251
|
-
faint: defaultDimStyle,
|
|
252
|
-
border: (s) => s,
|
|
253
|
-
surface: (s) => s,
|
|
254
|
-
bold: (s) => `\x1b[1m${s}\x1b[22m`,
|
|
255
|
-
error: defaultErrorStyle,
|
|
256
|
-
warning: (s) => `\x1b[33m${s}\x1b[39m`,
|
|
257
|
-
diffAdded: (s) => `\x1b[32m${s}\x1b[39m`,
|
|
258
|
-
diffRemoved: (s) => `\x1b[91m${s}\x1b[39m`,
|
|
259
|
-
bashMode: (s) => `\x1b[32m${s}\x1b[39m`,
|
|
260
|
-
bashModeAlt: (s) => `\x1b[92m${s}\x1b[39m`,
|
|
261
|
-
};
|
|
262
|
-
export class ChatView {
|
|
263
|
-
tui;
|
|
264
|
-
/** The chat scroll area handed in by the attach command. */
|
|
265
|
-
container;
|
|
266
|
-
/** Settled history is cached independently from the live status area so picker
|
|
267
|
-
* navigation does not re-render a long conversation on every key repeat. */
|
|
268
|
-
historyContainer = new MeasuredContainer();
|
|
269
|
-
/** Standalone ChatViews render activity inline; the attach viewer supplies
|
|
270
|
-
* `onActivityChange`, so its transcript excludes this container. */
|
|
271
|
-
statusContainer = new MeasuredContainer();
|
|
272
|
-
/** Optional banner, above history and status in the viewport's flat source. */
|
|
273
|
-
bannerContainer;
|
|
274
|
-
transcript;
|
|
275
|
-
/** Where `append()` puts a component. Normally `historyContainer`; retargeted to
|
|
276
|
-
* a nested container while condensed history is being built, so the same
|
|
277
|
-
* message-rendering path serves both regions. */
|
|
278
|
-
appendTarget = this.historyContainer;
|
|
279
|
-
/** Inline page blocks placed in this transcript, by page id — one block per
|
|
280
|
-
* page, so a `--replace` revision refreshes the block already on screen. */
|
|
281
|
-
pageBlocks = new Map();
|
|
282
|
-
inlinePageBlocks;
|
|
283
|
-
pageOpenHint;
|
|
284
|
-
backgroundBashHint;
|
|
285
|
-
/** Trailing cycles kept at full fidelity (config `live_cycles`). */
|
|
286
|
-
liveCycles;
|
|
287
|
-
/** Messages kept from a condensed cycle (config `condensed_history`). */
|
|
288
|
-
condensedHistory;
|
|
289
|
-
cwd;
|
|
290
|
-
showImages;
|
|
291
|
-
imageWidthCells;
|
|
292
|
-
hideThinking;
|
|
293
|
-
hiddenThinkingLabel;
|
|
294
|
-
/** Ctrl+O: pi's two-state tool-output expansion. */
|
|
295
|
-
toolOutputExpanded;
|
|
296
|
-
/** The view setting (Alt+C → z → f): fold every SETTLED tool call to its single
|
|
297
|
-
* call line. Independent of `toolOutputExpanded` — it survives an expand/collapse
|
|
298
|
-
* and only ever applies to tool calls that are done. */
|
|
299
|
-
foldSettledTools = readFoldFinishedTools();
|
|
300
|
-
/** Summary mode only changes Ctrl+O when both persistent settings are on. */
|
|
301
|
-
summarizeToolCalls = readSummarizeToolCalls();
|
|
302
|
-
detailedToolRecaps = readDetailedToolRecaps();
|
|
303
|
-
showGroupSummaries = this.summarizeToolCalls && this.foldSettledTools;
|
|
304
|
-
/** Groups exist only while building/rendering the full-fidelity live region. */
|
|
305
|
-
groups = [];
|
|
306
|
-
openGroup;
|
|
307
|
-
groupSummaries = new Map();
|
|
308
|
-
/** Node id → display name for every node spawned in this transcript, so a
|
|
309
|
-
* later group's finish notice can name the child rather than its id. */
|
|
310
|
-
nodeRoster = new Map();
|
|
311
|
-
streamingWasGroupMember = false;
|
|
312
|
-
onFooterEvent;
|
|
313
|
-
/** Viewer hook that places activity in its fixed slot, when available. */
|
|
314
|
-
onActivityChange;
|
|
315
|
-
/** Theme-derived colorizers for the activity/status area. */
|
|
316
|
-
spinnerStyle;
|
|
317
|
-
dimStyle;
|
|
318
|
-
errorStyle;
|
|
319
|
-
/** Palette shared with recap rows that render outside pi tool callbacks. */
|
|
320
|
-
recapPalette;
|
|
321
|
-
/** Bold accent for the expanded crtr-context label. */
|
|
322
|
-
labelStyle = (s) => `\x1b[1m${s}\x1b[22m`;
|
|
323
|
-
/** Viewer-local Markdown projection, handed to pi's message components so
|
|
324
|
-
* THEY apply it at render time with the exact content width. The viewer keeps
|
|
325
|
-
* no projected copy: the components hold canonical source, and each
|
|
326
|
-
* transformer reads live viewer state on every call. Diagrams apply only to
|
|
327
|
-
* assistant-authored Markdown. */
|
|
328
|
-
markdownTransformers = [
|
|
329
|
-
(markdown, { messageType, availableWidth }) => (messageType === 'assistant' ? transformDiagramFences(markdown, availableWidth) : markdown),
|
|
330
|
-
(markdown, { messageType }) => (messageType === 'user' ? styleAttachMarkdownSource(markdown) : styleAttachAgentMarkdown(markdown)),
|
|
331
|
-
];
|
|
332
|
-
/** The assistant message component currently being streamed (between
|
|
333
|
-
* message_start and message_end for an assistant turn). */
|
|
334
|
-
streamingComponent;
|
|
335
|
-
/** The separator immediately after the live assistant component. It becomes
|
|
336
|
-
* visible when that response has visible prose or thinking and folded tools. */
|
|
337
|
-
streamingToolSeparator;
|
|
338
|
-
/** Content classes for each separator, so Ctrl+T can add/remove thinking gaps
|
|
339
|
-
* without rebuilding the transcript. */
|
|
340
|
-
foldedToolSeparatorContents = new Map();
|
|
341
|
-
/** Tool-call id → its execution component, for the duration of the call. */
|
|
342
|
-
pendingTools = new Map();
|
|
343
|
-
/** The `!` bash component currently streaming (between bash_start and bash_end). */
|
|
344
|
-
bashComponent;
|
|
345
|
-
/** The single active activity loader (working/compaction/retry), if any. */
|
|
346
|
-
activityLoader;
|
|
347
|
-
/** The shared broker transcript state; this renderer projects it into pi TUI
|
|
348
|
-
* components while retaining terminal-only folding and virtualization. */
|
|
349
|
-
projection = initialConvState();
|
|
350
|
-
/** Broker-selected normal label for this turn; compaction/retry temporarily
|
|
351
|
-
* replace it and restore it when the run remains active. */
|
|
352
|
-
workingActivity = this.projection.workingActivity;
|
|
353
|
-
runActive = false;
|
|
354
|
-
// -- Single-writer snapshot ordering -------------------------------------
|
|
355
|
-
// A non-streaming catch-up yields to the event loop mid-build (so queued stdin
|
|
356
|
-
// drains), which opens a window where later broker frames could otherwise
|
|
357
|
-
// mutate a half-rebuilt transcript. These three fields make the ChatView a
|
|
358
|
-
// single ordered writer: applySnapshot is the only thing that mutates the
|
|
359
|
-
// view while a build is in flight, live frames are deferred and replayed in
|
|
360
|
-
// wire order once it finishes, and a newer welcome always supersedes an older
|
|
361
|
-
// build. See applySnapshot / deferIfBuilding.
|
|
362
|
-
/** True while applySnapshot is mid-build; live broker frames defer instead of
|
|
363
|
-
* mutating the partially-rebuilt view. */
|
|
364
|
-
applyingSnapshot = false;
|
|
365
|
-
/** Bumped on every applySnapshot. A build suspended at a yield compares this
|
|
366
|
-
* after resuming and abandons itself when a newer welcome has bumped it, so
|
|
367
|
-
* the newest welcome wins and stale state never overwrites the live view. */
|
|
368
|
-
snapshotGeneration = 0;
|
|
369
|
-
/** Live frames captured during an in-flight build (bound closures that re-run
|
|
370
|
-
* the original entry point), replayed in order when the build completes and
|
|
371
|
-
* dropped when a newer welcome supersedes the build. */
|
|
372
|
-
deferredFrames = [];
|
|
373
|
-
/** Text of the most recent assistant message, kept current from the welcome
|
|
374
|
-
* snapshot AND the live event stream so `/copy` (getLastAssistantText) works
|
|
375
|
-
* whether the message arrived before or after attach. */
|
|
376
|
-
lastAssistantText;
|
|
377
|
-
/** Existing file paths found anywhere in the rendered transcript, newest first. */
|
|
378
|
-
transcriptFilePaths = [];
|
|
379
|
-
/** Canonical copyable transcript blocks, in their rendered visual order. */
|
|
380
|
-
copyBlockRecords = [];
|
|
381
|
-
copyIndex = new Map();
|
|
382
|
-
/** Registrations made while building condensed history are collapsed onto its
|
|
383
|
-
* outer container once that container becomes a top-level viewport block. */
|
|
384
|
-
condensedCopyBlocks = new WeakMap();
|
|
385
|
-
constructor(tui, container, opts = {}) {
|
|
386
|
-
this.tui = tui;
|
|
387
|
-
this.container = container;
|
|
388
|
-
this.cwd = opts.cwd ?? process.cwd();
|
|
389
|
-
this.showImages = opts.showImages ?? true;
|
|
390
|
-
this.imageWidthCells = opts.imageWidthCells ?? 60;
|
|
391
|
-
this.hideThinking = opts.hideThinking ?? false;
|
|
392
|
-
this.hiddenThinkingLabel = opts.hiddenThinkingLabel ?? 'Thinking...';
|
|
393
|
-
this.toolOutputExpanded = opts.toolOutputExpanded ?? false;
|
|
394
|
-
this.liveCycles = opts.liveCycles ?? readLiveCycles();
|
|
395
|
-
this.condensedHistory = opts.condensedHistory ?? readCondensedHistory();
|
|
396
|
-
this.onFooterEvent = opts.onFooterEvent;
|
|
397
|
-
this.onActivityChange = opts.onActivityChange;
|
|
398
|
-
this.inlinePageBlocks = opts.inlinePageBlocks ?? false;
|
|
399
|
-
this.pageOpenHint = opts.pageOpenHint ?? (() => 'crtr human list');
|
|
400
|
-
this.backgroundBashHint = opts.backgroundBashHint ?? (() => null);
|
|
401
|
-
this.recapPalette = opts.palette ?? defaultAttachPalette;
|
|
402
|
-
this.spinnerStyle = this.recapPalette.active;
|
|
403
|
-
this.dimStyle = this.recapPalette.muted;
|
|
404
|
-
this.errorStyle = this.recapPalette.error;
|
|
405
|
-
// Banner sits above history and OUTSIDE it, so resetChat() (which clears only
|
|
406
|
-
// historyContainer) never wipes it — it persists across every welcome snapshot.
|
|
407
|
-
if (opts.banner && opts.banner.length > 0) {
|
|
408
|
-
const banner = new MeasuredContainer();
|
|
409
|
-
banner.addChild(new Spacer(1));
|
|
410
|
-
for (const line of opts.banner)
|
|
411
|
-
banner.addChild(new Text(line, 1, 0));
|
|
412
|
-
banner.addChild(new Spacer(1));
|
|
413
|
-
this.bannerContainer = banner;
|
|
414
|
-
this.container.addChild(banner);
|
|
415
|
-
}
|
|
416
|
-
this.container.addChild(this.historyContainer);
|
|
417
|
-
if (!this.onActivityChange)
|
|
418
|
-
this.container.addChild(this.statusContainer);
|
|
419
|
-
this.transcript = new CompositeViewportSource([
|
|
420
|
-
...(this.bannerContainer ? [this.bannerContainer] : []),
|
|
421
|
-
this.historyContainer,
|
|
422
|
-
...(this.onActivityChange ? [] : [this.statusContainer]),
|
|
423
|
-
]);
|
|
424
|
-
}
|
|
425
|
-
/** The transcript as one flat ordered block list for the viewport. */
|
|
426
|
-
transcriptSource() {
|
|
427
|
-
return this.transcript;
|
|
428
|
-
}
|
|
429
|
-
// Catch-up: render the welcome snapshot, then live events resume.
|
|
430
|
-
/** Render the full message history from a `welcome` snapshot. Ports pi's
|
|
431
|
-
* `renderSessionContext` (interactive-mode.js:2553): assistant messages spawn
|
|
432
|
-
* tool-execution components matched to their toolResult messages; everything
|
|
433
|
-
* else routes through `addMessageToChat`. The TUI's differential renderer +
|
|
434
|
-
* reflow-on-resize is automatic — no scrollback reconstruction needed. */
|
|
435
|
-
async applySnapshot(snapshot) {
|
|
436
|
-
// Open a new build generation. Any older build still suspended at a yield
|
|
437
|
-
// abandons itself when it resumes (generation check below), and live frames
|
|
438
|
-
// that were deferred against the transcript we are about to discard are
|
|
439
|
-
// dropped — a newer welcome always wins.
|
|
440
|
-
const generation = ++this.snapshotGeneration;
|
|
441
|
-
this.applyingSnapshot = true;
|
|
442
|
-
this.deferredFrames.length = 0;
|
|
443
|
-
this.resetChat();
|
|
444
|
-
this.projection = projectSnapshot(snapshot, this.projection);
|
|
445
|
-
this.workingActivity = this.projection.workingActivity;
|
|
446
|
-
this.runActive = this.projection.isStreaming;
|
|
447
|
-
this.seedToolGroupSummaries(this.projection.toolGroupSummaryDetails);
|
|
448
|
-
const renderedPendingTools = new Map();
|
|
449
|
-
const messages = this.projection.messages;
|
|
450
|
-
const lastIndex = messages.length - 1;
|
|
451
|
-
// Cycles older than the trailing `live_cycles` are condensed into one nested
|
|
452
|
-
// container before the live region is built. It retains only configured prose
|
|
453
|
-
// and cycle seams, avoiding old tool components while still reflowing on pane
|
|
454
|
-
// resize. `liveStart` is 0 until the node has yielded past the configured
|
|
455
|
-
// window, so a fresh node renders at full fidelity.
|
|
456
|
-
const liveStart = liveRegionStart(messages, this.liveCycles);
|
|
457
|
-
if (liveStart > 0) {
|
|
458
|
-
const condensed = await this.buildCondensedBlock(messages.slice(0, liveStart), generation);
|
|
459
|
-
if (generation !== this.snapshotGeneration)
|
|
460
|
-
return;
|
|
461
|
-
if (condensed)
|
|
462
|
-
this.appendCondensedBlock(condensed);
|
|
463
|
-
}
|
|
464
|
-
for (let i = liveStart; i < messages.length; i++) {
|
|
465
|
-
// Yield to the event loop every SNAPSHOT_YIELD_EVERY messages so queued
|
|
466
|
-
// stdin drains (keystrokes are handled instead of bursting after a long
|
|
467
|
-
// catch-up) while a big transcript constructs. Skipped for a STREAMING
|
|
468
|
-
// snapshot: its in-flight tail + pending tools must be bound before any
|
|
469
|
-
// relayed message_update/message_end lands, so it builds synchronously
|
|
470
|
-
// (no await → no broker frame can interleave and freeze the live bubble).
|
|
471
|
-
if (!this.projection.isStreaming &&
|
|
472
|
-
i > liveStart &&
|
|
473
|
-
(i - liveStart) % SNAPSHOT_YIELD_EVERY === 0) {
|
|
474
|
-
await new Promise((resolve) => setImmediate(resolve));
|
|
475
|
-
// A newer welcome arrived while we were suspended — abandon this stale
|
|
476
|
-
// build without touching the view (or the gate) it no longer owns.
|
|
477
|
-
if (generation !== this.snapshotGeneration)
|
|
478
|
-
return;
|
|
479
|
-
}
|
|
480
|
-
const message = messages[i];
|
|
481
|
-
if (message.role === 'assistant') {
|
|
482
|
-
// Keep the `/copy` source current from the catch-up transcript too, not
|
|
483
|
-
// only the live stream (you usually attach AFTER the last reply landed).
|
|
484
|
-
const text = assistantVisibleText(message);
|
|
485
|
-
if (text.trim()) {
|
|
486
|
-
this.lastAssistantText = text;
|
|
487
|
-
this.pushTranscriptText(text);
|
|
488
|
-
}
|
|
489
|
-
// If the snapshot caught an IN-FLIGHT assistant turn (state.isStreaming
|
|
490
|
-
// and this is the trailing, non-terminal assistant message), bind it as
|
|
491
|
-
// the live streaming component so the relayed message_update/message_end
|
|
492
|
-
// frames that follow `welcome` land on it. Otherwise the in-flight
|
|
493
|
-
// message would freeze at its snapshot value until the next turn — the
|
|
494
|
-
// common case, since you typically attach to a node that is working.
|
|
495
|
-
const isStreamingTail = i === lastIndex &&
|
|
496
|
-
this.projection.isStreaming &&
|
|
497
|
-
message.stopReason !== 'aborted' &&
|
|
498
|
-
message.stopReason !== 'error';
|
|
499
|
-
const hasProse = assistantVisibleText(message).trim() !== '';
|
|
500
|
-
const toolCalls = this.assistantToolCalls(message);
|
|
501
|
-
const endedWithFailure = message.stopReason === 'aborted' || message.stopReason === 'error';
|
|
502
|
-
const terminalErrorMessage = endedByAbort(message) ? 'Interrupted' : (message.errorMessage ?? 'Error');
|
|
503
|
-
// A terminal assistant failure remains visible as its own boundary. Settle
|
|
504
|
-
// any interrupted calls so the completed span before it can still recap.
|
|
505
|
-
if (endedWithFailure) {
|
|
506
|
-
for (const component of renderedPendingTools.values()) {
|
|
507
|
-
const result = { content: [{ type: 'text', text: terminalErrorMessage }], isError: true };
|
|
508
|
-
component.updateResult(result);
|
|
509
|
-
this.registerCopyBlock(component, 'tool', terminalErrorMessage);
|
|
510
|
-
this.settleGroupTool(component, result, true);
|
|
511
|
-
}
|
|
512
|
-
renderedPendingTools.clear();
|
|
513
|
-
}
|
|
514
|
-
if (hasProse || endedWithFailure)
|
|
515
|
-
this.closeOpenGroup();
|
|
516
|
-
let separator;
|
|
517
|
-
if (isStreamingTail) {
|
|
518
|
-
this.streamingComponent = new ViewerAssistantMessageComponent(undefined, this.hideThinking, attachMarkdownTheme(), this.hiddenThinkingLabel, this.markdownTransformers);
|
|
519
|
-
this.appendAssistantPart(this.streamingComponent, !hasProse);
|
|
520
|
-
this.registerCopyBlock(this.streamingComponent, 'assistant', '');
|
|
521
|
-
this.streamingWasGroupMember = !hasProse;
|
|
522
|
-
this.streamingComponent.updateContent(message);
|
|
523
|
-
this.registerCopyBlock(this.streamingComponent, 'assistant', assistantVisibleText(message));
|
|
524
|
-
separator = this.streamingToolSeparator = this.appendAssistantSeparator(!hasProse);
|
|
525
|
-
}
|
|
526
|
-
else {
|
|
527
|
-
separator = this.appendAssistantMessage(message, !hasProse && !endedWithFailure);
|
|
528
|
-
}
|
|
529
|
-
if (separator)
|
|
530
|
-
this.setAssistantSeparatorContent(separator, message);
|
|
531
|
-
for (const content of toolCalls) {
|
|
532
|
-
this.pushTranscriptValue(content.arguments);
|
|
533
|
-
const component = this.appendToolComponent(content.name, content.id, content.arguments);
|
|
534
|
-
// (isStreamingTail is never aborted/error, so its tools fall through to
|
|
535
|
-
// renderedPendingTools → pendingTools, where live tool events find them.)
|
|
536
|
-
if (message.stopReason === 'aborted' || message.stopReason === 'error') {
|
|
537
|
-
component.updateResult({ content: [{ type: 'text', text: terminalErrorMessage }], isError: true });
|
|
538
|
-
this.registerCopyBlock(component, 'tool', terminalErrorMessage);
|
|
539
|
-
this.settleGroupTool(component, { content: [{ type: 'text', text: terminalErrorMessage }], isError: true }, true);
|
|
540
|
-
}
|
|
541
|
-
else {
|
|
542
|
-
renderedPendingTools.set(content.id, component);
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
if (endedWithFailure)
|
|
546
|
-
this.closeOpenGroup();
|
|
547
|
-
}
|
|
548
|
-
else if (message.role === 'toolResult') {
|
|
549
|
-
this.pushTranscriptText(this.userMessageText(message));
|
|
550
|
-
const component = renderedPendingTools.get(message.toolCallId);
|
|
551
|
-
if (component) {
|
|
552
|
-
component.updateResult(message);
|
|
553
|
-
this.registerCopyBlock(component, 'tool', this.toolResultText(message));
|
|
554
|
-
this.historyContainer.markDirty(component);
|
|
555
|
-
this.settleGroupTool(component, message, message.isError === true);
|
|
556
|
-
renderedPendingTools.delete(message.toolCallId);
|
|
557
|
-
this.maybeAppendPageBlock(message);
|
|
558
|
-
}
|
|
559
|
-
}
|
|
560
|
-
else {
|
|
561
|
-
this.addMessageToChat(message);
|
|
562
|
-
}
|
|
563
|
-
}
|
|
564
|
-
for (const [id, component] of renderedPendingTools) {
|
|
565
|
-
this.pendingTools.set(id, component);
|
|
566
|
-
}
|
|
567
|
-
// A rebuild constructs fresh components, which are born unfolded; re-apply the
|
|
568
|
-
// setting so a reconnect/welcome does not silently unfold the transcript.
|
|
569
|
-
this.applyToolDisplay();
|
|
570
|
-
// If we attached mid-turn, the `agent_start` that spins up the working loader
|
|
571
|
-
// already fired before we connected — restore it from the snapshot's streaming
|
|
572
|
-
// state so an actively-working node shows the spinner right away.
|
|
573
|
-
if (this.projection.isStreaming)
|
|
574
|
-
this.setActivity(this.makeLoader(this.workingActivity));
|
|
575
|
-
this.tui.requestRender();
|
|
576
|
-
// Build complete and still current (a mismatch would have returned above):
|
|
577
|
-
// open the gate and replay, in wire order, any live frames that arrived
|
|
578
|
-
// during construction so they land on the finished transcript.
|
|
579
|
-
this.applyingSnapshot = false;
|
|
580
|
-
this.replayDeferredFrames();
|
|
581
|
-
}
|
|
582
|
-
/**
|
|
583
|
-
* Build the condensed form of the already-finished cycles as a nested component
|
|
584
|
-
* container, or return undefined when nothing survives condensation.
|
|
585
|
-
*
|
|
586
|
-
* Reuses `addMessageToChat` by retargeting `append()` at the nested container, so
|
|
587
|
-
* condensed history uses the same renderer as live history with tool traffic
|
|
588
|
-
* filtered out. The outer history cache keeps stable-width frames cheap, while
|
|
589
|
-
* preserving the components lets pane-width changes reflow their content. The
|
|
590
|
-
* build yields on the live cadence and abandons itself when a newer welcome
|
|
591
|
-
* supersedes this generation.
|
|
592
|
-
*/
|
|
593
|
-
async buildCondensedBlock(messages, generation) {
|
|
594
|
-
const condensed = new Container();
|
|
595
|
-
const previousTarget = this.appendTarget;
|
|
596
|
-
const copyBlocks = [];
|
|
597
|
-
this.appendTarget = condensed;
|
|
598
|
-
this.condensedCopyBlocks.set(condensed, copyBlocks);
|
|
599
|
-
try {
|
|
600
|
-
let built = 0;
|
|
601
|
-
for (const message of messages) {
|
|
602
|
-
if (!keepWhenCondensed(message, this.condensedHistory))
|
|
603
|
-
continue;
|
|
604
|
-
if (built > 0 && built % SNAPSHOT_YIELD_EVERY === 0) {
|
|
605
|
-
await new Promise((resolve) => setImmediate(resolve));
|
|
606
|
-
if (generation !== this.snapshotGeneration)
|
|
607
|
-
return undefined;
|
|
608
|
-
}
|
|
609
|
-
built++;
|
|
610
|
-
// Condensed prose still feeds the @-path picker; `lastAssistantText` (the
|
|
611
|
-
// `/copy` source) deliberately does not — the live region always holds the
|
|
612
|
-
// newest reply.
|
|
613
|
-
this.pushTranscriptText(this.userMessageText(message));
|
|
614
|
-
this.addMessageToChat(message);
|
|
615
|
-
}
|
|
616
|
-
}
|
|
617
|
-
finally {
|
|
618
|
-
this.appendTarget = previousTarget;
|
|
619
|
-
this.condensedCopyBlocks.delete(condensed);
|
|
620
|
-
}
|
|
621
|
-
return condensed.children.length > 0 ? { component: condensed, copyBlocks } : undefined;
|
|
622
|
-
}
|
|
623
|
-
/** Defer a live broker frame when a snapshot build is in flight. Returns true
|
|
624
|
-
* (and enqueues the replay closure) while building so the caller returns
|
|
625
|
-
* without mutating the half-rebuilt view; false when the caller may proceed.
|
|
626
|
-
* This is the single-writer gate every live-frame entry point passes through. */
|
|
627
|
-
deferIfBuilding(replay) {
|
|
628
|
-
if (!this.applyingSnapshot)
|
|
629
|
-
return false;
|
|
630
|
-
this.deferredFrames.push(replay);
|
|
631
|
-
return true;
|
|
632
|
-
}
|
|
633
|
-
/** Replay deferred live frames in wire order. The gate is already open, so each
|
|
634
|
-
* closure re-enters its entry point and dispatches immediately. */
|
|
635
|
-
replayDeferredFrames() {
|
|
636
|
-
const frames = this.deferredFrames.splice(0);
|
|
637
|
-
for (const replay of frames)
|
|
638
|
-
replay();
|
|
639
|
-
}
|
|
640
|
-
/** Apply the broker's random choice for a newly received user message. */
|
|
641
|
-
setWorkingActivity(activity) {
|
|
642
|
-
if (this.deferIfBuilding(() => this.setWorkingActivity(activity)))
|
|
643
|
-
return;
|
|
644
|
-
const wasShowingWorkingActivity = this.projection.activity === this.workingActivity;
|
|
645
|
-
this.projection = projectWorkingActivity(this.projection, activity);
|
|
646
|
-
this.workingActivity = this.projection.workingActivity;
|
|
647
|
-
if (this.runActive && wasShowingWorkingActivity)
|
|
648
|
-
this.setActivity(this.makeLoader(this.workingActivity));
|
|
649
|
-
}
|
|
650
|
-
/** Clear live turn state after the broker reports completion or the viewer observes dormancy. */
|
|
651
|
-
settleRun() {
|
|
652
|
-
this.runActive = false;
|
|
653
|
-
for (const component of this.pendingTools.values())
|
|
654
|
-
this.settleGroupTool(component);
|
|
655
|
-
if (this.streamingComponent) {
|
|
656
|
-
this.historyContainer.removeChild(this.streamingComponent);
|
|
657
|
-
this.unregisterCopyBlock(this.streamingComponent);
|
|
658
|
-
this.streamingComponent = undefined;
|
|
659
|
-
}
|
|
660
|
-
this.streamingToolSeparator = undefined;
|
|
661
|
-
this.pendingTools.clear();
|
|
662
|
-
this.applyToolDisplay();
|
|
663
|
-
this.setActivity(undefined);
|
|
664
|
-
this.settleBashComponent();
|
|
665
|
-
}
|
|
666
|
-
/** Stop any spinning activity loader. A one-shot `crtr surface attach` process lets its
|
|
667
|
-
* timers die with the process, but if T7 reuses a ChatView across reconnects in
|
|
668
|
-
* one process it should call this on detach to avoid a leaked interval. */
|
|
669
|
-
dispose() {
|
|
670
|
-
this.settleRun();
|
|
671
|
-
}
|
|
672
|
-
// Global display toggles (Ctrl+O / Ctrl+T), driven by the input controller.
|
|
673
|
-
// Pure client-side render state — no broker round-trip — ported from pi's
|
|
674
|
-
// `setToolsExpanded` / `toggleThinkingBlockVisibility`.
|
|
675
|
-
/** Ctrl+O prefers summaries when the user enabled both folding and summary
|
|
676
|
-
* generation. */
|
|
677
|
-
toggleToolsExpanded() {
|
|
678
|
-
let result;
|
|
679
|
-
if (this.summarizeToolCalls && this.foldSettledTools) {
|
|
680
|
-
this.showGroupSummaries = !this.showGroupSummaries;
|
|
681
|
-
this.toolOutputExpanded = !this.showGroupSummaries;
|
|
682
|
-
result = { kind: 'summaries', shown: this.showGroupSummaries };
|
|
683
|
-
}
|
|
684
|
-
else {
|
|
685
|
-
this.toolOutputExpanded = !this.toolOutputExpanded;
|
|
686
|
-
result = { kind: 'output', expanded: this.toolOutputExpanded };
|
|
687
|
-
}
|
|
688
|
-
this.applyToolDisplay();
|
|
689
|
-
return result;
|
|
690
|
-
}
|
|
691
|
-
/** The `fold finished tool calls` view setting (`/fold-tools`, Alt+C → z → f).
|
|
692
|
-
* Returns the new state so the caller can surface a notice. */
|
|
693
|
-
toggleFoldSettledTools() {
|
|
694
|
-
this.foldSettledTools = !this.foldSettledTools;
|
|
695
|
-
persistFoldFinishedTools(this.foldSettledTools);
|
|
696
|
-
// Turning folding back on restores the configured default (summaries),
|
|
697
|
-
// rather than preserving a stale Ctrl+O choice from an unfolded view.
|
|
698
|
-
if (this.summarizeToolCalls && this.foldSettledTools)
|
|
699
|
-
this.showGroupSummaries = true;
|
|
700
|
-
this.applyToolDisplay();
|
|
701
|
-
return this.foldSettledTools;
|
|
702
|
-
}
|
|
703
|
-
/** Push both display settings onto every rendered component. A tool call still in
|
|
704
|
-
* flight is never hidden or minimized. Only a settled group with a broker-known
|
|
705
|
-
* summary collapses; incomplete/failed generation leaves its folded call lines. */
|
|
706
|
-
applyToolDisplay() {
|
|
707
|
-
const inFlight = new Set(this.pendingTools.values());
|
|
708
|
-
for (const group of this.groups)
|
|
709
|
-
for (const tool of group.inFlight)
|
|
710
|
-
inFlight.add(tool);
|
|
711
|
-
for (const child of this.historyContainer.children) {
|
|
712
|
-
if (child instanceof MinimizableToolComponent)
|
|
713
|
-
child.setMinimized(this.foldSettledTools && !inFlight.has(child));
|
|
714
|
-
if (isExpandable(child))
|
|
715
|
-
child.setExpanded(this.toolOutputExpanded);
|
|
716
|
-
}
|
|
717
|
-
for (const group of this.groups)
|
|
718
|
-
this.applyGroupDisplay(group);
|
|
719
|
-
this.updateFoldedToolSeparators(inFlight);
|
|
720
|
-
this.historyContainer.markDirty();
|
|
721
|
-
this.tui.requestRender();
|
|
722
|
-
}
|
|
723
|
-
/** Ctrl+T / app.thinking.toggle — flip thinking-block visibility and apply it to
|
|
724
|
-
* every assistant message (the in-flight streaming bubble is itself a child of
|
|
725
|
-
* the container, so the loop covers it too). Returns the new HIDDEN state. */
|
|
726
|
-
toggleThinking() {
|
|
727
|
-
this.hideThinking = !this.hideThinking;
|
|
728
|
-
for (const child of this.historyContainer.children) {
|
|
729
|
-
if (child instanceof AssistantMessageComponent)
|
|
730
|
-
child.setHideThinkingBlock(this.hideThinking);
|
|
731
|
-
}
|
|
732
|
-
for (const [separator, content] of this.foldedToolSeparatorContents) {
|
|
733
|
-
separator.setSeparatesToolGroup(content.hasText || (!this.hideThinking && content.hasThinking));
|
|
734
|
-
}
|
|
735
|
-
this.historyContainer.markDirty();
|
|
736
|
-
this.tui.requestRender();
|
|
737
|
-
return this.hideThinking;
|
|
738
|
-
}
|
|
739
|
-
// Live stream: the 15-of-17-case handleEvent port (turn_start/turn_end no-op,
|
|
740
|
-
// exactly as interactive pi falls through default for those two).
|
|
741
|
-
handleEvent(event) {
|
|
742
|
-
// Order behind an in-flight catch-up: a live turn that starts while a large
|
|
743
|
-
// welcome is still building is replayed after it, never interleaved into it.
|
|
744
|
-
if (this.deferIfBuilding(() => this.handleEvent(event)))
|
|
745
|
-
return;
|
|
746
|
-
this.projection = projectEvent(this.projection, event);
|
|
747
|
-
switch (event.type) {
|
|
748
|
-
case 'agent_start': {
|
|
749
|
-
this.runActive = this.projection.isStreaming;
|
|
750
|
-
for (const component of this.pendingTools.values())
|
|
751
|
-
this.settleGroupTool(component);
|
|
752
|
-
this.pendingTools.clear();
|
|
753
|
-
this.setActivity(this.makeLoader(this.workingActivity));
|
|
754
|
-
break;
|
|
755
|
-
}
|
|
756
|
-
case 'agent_end': {
|
|
757
|
-
this.settleRun();
|
|
758
|
-
// The node you're watching just finished its turn and handed control
|
|
759
|
-
// back — ring the completion bell (the Claude-Code Stop-hook ding).
|
|
760
|
-
// Best-effort/detached; gated on the `completion_bell` config setting.
|
|
761
|
-
// Only ever reached inside a live viewer pane, so a headless/background
|
|
762
|
-
// node (no ChatView) is always silent.
|
|
763
|
-
ringCompletionBell();
|
|
764
|
-
break;
|
|
765
|
-
}
|
|
766
|
-
// The whole run has truly settled (after any recovery/continuations). This
|
|
767
|
-
// is the broker's canonical turn-over signal and is always relayed, so use
|
|
768
|
-
// it as a safety net to clear a lingering activity loader: a missed or
|
|
769
|
-
// abnormal `agent_end` would otherwise leave a dormant, between-wakes node
|
|
770
|
-
// showing a frozen `Working…` spinner. No bell here — `agent_end` already
|
|
771
|
-
// rang it on the normal path; this only cleans up display state.
|
|
772
|
-
case 'agent_settled': {
|
|
773
|
-
this.settleRun();
|
|
774
|
-
break;
|
|
775
|
-
}
|
|
776
|
-
case 'message_start': {
|
|
777
|
-
if (event.message.role === 'custom' || event.message.role === 'user') {
|
|
778
|
-
this.addMessageToChat(event.message);
|
|
779
|
-
}
|
|
780
|
-
else if (event.message.role === 'assistant') {
|
|
781
|
-
const hasProse = assistantVisibleText(event.message).trim() !== '';
|
|
782
|
-
if (hasProse)
|
|
783
|
-
this.closeOpenGroup();
|
|
784
|
-
this.streamingComponent = new ViewerAssistantMessageComponent(undefined, this.hideThinking, attachMarkdownTheme(), this.hiddenThinkingLabel, this.markdownTransformers);
|
|
785
|
-
this.streamingWasGroupMember = !hasProse;
|
|
786
|
-
this.appendAssistantPart(this.streamingComponent, !hasProse);
|
|
787
|
-
this.registerCopyBlock(this.streamingComponent, 'assistant', '');
|
|
788
|
-
this.streamingComponent.updateContent(event.message);
|
|
789
|
-
this.registerCopyBlock(this.streamingComponent, 'assistant', assistantVisibleText(event.message));
|
|
790
|
-
this.streamingToolSeparator = this.appendAssistantSeparator(!hasProse);
|
|
791
|
-
this.setAssistantSeparatorContent(this.streamingToolSeparator, event.message);
|
|
792
|
-
}
|
|
793
|
-
break;
|
|
794
|
-
}
|
|
795
|
-
case 'message_update': {
|
|
796
|
-
if (this.streamingComponent && event.message.role === 'assistant') {
|
|
797
|
-
this.promoteStreamingAssistantToBoundary(event.message);
|
|
798
|
-
// Incomplete Mermaid fences and HTML pairs stay literal until their
|
|
799
|
-
// closing marker arrives; the transformers upgrade them on the render
|
|
800
|
-
// that follows, with no separate mid-stream path.
|
|
801
|
-
this.streamingComponent.updateContent(event.message);
|
|
802
|
-
this.registerCopyBlock(this.streamingComponent, 'assistant', assistantVisibleText(event.message));
|
|
803
|
-
this.historyContainer.markDirty(this.streamingComponent);
|
|
804
|
-
const toolCalls = this.assistantToolCalls(event.message);
|
|
805
|
-
if (this.streamingToolSeparator)
|
|
806
|
-
this.setAssistantSeparatorContent(this.streamingToolSeparator, event.message);
|
|
807
|
-
for (const content of toolCalls) {
|
|
808
|
-
this.pushTranscriptValue(content.arguments);
|
|
809
|
-
const existing = this.pendingTools.get(content.id);
|
|
810
|
-
if (existing) {
|
|
811
|
-
existing.updateArgs(content.arguments);
|
|
812
|
-
this.noteGroupTool(existing, content.name, content.arguments);
|
|
813
|
-
this.historyContainer.markDirty(existing);
|
|
814
|
-
}
|
|
815
|
-
else {
|
|
816
|
-
const component = this.appendToolComponent(content.name, content.id, content.arguments);
|
|
817
|
-
this.pendingTools.set(content.id, component);
|
|
818
|
-
}
|
|
819
|
-
}
|
|
820
|
-
}
|
|
821
|
-
break;
|
|
822
|
-
}
|
|
823
|
-
case 'message_end': {
|
|
824
|
-
if (event.message.role !== 'assistant')
|
|
825
|
-
break;
|
|
826
|
-
const endedWithFailure = event.message.stopReason === 'aborted' || event.message.stopReason === 'error';
|
|
827
|
-
// A terminal failure is always its own visible boundary, including an
|
|
828
|
-
// empty abort created by yield or a daemon restart.
|
|
829
|
-
this.promoteStreamingAssistantToBoundary(event.message, endedWithFailure);
|
|
830
|
-
// Stash the completed reply's text for `/copy` (skip aborted/error turns,
|
|
831
|
-
// whose text is partial or absent).
|
|
832
|
-
if (this.streamingComponent)
|
|
833
|
-
this.registerCopyBlock(this.streamingComponent, 'assistant', assistantVisibleText(event.message));
|
|
834
|
-
if (event.message.stopReason !== 'aborted' && event.message.stopReason !== 'error') {
|
|
835
|
-
const text = assistantVisibleText(event.message);
|
|
836
|
-
if (text.trim()) {
|
|
837
|
-
this.lastAssistantText = text;
|
|
838
|
-
this.pushTranscriptText(text);
|
|
839
|
-
}
|
|
840
|
-
}
|
|
841
|
-
if (this.streamingComponent) {
|
|
842
|
-
const stopReason = event.message.stopReason;
|
|
843
|
-
let errorMessage = event.message.errorMessage;
|
|
844
|
-
// An aborted turn may be a user interrupt or a lifecycle interruption
|
|
845
|
-
// (a refresh-yield aborts its own turn). Providers spell it several
|
|
846
|
-
// ways — including `stopReason: 'error'` carrying a bare AbortError,
|
|
847
|
-
// which would otherwise render as a red `Error: This operation was
|
|
848
|
-
// aborted` for a perfectly healthy yield — so override it outright
|
|
849
|
-
// with one plain, human label.
|
|
850
|
-
if (endedByAbort(event.message)) {
|
|
851
|
-
errorMessage = 'Interrupted';
|
|
852
|
-
// Surface the abort on the assistant bubble itself, mirroring pi
|
|
853
|
-
// (interactive-mode.js:2280 sets streamingMessage.errorMessage before
|
|
854
|
-
// updateContent) so the rendered message shows the annotation. The
|
|
855
|
-
// stopReason moves with it: pi's component reserves its red
|
|
856
|
-
// `Error: …` line for stopReason 'error', and an abort is not one.
|
|
857
|
-
event.message.errorMessage = errorMessage;
|
|
858
|
-
event.message.stopReason = 'aborted';
|
|
859
|
-
}
|
|
860
|
-
this.streamingComponent.updateContent(event.message);
|
|
861
|
-
if (stopReason === 'aborted' || stopReason === 'error') {
|
|
862
|
-
const text = errorMessage ?? 'Error';
|
|
863
|
-
for (const component of this.pendingTools.values()) {
|
|
864
|
-
component.updateResult({ content: [{ type: 'text', text }], isError: true });
|
|
865
|
-
this.registerCopyBlock(component, 'tool', text);
|
|
866
|
-
this.settleGroupTool(component, { content: [{ type: 'text', text }], isError: true }, true);
|
|
867
|
-
this.historyContainer.markDirty(component);
|
|
868
|
-
}
|
|
869
|
-
this.pendingTools.clear();
|
|
870
|
-
}
|
|
871
|
-
else {
|
|
872
|
-
// Finalize renderer caches now that every tool argument is complete.
|
|
873
|
-
for (const component of this.pendingTools.values()) {
|
|
874
|
-
component.setArgsComplete();
|
|
875
|
-
this.historyContainer.markDirty(component);
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
this.historyContainer.markDirty(this.streamingComponent);
|
|
879
|
-
this.streamingComponent = undefined;
|
|
880
|
-
this.streamingToolSeparator = undefined;
|
|
881
|
-
}
|
|
882
|
-
if (endedWithFailure) {
|
|
883
|
-
this.closeOpenGroup();
|
|
884
|
-
// A summary normally follows this terminal frame, but re-evaluate now
|
|
885
|
-
// too so an early recap immediately folds the tools before this seam.
|
|
886
|
-
this.applyToolDisplay();
|
|
887
|
-
}
|
|
888
|
-
break;
|
|
889
|
-
}
|
|
890
|
-
case 'tool_execution_start': {
|
|
891
|
-
this.pushTranscriptValue(event.args);
|
|
892
|
-
let component = this.pendingTools.get(event.toolCallId);
|
|
893
|
-
if (!component) {
|
|
894
|
-
component = this.appendToolComponent(event.toolName, event.toolCallId, event.args);
|
|
895
|
-
this.pendingTools.set(event.toolCallId, component);
|
|
896
|
-
}
|
|
897
|
-
else {
|
|
898
|
-
this.noteGroupTool(component, event.toolName, event.args);
|
|
899
|
-
}
|
|
900
|
-
component.markExecutionStarted();
|
|
901
|
-
this.historyContainer.markDirty(component);
|
|
902
|
-
break;
|
|
903
|
-
}
|
|
904
|
-
case 'tool_execution_update': {
|
|
905
|
-
const result = this.projection.partialToolResults.get(event.toolCallId) ?? event.partialResult;
|
|
906
|
-
this.pushTranscriptValue(result);
|
|
907
|
-
const component = this.pendingTools.get(event.toolCallId);
|
|
908
|
-
if (component) {
|
|
909
|
-
component.updateResult(result, true);
|
|
910
|
-
this.registerCopyBlock(component, 'tool', this.toolResultText(result));
|
|
911
|
-
this.historyContainer.markDirty(component);
|
|
912
|
-
}
|
|
913
|
-
break;
|
|
914
|
-
}
|
|
915
|
-
case 'tool_execution_end': {
|
|
916
|
-
const result = this.projection.partialToolResults.get(event.toolCallId) ?? event.result;
|
|
917
|
-
this.pushTranscriptValue(result);
|
|
918
|
-
const component = this.pendingTools.get(event.toolCallId);
|
|
919
|
-
if (component) {
|
|
920
|
-
component.updateResult(result);
|
|
921
|
-
this.registerCopyBlock(component, 'tool', this.toolResultText(result));
|
|
922
|
-
this.pendingTools.delete(event.toolCallId);
|
|
923
|
-
this.settleGroupTool(component, result, event.isError);
|
|
924
|
-
this.applyToolDisplay();
|
|
925
|
-
this.historyContainer.markDirty(component);
|
|
926
|
-
this.maybeAppendPageBlock(result);
|
|
927
|
-
}
|
|
928
|
-
break;
|
|
929
|
-
}
|
|
930
|
-
case 'compaction_start': {
|
|
931
|
-
const label = event.reason === 'manual' ? 'Compacting context...' : 'Auto-compacting...';
|
|
932
|
-
this.setActivity(this.makeLoader(label));
|
|
933
|
-
break;
|
|
934
|
-
}
|
|
935
|
-
case 'compaction_end': {
|
|
936
|
-
this.setActivity(this.runActive ? this.makeLoader(this.workingActivity) : undefined);
|
|
937
|
-
if (event.aborted) {
|
|
938
|
-
this.showStatus(event.reason === 'manual' ? 'Compaction cancelled' : 'Auto-compaction cancelled');
|
|
939
|
-
}
|
|
940
|
-
else if (event.result) {
|
|
941
|
-
// 0.78.1 divergence from the §3.2 sketch: `compaction_end` carries only
|
|
942
|
-
// the CompactionResult (summary + tokensBefore), NOT the post-compaction
|
|
943
|
-
// message list — so the viewer cannot clear+rebuild the transcript the
|
|
944
|
-
// way in-process pi does (it rebuilds from its own SessionManager). We
|
|
945
|
-
// append the compaction summary marker instead and KEEP the
|
|
946
|
-
// pre-compaction scrollback for the rest of this attach session; a fresh
|
|
947
|
-
// re-attach gets the already-compacted history via `welcome`. (Reported
|
|
948
|
-
// in T5's final.)
|
|
949
|
-
this.addMessageToChat({
|
|
950
|
-
role: 'compactionSummary',
|
|
951
|
-
summary: event.result.summary,
|
|
952
|
-
tokensBefore: event.result.tokensBefore,
|
|
953
|
-
timestamp: Date.now(),
|
|
954
|
-
});
|
|
955
|
-
}
|
|
956
|
-
else if (event.errorMessage) {
|
|
957
|
-
this.showError(event.errorMessage);
|
|
958
|
-
}
|
|
959
|
-
break;
|
|
960
|
-
}
|
|
961
|
-
case 'auto_retry_start': {
|
|
962
|
-
const seconds = Math.ceil(event.delayMs / 1000);
|
|
963
|
-
this.setActivity(this.makeLoader(`Retrying (${event.attempt}/${event.maxAttempts}) in ${seconds}s...`));
|
|
964
|
-
break;
|
|
965
|
-
}
|
|
966
|
-
case 'auto_retry_end': {
|
|
967
|
-
this.setActivity(this.runActive ? this.makeLoader(this.workingActivity) : undefined);
|
|
968
|
-
if (!event.success) {
|
|
969
|
-
this.showError(`Retry failed after ${event.attempt} attempts: ${event.finalError ?? 'Unknown error'}`);
|
|
970
|
-
}
|
|
971
|
-
break;
|
|
972
|
-
}
|
|
973
|
-
// Footer/header-only — ChatView owns no footer; forward to the sink.
|
|
974
|
-
case 'queue_update':
|
|
975
|
-
case 'session_info_changed':
|
|
976
|
-
case 'thinking_level_changed':
|
|
977
|
-
this.onFooterEvent?.(event);
|
|
978
|
-
break;
|
|
979
|
-
// turn_start / turn_end — interactive pi ignores these (falls through
|
|
980
|
-
// default); the viewer does too.
|
|
981
|
-
default:
|
|
982
|
-
break;
|
|
983
|
-
}
|
|
984
|
-
// No unconditional markDirty here: appends/removes invalidate through
|
|
985
|
-
// MeasuredContainer, and branches that mutate a child in place explicitly
|
|
986
|
-
// mark it dirty. Activity-only events leave settled history cached while the
|
|
987
|
-
// independent status loader animates.
|
|
988
|
-
this.tui.requestRender();
|
|
989
|
-
}
|
|
990
|
-
// `!` bash live stream (broker bash_start/bash_output/bash_end frames). Mirrors
|
|
991
|
-
// pi interactive mode's `!` handling: create the component on start, stream
|
|
992
|
-
// chunks into it, mark complete on end. The persisted `bashExecution` message
|
|
993
|
-
// also rides the next snapshot, so this only drives the LIVE view.
|
|
994
|
-
bashStart(command, excludeFromContext) {
|
|
995
|
-
if (this.deferIfBuilding(() => this.bashStart(command, excludeFromContext)))
|
|
996
|
-
return;
|
|
997
|
-
this.projection = projectBashStart(this.projection, command, excludeFromContext);
|
|
998
|
-
this.closeOpenGroup();
|
|
999
|
-
this.settleBashComponent();
|
|
1000
|
-
let component;
|
|
1001
|
-
component = new BashExecutionComponent(command, this.componentTui(() => component), excludeFromContext);
|
|
1002
|
-
this.bashComponent = component;
|
|
1003
|
-
this.append(component);
|
|
1004
|
-
this.tui.requestRender();
|
|
1005
|
-
}
|
|
1006
|
-
bashOutput(chunk) {
|
|
1007
|
-
if (this.deferIfBuilding(() => this.bashOutput(chunk)))
|
|
1008
|
-
return;
|
|
1009
|
-
this.projection = projectBashOutput(this.projection, chunk);
|
|
1010
|
-
this.pushTranscriptText(chunk);
|
|
1011
|
-
if (this.bashComponent) {
|
|
1012
|
-
this.bashComponent.appendOutput(chunk);
|
|
1013
|
-
this.historyContainer.markDirty(this.bashComponent);
|
|
1014
|
-
}
|
|
1015
|
-
this.tui.requestRender();
|
|
1016
|
-
}
|
|
1017
|
-
bashEnd(result) {
|
|
1018
|
-
if (this.deferIfBuilding(() => this.bashEnd(result)))
|
|
1019
|
-
return;
|
|
1020
|
-
this.projection = projectBashEnd(this.projection, result);
|
|
1021
|
-
this.settleBashComponent(result);
|
|
1022
|
-
this.tui.requestRender();
|
|
1023
|
-
}
|
|
1024
|
-
// Rebuild path (ports addMessageToChat, interactive-mode.js:2483).
|
|
1025
|
-
addMessageToChat(message) {
|
|
1026
|
-
// Crouter-generated context retains its runtime role (user vs custom) so
|
|
1027
|
-
// delivery to the model is unchanged, but every attached view presents it
|
|
1028
|
-
// through one compact disclosure contract. The producer's envelope is what
|
|
1029
|
-
// classifies, so an ordinary user prompt cannot acquire this treatment and
|
|
1030
|
-
// saved transcripts gain it too.
|
|
1031
|
-
const card = parseCard(message);
|
|
1032
|
-
if (card !== null &&
|
|
1033
|
-
(message.role !== 'custom' || message.display === true)) {
|
|
1034
|
-
this.pushTranscriptText(card.body);
|
|
1035
|
-
// A person's inbox answer is the person speaking: their words leave the
|
|
1036
|
-
// card and render as their own message. A digest carrying nothing else
|
|
1037
|
-
// gets no card at all — but a passive backlog folded into the same body
|
|
1038
|
-
// is content, so the residue check keeps it from vanishing with the card.
|
|
1039
|
-
const answers = card.senders
|
|
1040
|
-
.flatMap((sender) => sender.entries)
|
|
1041
|
-
.filter((entry) => entry.disposition === 'human-answer')
|
|
1042
|
-
.map((entry) => entry.body.trim())
|
|
1043
|
-
.filter((text) => text !== '');
|
|
1044
|
-
const onlyHumanWords = answers.length > 0
|
|
1045
|
-
&& card.body.replace(INBOX_SENDER_SECTIONS, '').trim() === ''
|
|
1046
|
-
&& card.senders.every((sender) => sender.entries.every((entry) => entry.disposition === 'human-answer'));
|
|
1047
|
-
if (!onlyHumanWords) {
|
|
1048
|
-
const presentation = presentationFor(card.kind);
|
|
1049
|
-
const component = new ContextMessageComponent(card, presentation, this.toolOutputExpanded, this.dimStyle, (s) => this.spinnerStyle(this.labelStyle(s)));
|
|
1050
|
-
// A boundary card is a visible seam, not a group member: the preceding
|
|
1051
|
-
// span keeps its own recap and the next tool call begins a
|
|
1052
|
-
// broker-aligned fresh group.
|
|
1053
|
-
if (isGroupBoundaryKind(card.kind)) {
|
|
1054
|
-
this.closeOpenGroup();
|
|
1055
|
-
this.append(component);
|
|
1056
|
-
}
|
|
1057
|
-
else {
|
|
1058
|
-
// A folded group hides its members, so whatever the card should leave
|
|
1059
|
-
// behind — a child's final, a recovery — reaches the recap here.
|
|
1060
|
-
this.appendGroupMember(component)?.activity.noteCard(card, presentation);
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
for (const answer of answers)
|
|
1064
|
-
this.appendHumanAnswer(answer);
|
|
1065
|
-
return;
|
|
1066
|
-
}
|
|
1067
|
-
switch (message.role) {
|
|
1068
|
-
case 'bashExecution': {
|
|
1069
|
-
this.closeOpenGroup();
|
|
1070
|
-
this.pushTranscriptText(message.output ?? '');
|
|
1071
|
-
const component = new BashExecutionComponent(message.command, this.tui, message.excludeFromContext);
|
|
1072
|
-
if (message.output)
|
|
1073
|
-
component.appendOutput(message.output);
|
|
1074
|
-
component.setComplete(message.exitCode, message.cancelled,
|
|
1075
|
-
// pi's interactive mode passes a minimal `{truncated:true}` marker here
|
|
1076
|
-
// (interactive-mode.js:2489) where the typed param is the full
|
|
1077
|
-
// TruncationResult; the snapshot message only carries the boolean, so we
|
|
1078
|
-
// mirror pi and cast.
|
|
1079
|
-
message.truncated ? { truncated: true } : undefined, message.fullOutputPath);
|
|
1080
|
-
this.append(component);
|
|
1081
|
-
break;
|
|
1082
|
-
}
|
|
1083
|
-
case 'custom': {
|
|
1084
|
-
if (message.display) {
|
|
1085
|
-
this.pushTranscriptText(this.userMessageText(message));
|
|
1086
|
-
if (message.customType === CRTR_OUTPUT_CUSTOM_TYPE) {
|
|
1087
|
-
this.appendGroupMember(new CrtrOutputMessageComponent(this.userMessageText(message), this.toolOutputExpanded, this.crtrOutputTheme()));
|
|
1088
|
-
break;
|
|
1089
|
-
}
|
|
1090
|
-
// A refresh-yield cycle boundary (session-cycles.ts, synthetic — never
|
|
1091
|
-
// persisted): render as a dim rule rather than the generic custom-
|
|
1092
|
-
// message card, so scrolling through a multi-cycle node's full history
|
|
1093
|
-
// reads as one conversation with clear seams between cycles.
|
|
1094
|
-
if (message.customType === CRTR_CYCLE_DIVIDER_CUSTOM_TYPE) {
|
|
1095
|
-
this.closeOpenGroup();
|
|
1096
|
-
this.append(new Spacer(1));
|
|
1097
|
-
this.append(new Text(this.dimStyle(`── ${this.userMessageText(message)} ──`), 1, 0));
|
|
1098
|
-
this.append(new Spacer(1));
|
|
1099
|
-
break;
|
|
1100
|
-
}
|
|
1101
|
-
const component = new CustomMessageComponent(styleAttachMessageMarkdown(message), undefined, attachMarkdownTheme());
|
|
1102
|
-
component.setExpanded(this.toolOutputExpanded);
|
|
1103
|
-
this.appendGroupMember(component);
|
|
1104
|
-
}
|
|
1105
|
-
break;
|
|
1106
|
-
}
|
|
1107
|
-
case 'compactionSummary': {
|
|
1108
|
-
this.closeOpenGroup();
|
|
1109
|
-
this.append(new Spacer(1));
|
|
1110
|
-
const component = new CompactionSummaryMessageComponent(styleAttachSummaryMarkdown(message), attachMarkdownTheme());
|
|
1111
|
-
component.setExpanded(this.toolOutputExpanded);
|
|
1112
|
-
this.append(component);
|
|
1113
|
-
break;
|
|
1114
|
-
}
|
|
1115
|
-
case 'branchSummary': {
|
|
1116
|
-
this.closeOpenGroup();
|
|
1117
|
-
this.append(new Spacer(1));
|
|
1118
|
-
const component = new BranchSummaryMessageComponent(styleAttachSummaryMarkdown(message), attachMarkdownTheme());
|
|
1119
|
-
component.setExpanded(this.toolOutputExpanded);
|
|
1120
|
-
this.append(component);
|
|
1121
|
-
this.registerCopyBlock(component, 'assistant', message.summary);
|
|
1122
|
-
break;
|
|
1123
|
-
}
|
|
1124
|
-
case 'user': {
|
|
1125
|
-
if (isTrueUserMessage(message))
|
|
1126
|
-
this.closeOpenGroup();
|
|
1127
|
-
const textContent = this.userMessageText(message);
|
|
1128
|
-
if (!textContent)
|
|
1129
|
-
break;
|
|
1130
|
-
this.pushTranscriptText(textContent);
|
|
1131
|
-
if (this.chatChildCount() > 0)
|
|
1132
|
-
this.appendUserPart(new Spacer(1), !isTrueUserMessage(message));
|
|
1133
|
-
const skillBlock = parseSkillBlock(textContent);
|
|
1134
|
-
if (skillBlock) {
|
|
1135
|
-
// SkillInvocationMessageComponent has no transformer seam, so its body
|
|
1136
|
-
// is still styled before construction.
|
|
1137
|
-
const component = new SkillInvocationMessageComponent({ ...skillBlock, content: styleAttachMarkdownSource(skillBlock.content) }, attachMarkdownTheme());
|
|
1138
|
-
component.setExpanded(this.toolOutputExpanded);
|
|
1139
|
-
this.appendUserPart(component, !isTrueUserMessage(message));
|
|
1140
|
-
this.registerCopyBlock(component, 'user', textContent);
|
|
1141
|
-
if (skillBlock.userMessage) {
|
|
1142
|
-
const userMessage = new UserMessageComponent(skillBlock.userMessage, attachMarkdownTheme(), undefined, this.markdownTransformers);
|
|
1143
|
-
this.appendUserPart(userMessage, !isTrueUserMessage(message));
|
|
1144
|
-
this.registerCopyBlock(userMessage, 'user', skillBlock.userMessage);
|
|
1145
|
-
}
|
|
1146
|
-
}
|
|
1147
|
-
else {
|
|
1148
|
-
const component = new UserMessageComponent(textContent, attachMarkdownTheme(), undefined, this.markdownTransformers);
|
|
1149
|
-
this.appendUserPart(component, !isTrueUserMessage(message));
|
|
1150
|
-
this.registerCopyBlock(component, 'user', textContent);
|
|
1151
|
-
}
|
|
1152
|
-
break;
|
|
1153
|
-
}
|
|
1154
|
-
case 'assistant': {
|
|
1155
|
-
const hasProse = assistantVisibleText(message).trim() !== '';
|
|
1156
|
-
if (hasProse)
|
|
1157
|
-
this.closeOpenGroup();
|
|
1158
|
-
this.appendAssistantMessage(message, !hasProse);
|
|
1159
|
-
break;
|
|
1160
|
-
}
|
|
1161
|
-
// toolResult is rendered inline with its tool call (handled in applySnapshot).
|
|
1162
|
-
default:
|
|
1163
|
-
break;
|
|
1164
|
-
}
|
|
1165
|
-
}
|
|
1166
|
-
// Helpers
|
|
1167
|
-
/** Render an assistant reply plus its initially-hidden boundary separator.
|
|
1168
|
-
* A turn that ended on its own abort is rendered as the interrupt it is,
|
|
1169
|
-
* matching the live seam above, so re-reading the transcript later never
|
|
1170
|
-
* turns a healthy interrupt into a red `Error:` line. */
|
|
1171
|
-
appendAssistantMessage(message, groupMember = false) {
|
|
1172
|
-
const component = new ViewerAssistantMessageComponent(undefined, this.hideThinking, attachMarkdownTheme(), this.hiddenThinkingLabel, this.markdownTransformers);
|
|
1173
|
-
const rendered = endedByAbort(message)
|
|
1174
|
-
? { ...message, stopReason: 'aborted', errorMessage: 'Interrupted' }
|
|
1175
|
-
: message;
|
|
1176
|
-
component.updateContent(rendered);
|
|
1177
|
-
this.appendAssistantPart(component, groupMember);
|
|
1178
|
-
this.registerCopyBlock(component, 'assistant', assistantVisibleText(message));
|
|
1179
|
-
const separator = this.appendAssistantSeparator(groupMember);
|
|
1180
|
-
this.setAssistantSeparatorContent(separator, message);
|
|
1181
|
-
return separator;
|
|
1182
|
-
}
|
|
1183
|
-
/** Add a separator in transcript order now; it renders only after a following
|
|
1184
|
-
* tool settles in the folded view. */
|
|
1185
|
-
appendAssistantSeparator(groupMember = false) {
|
|
1186
|
-
const separator = new FoldedToolSeparator();
|
|
1187
|
-
if (groupMember)
|
|
1188
|
-
this.appendGroupMember(separator);
|
|
1189
|
-
else
|
|
1190
|
-
this.append(separator);
|
|
1191
|
-
return separator;
|
|
1192
|
-
}
|
|
1193
|
-
appendAssistantPart(component, groupMember) {
|
|
1194
|
-
if (groupMember)
|
|
1195
|
-
this.appendGroupMember(component);
|
|
1196
|
-
else
|
|
1197
|
-
this.append(component);
|
|
1198
|
-
}
|
|
1199
|
-
appendUserPart(component, groupMember) {
|
|
1200
|
-
if (groupMember)
|
|
1201
|
-
this.appendGroupMember(component);
|
|
1202
|
-
else
|
|
1203
|
-
this.append(component);
|
|
1204
|
-
}
|
|
1205
|
-
/** An answer the person typed in their inbox renders exactly like a message
|
|
1206
|
-
* they typed here, and closes the run around it the same way. */
|
|
1207
|
-
appendHumanAnswer(text) {
|
|
1208
|
-
this.closeOpenGroup();
|
|
1209
|
-
if (this.chatChildCount() > 0)
|
|
1210
|
-
this.append(new Spacer(1));
|
|
1211
|
-
const component = new UserMessageComponent(text, attachMarkdownTheme(), undefined, this.markdownTransformers);
|
|
1212
|
-
this.append(component);
|
|
1213
|
-
this.registerCopyBlock(component, 'user', text);
|
|
1214
|
-
}
|
|
1215
|
-
/** Only the full-fidelity trailing region gets summary groups. Condensed
|
|
1216
|
-
* history intentionally drops tool traffic, so grouping there would create
|
|
1217
|
-
* phantom summary rows and cross the live/condensed boundary. */
|
|
1218
|
-
isLiveGroupRegion() {
|
|
1219
|
-
return this.appendTarget === this.historyContainer;
|
|
1220
|
-
}
|
|
1221
|
-
ensureGroup() {
|
|
1222
|
-
if (!this.isLiveGroupRegion())
|
|
1223
|
-
return undefined;
|
|
1224
|
-
if (this.openGroup)
|
|
1225
|
-
return this.openGroup;
|
|
1226
|
-
const recap = new GroupRecapComponent();
|
|
1227
|
-
const group = {
|
|
1228
|
-
members: [],
|
|
1229
|
-
recap,
|
|
1230
|
-
activity: new GroupActivityRecorder(this.cwd, this.nodeRoster),
|
|
1231
|
-
toolCount: 0,
|
|
1232
|
-
inFlight: new Set(),
|
|
1233
|
-
};
|
|
1234
|
-
this.append(recap);
|
|
1235
|
-
// The recap is a direct history child for cache identity, but zero-row and
|
|
1236
|
-
// hidden until a settled broker summary makes this group collapsible.
|
|
1237
|
-
this.historyContainer.setHidden(recap, true);
|
|
1238
|
-
this.groups.push(group);
|
|
1239
|
-
this.openGroup = group;
|
|
1240
|
-
return group;
|
|
1241
|
-
}
|
|
1242
|
-
closeOpenGroup() {
|
|
1243
|
-
this.openGroup = undefined;
|
|
1244
|
-
}
|
|
1245
|
-
appendGroupMember(component) {
|
|
1246
|
-
const group = this.ensureGroup();
|
|
1247
|
-
this.append(component);
|
|
1248
|
-
if (group)
|
|
1249
|
-
group.members.push(component);
|
|
1250
|
-
return group;
|
|
1251
|
-
}
|
|
1252
|
-
removeGroupMember(component) {
|
|
1253
|
-
for (const group of this.groups) {
|
|
1254
|
-
const index = group.members.indexOf(component);
|
|
1255
|
-
if (index !== -1)
|
|
1256
|
-
group.members.splice(index, 1);
|
|
1257
|
-
}
|
|
1258
|
-
this.historyContainer.setHidden(component, false);
|
|
1259
|
-
}
|
|
1260
|
-
/** Add one tool as a group member, moving the assistant's boundary separator
|
|
1261
|
-
* behind the new summary row without changing the separator's identity. */
|
|
1262
|
-
appendToolComponent(name, id, args) {
|
|
1263
|
-
const trailingSeparator = this.isLiveGroupRegion() &&
|
|
1264
|
-
!this.openGroup &&
|
|
1265
|
-
this.historyContainer.children.at(-1) instanceof FoldedToolSeparator
|
|
1266
|
-
? this.historyContainer.children.at(-1)
|
|
1267
|
-
: undefined;
|
|
1268
|
-
if (trailingSeparator)
|
|
1269
|
-
this.historyContainer.removeChild(trailingSeparator);
|
|
1270
|
-
const group = this.ensureGroup();
|
|
1271
|
-
if (trailingSeparator) {
|
|
1272
|
-
this.append(trailingSeparator);
|
|
1273
|
-
group?.members.push(trailingSeparator);
|
|
1274
|
-
}
|
|
1275
|
-
const component = this.makeToolComponent(name, id, args);
|
|
1276
|
-
component.activityCallId = id;
|
|
1277
|
-
this.appendGroupMember(component);
|
|
1278
|
-
this.registerCopyBlock(component, 'tool', '');
|
|
1279
|
-
if (group) {
|
|
1280
|
-
group.key ??= id;
|
|
1281
|
-
group.toolCount++;
|
|
1282
|
-
group.inFlight.add(component);
|
|
1283
|
-
group.activity.noteCall(id, name, args);
|
|
1284
|
-
}
|
|
1285
|
-
return component;
|
|
1286
|
-
}
|
|
1287
|
-
noteGroupTool(component, name, args) {
|
|
1288
|
-
if (!component.activityCallId)
|
|
1289
|
-
return;
|
|
1290
|
-
for (const group of this.groups) {
|
|
1291
|
-
if (group.members.includes(component))
|
|
1292
|
-
group.activity.noteCall(component.activityCallId, name, args);
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
settleGroupTool(component, result, isError = false) {
|
|
1296
|
-
for (const group of this.groups) {
|
|
1297
|
-
group.inFlight.delete(component);
|
|
1298
|
-
if (!component.activityCallId || !group.members.includes(component))
|
|
1299
|
-
continue;
|
|
1300
|
-
if (result === undefined)
|
|
1301
|
-
group.activity.resolveWithoutResult(component.activityCallId);
|
|
1302
|
-
else
|
|
1303
|
-
group.activity.settle(component.activityCallId, result, isError);
|
|
1304
|
-
}
|
|
1305
|
-
}
|
|
1306
|
-
/** An assistant starts as a non-boundary while its text is empty. Visible prose
|
|
1307
|
-
* or a terminal failure turns it into a boundary without recreating either
|
|
1308
|
-
* pi-owned component (their direct-child cache identities remain intact). */
|
|
1309
|
-
promoteStreamingAssistantToBoundary(message, force = false) {
|
|
1310
|
-
if (!this.streamingWasGroupMember || (!force && assistantVisibleText(message).trim() === ''))
|
|
1311
|
-
return;
|
|
1312
|
-
if (this.streamingComponent)
|
|
1313
|
-
this.removeGroupMember(this.streamingComponent);
|
|
1314
|
-
if (this.streamingToolSeparator)
|
|
1315
|
-
this.removeGroupMember(this.streamingToolSeparator);
|
|
1316
|
-
this.streamingWasGroupMember = false;
|
|
1317
|
-
this.closeOpenGroup();
|
|
1318
|
-
}
|
|
1319
|
-
seedToolGroupSummaries(summaries) {
|
|
1320
|
-
this.groupSummaries.clear();
|
|
1321
|
-
for (const [key, summary] of Object.entries(summaries))
|
|
1322
|
-
this.groupSummaries.set(key, summary);
|
|
1323
|
-
}
|
|
1324
|
-
/** Broker frames can arrive before or after their group's events, and snapshot
|
|
1325
|
-
* rebuilding defers them through the single-writer gate, so this stores first
|
|
1326
|
-
* and applies to every currently-rendered matching group. */
|
|
1327
|
-
applyToolGroupSummary(key, summary) {
|
|
1328
|
-
if (this.deferIfBuilding(() => this.applyToolGroupSummary(key, summary)))
|
|
1329
|
-
return;
|
|
1330
|
-
this.projection = projectToolGroupSummary(this.projection, key, summary);
|
|
1331
|
-
const projected = this.projection.toolGroupSummaryDetails[key];
|
|
1332
|
-
if (projected === undefined)
|
|
1333
|
-
return;
|
|
1334
|
-
this.groupSummaries.set(key, projected);
|
|
1335
|
-
this.applyToolDisplay();
|
|
1336
|
-
}
|
|
1337
|
-
applyGroupDisplay(group) {
|
|
1338
|
-
const summary = group.key === undefined ? undefined : this.groupSummaries.get(group.key);
|
|
1339
|
-
const collapsed = this.foldSettledTools &&
|
|
1340
|
-
this.showGroupSummaries &&
|
|
1341
|
-
group.toolCount > 0 &&
|
|
1342
|
-
group.inFlight.size === 0 &&
|
|
1343
|
-
summary !== undefined;
|
|
1344
|
-
group.recap.setRecap(collapsed ? summary : undefined, group.toolCount, group.activity.activity(), this.detailedToolRecaps, this.recapPalette);
|
|
1345
|
-
this.historyContainer.setHidden(group.recap, !collapsed);
|
|
1346
|
-
for (const member of group.members)
|
|
1347
|
-
this.historyContainer.setHidden(member, collapsed);
|
|
1348
|
-
}
|
|
1349
|
-
/** Make each separator visible only if its immediately-following tool call is
|
|
1350
|
-
* actually folded; in-flight calls remain flush with their live output. */
|
|
1351
|
-
updateFoldedToolSeparators(inFlight = new Set(this.pendingTools.values())) {
|
|
1352
|
-
const children = this.historyContainer.children;
|
|
1353
|
-
for (let i = 0; i < children.length; i++) {
|
|
1354
|
-
const separator = children[i];
|
|
1355
|
-
if (!(separator instanceof FoldedToolSeparator))
|
|
1356
|
-
continue;
|
|
1357
|
-
const followingTool = children[i + 1];
|
|
1358
|
-
separator.setFolded(this.foldSettledTools &&
|
|
1359
|
-
!this.historyContainer.hiddenChildren.has(separator) &&
|
|
1360
|
-
followingTool instanceof MinimizableToolComponent &&
|
|
1361
|
-
!this.historyContainer.hiddenChildren.has(followingTool) &&
|
|
1362
|
-
!inFlight.has(followingTool));
|
|
1363
|
-
this.historyContainer.markDirty(separator);
|
|
1364
|
-
}
|
|
1365
|
-
}
|
|
1366
|
-
/** Track whether an assistant response contains prose or thinking, then make
|
|
1367
|
-
* its separator eligible only for content the current Ctrl+T setting shows. */
|
|
1368
|
-
setAssistantSeparatorContent(separator, message) {
|
|
1369
|
-
const content = message.content;
|
|
1370
|
-
const parts = Array.isArray(content) ? content : [];
|
|
1371
|
-
const hasText = parts.some((part) => typeof part === 'object' &&
|
|
1372
|
-
part !== null &&
|
|
1373
|
-
part.type === 'text' &&
|
|
1374
|
-
typeof part.text === 'string' &&
|
|
1375
|
-
part.text.trim() !== '');
|
|
1376
|
-
const hasThinking = parts.some((part) => typeof part === 'object' &&
|
|
1377
|
-
part !== null &&
|
|
1378
|
-
part.type === 'thinking' &&
|
|
1379
|
-
typeof part.thinking === 'string' &&
|
|
1380
|
-
part.thinking.trim() !== '');
|
|
1381
|
-
this.foldedToolSeparatorContents.set(separator, { hasText, hasThinking });
|
|
1382
|
-
separator.setSeparatesToolGroup(hasText || (!this.hideThinking && hasThinking));
|
|
1383
|
-
}
|
|
1384
|
-
/** Tool component with native viewer renderers for crouter-owned tool output. */
|
|
1385
|
-
makeToolComponent(name, id, args) {
|
|
1386
|
-
const fold = new FoldedToolCallController();
|
|
1387
|
-
let resultObserver;
|
|
1388
|
-
let toolDefinition;
|
|
1389
|
-
if (name === 'bash') {
|
|
1390
|
-
const crtr = createCrtrBashToolDefinition(args, fold);
|
|
1391
|
-
if (crtr === undefined) {
|
|
1392
|
-
toolDefinition = createCrtrPlainBashToolDefinition(this.cwd, fold, this.backgroundBashHint);
|
|
1393
|
-
}
|
|
1394
|
-
else {
|
|
1395
|
-
toolDefinition = crtr.definition;
|
|
1396
|
-
resultObserver = crtr.observeResult;
|
|
1397
|
-
}
|
|
1398
|
-
}
|
|
1399
|
-
else if (name === 'edit') {
|
|
1400
|
-
const edit = createCrtrEditToolDefinition(this.cwd, fold);
|
|
1401
|
-
toolDefinition = edit.definition;
|
|
1402
|
-
resultObserver = edit.observeResult;
|
|
1403
|
-
}
|
|
1404
|
-
else if (name === 'read') {
|
|
1405
|
-
toolDefinition = createCrtrReadToolDefinition(this.cwd, fold);
|
|
1406
|
-
}
|
|
1407
|
-
else if (name === 'write') {
|
|
1408
|
-
toolDefinition = createCrtrWriteToolDefinition(this.cwd, fold);
|
|
1409
|
-
}
|
|
1410
|
-
let component;
|
|
1411
|
-
component = new MinimizableToolComponent(name, id, args, { showImages: this.showImages, imageWidthCells: this.imageWidthCells }, toolDefinition, this.componentTui(() => component), this.cwd);
|
|
1412
|
-
component.setToolView(toolDefinition === undefined ? undefined : fold, resultObserver);
|
|
1413
|
-
component.setExpanded(this.toolOutputExpanded);
|
|
1414
|
-
return component;
|
|
1415
|
-
}
|
|
1416
|
-
/** Append conversation content above the independent live status area — or into
|
|
1417
|
-
* the nested container while condensed history is under construction. */
|
|
1418
|
-
append(child) {
|
|
1419
|
-
this.appendTarget.addChild(child);
|
|
1420
|
-
}
|
|
1421
|
-
/** Number of rendered conversation components in the container currently being
|
|
1422
|
-
* appended to (live history or the nested condensed region). */
|
|
1423
|
-
chatChildCount() {
|
|
1424
|
-
return this.appendTarget.children.length;
|
|
1425
|
-
}
|
|
1426
|
-
/** Clear all chat content. */
|
|
1427
|
-
resetChat() {
|
|
1428
|
-
this.setActivity(undefined);
|
|
1429
|
-
this.settleBashComponent();
|
|
1430
|
-
this.streamingComponent = undefined;
|
|
1431
|
-
this.streamingToolSeparator = undefined;
|
|
1432
|
-
this.streamingWasGroupMember = false;
|
|
1433
|
-
this.foldedToolSeparatorContents.clear();
|
|
1434
|
-
this.groups.length = 0;
|
|
1435
|
-
this.openGroup = undefined;
|
|
1436
|
-
this.groupSummaries.clear();
|
|
1437
|
-
this.nodeRoster.clear();
|
|
1438
|
-
this.pendingTools.clear();
|
|
1439
|
-
this.lastAssistantText = undefined;
|
|
1440
|
-
this.copyBlockRecords.length = 0;
|
|
1441
|
-
this.copyIndex.clear();
|
|
1442
|
-
this.transcriptFilePaths.length = 0;
|
|
1443
|
-
this.pageBlocks.clear();
|
|
1444
|
-
this.historyContainer.clear();
|
|
1445
|
-
}
|
|
1446
|
-
/** Place the transcript block for an inline page a `human send` just raised.
|
|
1447
|
-
* The block is a plain history child, NOT a tool-group member: collapsing the
|
|
1448
|
-
* tool group folds the command away and leaves the page itself on screen, the
|
|
1449
|
-
* way assistant prose stays. Condensed history is skipped deliberately — old
|
|
1450
|
-
* cycles keep only prose and cycle seams. */
|
|
1451
|
-
maybeAppendPageBlock(result) {
|
|
1452
|
-
if (!this.inlinePageBlocks || this.appendTarget !== this.historyContainer)
|
|
1453
|
-
return;
|
|
1454
|
-
const page = detectInlinePageResult(result);
|
|
1455
|
-
if (page === undefined || this.pageBlocks.has(page.pageId))
|
|
1456
|
-
return;
|
|
1457
|
-
const block = new PageBlockComponent(page.pageId, this.pageOpenHint);
|
|
1458
|
-
this.pageBlocks.set(page.pageId, block);
|
|
1459
|
-
this.append(block);
|
|
1460
|
-
// The block is placed empty and fills itself from the daemon: reading a
|
|
1461
|
-
// request is a round trip, and the transcript must not block on one.
|
|
1462
|
-
void this.loadPageBlock(block);
|
|
1463
|
-
}
|
|
1464
|
-
async loadPageBlock(block) {
|
|
1465
|
-
if (!(await block.refresh()))
|
|
1466
|
-
return;
|
|
1467
|
-
this.historyContainer.markDirty(block);
|
|
1468
|
-
this.tui.requestRender();
|
|
1469
|
-
}
|
|
1470
|
-
/** Re-measure the tool calls still in flight. A silent long-running command
|
|
1471
|
-
* emits no tool-execution update, so nothing else would evict its cached
|
|
1472
|
-
* lines and its backgrounding hint would never appear. Driven by the
|
|
1473
|
-
* viewer's existing low-rate chrome poll, and cheap because it touches only
|
|
1474
|
-
* in-flight tools — usually one, never the transcript. */
|
|
1475
|
-
refreshInFlightTools() {
|
|
1476
|
-
if (this.pendingTools.size === 0)
|
|
1477
|
-
return;
|
|
1478
|
-
for (const component of this.pendingTools.values())
|
|
1479
|
-
this.historyContainer.markDirty(component);
|
|
1480
|
-
this.tui.requestRender();
|
|
1481
|
-
}
|
|
1482
|
-
/** Re-read every placed page through the daemon. Driven by the viewer's
|
|
1483
|
-
* ticket-activity watcher, so an answer, a cancellation, or a `--replace`
|
|
1484
|
-
* revision lands on the block already anchored in the transcript. */
|
|
1485
|
-
async refreshPageBlocks() {
|
|
1486
|
-
const blocks = [...this.pageBlocks.values()];
|
|
1487
|
-
const changed = await Promise.all(blocks.map(async (block) => {
|
|
1488
|
-
const moved = await block.refresh();
|
|
1489
|
-
if (moved)
|
|
1490
|
-
this.historyContainer.markDirty(block);
|
|
1491
|
-
return moved;
|
|
1492
|
-
}));
|
|
1493
|
-
if (changed.some(Boolean))
|
|
1494
|
-
this.tui.requestRender();
|
|
1495
|
-
}
|
|
1496
|
-
makeLoader(message) {
|
|
1497
|
-
// Loader updates itself on an interval. Its TUI callback has to evict the
|
|
1498
|
-
// status block's cached frame before requesting the next render.
|
|
1499
|
-
let loader;
|
|
1500
|
-
const statusTui = {
|
|
1501
|
-
requestRender: (force) => {
|
|
1502
|
-
if (loader && !this.onActivityChange)
|
|
1503
|
-
this.statusContainer.markDirty(loader);
|
|
1504
|
-
this.tui.requestRender(force);
|
|
1505
|
-
},
|
|
1506
|
-
terminal: this.tui.terminal,
|
|
1507
|
-
};
|
|
1508
|
-
loader = new Loader(statusTui, this.spinnerStyle, this.dimStyle, message);
|
|
1509
|
-
return loader;
|
|
1510
|
-
}
|
|
1511
|
-
/** Let a self-updating history child invalidate only its own cached lines. */
|
|
1512
|
-
componentTui(component) {
|
|
1513
|
-
return {
|
|
1514
|
-
requestRender: (force) => {
|
|
1515
|
-
this.historyContainer.markDirty(component());
|
|
1516
|
-
this.tui.requestRender(force);
|
|
1517
|
-
},
|
|
1518
|
-
terminal: this.tui.terminal,
|
|
1519
|
-
};
|
|
1520
|
-
}
|
|
1521
|
-
/** Complete and release the live bash component before ChatView gives up ownership. */
|
|
1522
|
-
settleBashComponent(result) {
|
|
1523
|
-
if (!this.bashComponent)
|
|
1524
|
-
return;
|
|
1525
|
-
const component = this.bashComponent;
|
|
1526
|
-
component.setComplete(result?.exitCode, result?.cancelled ?? true, result?.truncated ? { truncated: true } : undefined, result?.fullOutputPath);
|
|
1527
|
-
this.historyContainer.markDirty(component);
|
|
1528
|
-
this.bashComponent = undefined;
|
|
1529
|
-
}
|
|
1530
|
-
/** Swap the single active activity indicator (working/compaction/retry). */
|
|
1531
|
-
setActivity(loader) {
|
|
1532
|
-
this.activityLoader?.stop();
|
|
1533
|
-
this.activityLoader = loader;
|
|
1534
|
-
if (this.onActivityChange) {
|
|
1535
|
-
this.onActivityChange(loader);
|
|
1536
|
-
return;
|
|
1537
|
-
}
|
|
1538
|
-
this.statusContainer.clear();
|
|
1539
|
-
if (loader)
|
|
1540
|
-
this.statusContainer.addChild(loader);
|
|
1541
|
-
}
|
|
1542
|
-
showStatus(message) {
|
|
1543
|
-
this.closeOpenGroup();
|
|
1544
|
-
this.append(new Spacer(1));
|
|
1545
|
-
this.append(new Text(this.dimStyle(message), 1, 0));
|
|
1546
|
-
}
|
|
1547
|
-
showError(message) {
|
|
1548
|
-
this.closeOpenGroup();
|
|
1549
|
-
this.append(new Spacer(1));
|
|
1550
|
-
this.append(new Text(this.errorStyle(message), 1, 0));
|
|
1551
|
-
}
|
|
1552
|
-
crtrOutputTheme() {
|
|
1553
|
-
return {
|
|
1554
|
-
fg: (name, text) => {
|
|
1555
|
-
if (name === 'error')
|
|
1556
|
-
return this.errorStyle(text);
|
|
1557
|
-
if (name === 'warning' || name === 'accent' || name === 'toolTitle' || name === 'success')
|
|
1558
|
-
return this.spinnerStyle(text);
|
|
1559
|
-
if (name === 'muted')
|
|
1560
|
-
return this.dimStyle(text);
|
|
1561
|
-
return text;
|
|
1562
|
-
},
|
|
1563
|
-
bg: (_name, text) => text,
|
|
1564
|
-
bold: (text) => this.labelStyle(text),
|
|
1565
|
-
};
|
|
1566
|
-
}
|
|
1567
|
-
/** Extract the tool-call content items from an assistant message. */
|
|
1568
|
-
assistantToolCalls(message) {
|
|
1569
|
-
const content = message.content;
|
|
1570
|
-
if (!Array.isArray(content))
|
|
1571
|
-
return [];
|
|
1572
|
-
return content.filter((c) => typeof c === 'object' && c !== null && c.type === 'toolCall');
|
|
1573
|
-
}
|
|
1574
|
-
/** Existing file paths from the rendered transcript, newest first. */
|
|
1575
|
-
getTranscriptFilePathsNewestFirst() {
|
|
1576
|
-
return [...this.transcriptFilePaths];
|
|
1577
|
-
}
|
|
1578
|
-
/** The text of the most recent assistant message, for `/copy`. Undefined when
|
|
1579
|
-
* no assistant message has been seen (or it had no text content). */
|
|
1580
|
-
getLastAssistantText() {
|
|
1581
|
-
const t = this.lastAssistantText?.trim();
|
|
1582
|
-
return t ? t : undefined;
|
|
1583
|
-
}
|
|
1584
|
-
/** Copyable source text for a transcript block, if it has any. */
|
|
1585
|
-
blockText(block) {
|
|
1586
|
-
const index = this.copyIndex.get(block);
|
|
1587
|
-
return index === undefined ? undefined : this.copyBlockRecords[index]?.text;
|
|
1588
|
-
}
|
|
1589
|
-
/** The canonical ordered copy record, oldest → newest. */
|
|
1590
|
-
copyBlocks() {
|
|
1591
|
-
return this.copyBlockRecords;
|
|
1592
|
-
}
|
|
1593
|
-
/** Newest tool call's result text (`/copy-tool`). */
|
|
1594
|
-
getLastToolOutputText() {
|
|
1595
|
-
for (let i = this.copyBlockRecords.length - 1; i >= 0; i--) {
|
|
1596
|
-
const copyBlock = this.copyBlockRecords[i];
|
|
1597
|
-
if (copyBlock.kind !== 'tool')
|
|
1598
|
-
continue;
|
|
1599
|
-
return copyBlock.text.trim() === '' ? undefined : copyBlock.text;
|
|
1600
|
-
}
|
|
1601
|
-
return undefined;
|
|
1602
|
-
}
|
|
1603
|
-
/** Every copyable block's text, oldest → newest, joined by blank lines. */
|
|
1604
|
-
getTranscriptPlainText() {
|
|
1605
|
-
return this.copyBlockRecords
|
|
1606
|
-
.map((copyBlock) => copyBlock.text)
|
|
1607
|
-
.filter((text) => text.trim() !== '')
|
|
1608
|
-
.join('\n\n');
|
|
1609
|
-
}
|
|
1610
|
-
registerCopyBlock(block, kind, text) {
|
|
1611
|
-
const condensedCopyBlocks = this.condensedCopyBlocks.get(this.appendTarget);
|
|
1612
|
-
if (condensedCopyBlocks) {
|
|
1613
|
-
const index = condensedCopyBlocks.findIndex((copyBlock) => copyBlock.block === block);
|
|
1614
|
-
if (index === -1)
|
|
1615
|
-
condensedCopyBlocks.push({ block, kind, text });
|
|
1616
|
-
else
|
|
1617
|
-
condensedCopyBlocks[index].text = text;
|
|
1618
|
-
return;
|
|
1619
|
-
}
|
|
1620
|
-
const index = this.copyIndex.get(block);
|
|
1621
|
-
if (index === undefined) {
|
|
1622
|
-
this.copyIndex.set(block, this.copyBlockRecords.length);
|
|
1623
|
-
this.copyBlockRecords.push({ block, kind, text });
|
|
1624
|
-
}
|
|
1625
|
-
else {
|
|
1626
|
-
this.copyBlockRecords[index].text = text;
|
|
1627
|
-
}
|
|
1628
|
-
}
|
|
1629
|
-
unregisterCopyBlock(block) {
|
|
1630
|
-
const condensedCopyBlocks = this.condensedCopyBlocks.get(this.appendTarget);
|
|
1631
|
-
if (condensedCopyBlocks) {
|
|
1632
|
-
const index = condensedCopyBlocks.findIndex((copyBlock) => copyBlock.block === block);
|
|
1633
|
-
if (index !== -1)
|
|
1634
|
-
condensedCopyBlocks.splice(index, 1);
|
|
1635
|
-
return;
|
|
1636
|
-
}
|
|
1637
|
-
const index = this.copyIndex.get(block);
|
|
1638
|
-
if (index === undefined)
|
|
1639
|
-
return;
|
|
1640
|
-
this.copyBlockRecords.splice(index, 1);
|
|
1641
|
-
this.copyIndex.delete(block);
|
|
1642
|
-
for (let i = index; i < this.copyBlockRecords.length; i++) {
|
|
1643
|
-
this.copyIndex.set(this.copyBlockRecords[i].block, i);
|
|
1644
|
-
}
|
|
1645
|
-
}
|
|
1646
|
-
appendCondensedBlock({ component, copyBlocks }) {
|
|
1647
|
-
this.append(component);
|
|
1648
|
-
this.registerCopyBlock(component, 'condensed', copyBlocks.map((copyBlock) => copyBlock.text).filter((text) => text.trim() !== '').join('\n\n'));
|
|
1649
|
-
}
|
|
1650
|
-
/** Flatten arbitrary tool result payloads into the visible text copy target. */
|
|
1651
|
-
toolResultText(result) {
|
|
1652
|
-
if (typeof result === 'string')
|
|
1653
|
-
return result;
|
|
1654
|
-
if (typeof result === 'object' && result !== null && 'content' in result) {
|
|
1655
|
-
const content = result.content;
|
|
1656
|
-
if (typeof content === 'string')
|
|
1657
|
-
return content;
|
|
1658
|
-
if (Array.isArray(content)) {
|
|
1659
|
-
return content
|
|
1660
|
-
.filter((part) => typeof part === 'object' &&
|
|
1661
|
-
part !== null &&
|
|
1662
|
-
part.type === 'text' &&
|
|
1663
|
-
typeof part.text === 'string')
|
|
1664
|
-
.map((part) => part.text)
|
|
1665
|
-
.join('');
|
|
1666
|
-
}
|
|
1667
|
-
}
|
|
1668
|
-
try {
|
|
1669
|
-
const text = JSON.stringify(result);
|
|
1670
|
-
return typeof text === 'string' ? text : '';
|
|
1671
|
-
}
|
|
1672
|
-
catch {
|
|
1673
|
-
return '';
|
|
1674
|
-
}
|
|
1675
|
-
}
|
|
1676
|
-
pushTranscriptText(text) {
|
|
1677
|
-
const trimmed = text.trim();
|
|
1678
|
-
if (trimmed === '')
|
|
1679
|
-
return;
|
|
1680
|
-
const paths = extractFilePaths([trimmed], this.cwd);
|
|
1681
|
-
if (paths.length === 0)
|
|
1682
|
-
return;
|
|
1683
|
-
const next = [...paths, ...this.transcriptFilePaths.filter((path) => !paths.includes(path))].slice(0, 50);
|
|
1684
|
-
this.transcriptFilePaths.splice(0, this.transcriptFilePaths.length, ...next);
|
|
1685
|
-
}
|
|
1686
|
-
pushTranscriptValue(value) {
|
|
1687
|
-
try {
|
|
1688
|
-
const text = typeof value === 'string' ? value : JSON.stringify(value);
|
|
1689
|
-
if (typeof text === 'string')
|
|
1690
|
-
this.pushTranscriptText(text);
|
|
1691
|
-
}
|
|
1692
|
-
catch {
|
|
1693
|
-
// Tool payloads that cannot serialize are not transcript text.
|
|
1694
|
-
}
|
|
1695
|
-
}
|
|
1696
|
-
/** Concatenate the text blocks of a user message (string or content array). */
|
|
1697
|
-
userMessageText(message) {
|
|
1698
|
-
const content = message.content;
|
|
1699
|
-
if (typeof content === 'string')
|
|
1700
|
-
return content;
|
|
1701
|
-
if (!Array.isArray(content))
|
|
1702
|
-
return '';
|
|
1703
|
-
return content
|
|
1704
|
-
.filter((c) => typeof c === 'object' && c !== null && c.type === 'text')
|
|
1705
|
-
.map((c) => c.text)
|
|
1706
|
-
.join('');
|
|
1707
|
-
}
|
|
1708
|
-
}
|
|
1
|
+
var v=Object.defineProperty;var p=(h,t)=>v(h,"name",{value:t,configurable:!0});import{Container as j,Loader as F,Spacer as d,Text as x}from"@earendil-works/pi-tui";import{AssistantMessageComponent as L,BashExecutionComponent as M,BranchSummaryMessageComponent as H,CompactionSummaryMessageComponent as W,CustomMessageComponent as $,parseSkillBlock as q,SkillInvocationMessageComponent as V,ToolExecutionComponent as N,UserMessageComponent as S}from"@earendil-works/pi-coding-agent";import{attachMarkdownTheme as u}from"../config.js";import{ContextMessageComponent as U}from"./context-message.js";import{presentationFor as z}from"./card-presentation.js";import{detectInlinePageResult as Y,PageBlockComponent as J}from"./page-block.js";import{CRTR_OUTPUT_CUSTOM_TYPE as K,CrtrOutputMessageComponent as X,createCrtrBashToolDefinition as Q}from"./crtr-output.js";import{CRTR_CYCLE_DIVIDER_CUSTOM_TYPE as Z,endedByAbort as w}from"../../../core/runtime/session-cycles.js";import{parseCard as tt}from"../../../shared/generated-context.js";import{assistantVisibleText as c,isGroupBoundaryKind as et,isTrueUserMessage as C}from"../../../shared/tool-groups.js";import{transformDiagramFences as st}from"./diagram.js";import{styleAttachAgentMarkdown as it,styleAttachMarkdownSource as E,styleAttachMessageMarkdown as ot,styleAttachSummaryMarkdown as O}from"./markdown-source.js";import{createCrtrEditToolDefinition as nt}from"./edit-diff.js";import{GroupActivityRecorder as rt}from"./group-activity.js";import{GroupRecapComponent as at}from"./group-recap.js";import{FoldedToolCallController as ht,bashCallBackgroundHintLines as pt,createCrtrPlainBashToolDefinition as lt,createCrtrReadToolDefinition as dt,createCrtrWriteToolDefinition as ct}from"./tool-calls.js";import{ringCompletionBell as ut}from"../chrome/completion-bell.js";import{extractFilePaths as mt}from"#core/human/visible-paths";import{keepWhenCondensed as ft,liveRegionStart as gt}from"./condensed-history.js";import{ViewerAssistantMessageComponent as A}from"./assistant-message.js";import{CompositeViewportSource as yt,MeasuredContainer as B}from"./measured-container.js";import{readConfig as T,updateRawConfigAtomically as Ct}from"../../../core/config.js";import{DEFAULT_CONDENSED_HISTORY as Tt,DEFAULT_LIVE_CYCLES as kt}from"../../../types.js";import{applySnapshot as bt,applyToolGroupSummary as xt,applyWorkingActivity as St,bashEnd as wt,bashOutput as At,bashStart as Bt,initialConvState as Rt,reduce as Gt}from"../../conversation/projection.js";const I=p(h=>`\x1B[2m${h}\x1B[22m`,"defaultDimStyle"),_=50;function Mt(){try{return T("user").live_cycles}catch{return kt}}p(Mt,"readLiveCycles");function Et(){try{return T("user").condensed_history}catch{return Tt}}p(Et,"readCondensedHistory");function Ot(){try{return T("user").fold_finished_tools}catch{return!1}}p(Ot,"readFoldFinishedTools");function It(){try{return T("user").summarize_tool_calls}catch{return!1}}p(It,"readSummarizeToolCalls");function _t(){try{return T("user").detailed_tool_recaps}catch{return!0}}p(_t,"readDetailedToolRecaps");function Pt(h){try{Ct("user",t=>({...t,fold_finished_tools:h}))}catch{}}p(Pt,"persistFoldFinishedTools");function Dt(h){return typeof h=="object"&&h!==null&&"setExpanded"in h&&typeof h.setExpanded=="function"}p(Dt,"isExpandable");const vt=/\x1b\[[0-9;]*m/g,jt=/\x1b\[([0-9;]*)m/g;function Ft(h){return h.replace(jt,(t,e)=>{const s=e.split(";"),i=[];for(let o=0;o<s.length;o++){const n=Number(s[o]===""?0:s[o]);if(n===38||n===48||n===58){const r=Number(s[o+1]),a=o+(r===5?2:r===2?4:1);n!==48&&i.push(...s.slice(o,a+1)),o=a;continue}n>=40&&n<=47||n>=100&&n<=107||i.push(String(n))}return i.length>0?`\x1B[${i.join(";")}m`:""})}p(Ft,"stripBackground");const Lt=/<from\b[^>]*>[\s\S]*?<\/from>/g;class R extends d{static{p(this,"FoldedToolSeparator")}folded=!1;separatesToolGroup=!1;setFolded(t){this.folded=t,this.refresh()}setSeparatesToolGroup(t){this.separatesToolGroup=t,this.refresh()}refresh(){this.setLines(this.folded&&this.separatesToolGroup?1:0)}}class G extends N{static{p(this,"MinimizableToolComponent")}activityCallId;minimized=!1;expandedState=!1;foldController;resultObserver;setToolView(t,e){this.foldController=t,this.resultObserver=e}updateResult(...t){this.resultObserver?.(t[0],t[1]??!1),super.updateResult(...t)}setExpanded(t){this.expandedState=t,super.setExpanded(t)}setMinimized(t){!this.foldController||this.minimized===t||(this.minimized=t,this.foldController.setFolded(t),super.setExpanded(this.expandedState))}render(t){if(!this.minimized)return[...super.render(t),...pt(this.foldController?.callComponent(),t)];const e=this.foldController?.callComponent();return e?e.render(t).filter(s=>s.replace(vt,"").trim().length>0).map(s=>Ft(s).trimEnd()):super.render(t)}}const Ht=p(h=>`\x1B[31m${h}\x1B[39m`,"defaultErrorStyle"),Wt={accent:p(h=>`\x1B[33m${h}\x1B[39m`,"accent"),active:p(h=>`\x1B[36m${h}\x1B[39m`,"active"),info:p(h=>`\x1B[34m${h}\x1B[39m`,"info"),muted:I,faint:I,border:p(h=>h,"border"),surface:p(h=>h,"surface"),bold:p(h=>`\x1B[1m${h}\x1B[22m`,"bold"),error:Ht,warning:p(h=>`\x1B[33m${h}\x1B[39m`,"warning"),diffAdded:p(h=>`\x1B[32m${h}\x1B[39m`,"diffAdded"),diffRemoved:p(h=>`\x1B[91m${h}\x1B[39m`,"diffRemoved"),bashMode:p(h=>`\x1B[32m${h}\x1B[39m`,"bashMode"),bashModeAlt:p(h=>`\x1B[92m${h}\x1B[39m`,"bashModeAlt")};class ue{static{p(this,"ChatView")}tui;container;historyContainer=new B;statusContainer=new B;bannerContainer;transcript;appendTarget=this.historyContainer;pageBlocks=new Map;inlinePageBlocks;pageOpenHint;backgroundBashHint;liveCycles;condensedHistory;cwd;showImages;imageWidthCells;hideThinking;hiddenThinkingLabel;toolOutputExpanded;foldSettledTools=Ot();summarizeToolCalls=It();detailedToolRecaps=_t();showGroupSummaries=this.summarizeToolCalls&&this.foldSettledTools;groups=[];openGroup;groupSummaries=new Map;nodeRoster=new Map;streamingWasGroupMember=!1;onFooterEvent;onActivityChange;spinnerStyle;dimStyle;errorStyle;recapPalette;labelStyle=p(t=>`\x1B[1m${t}\x1B[22m`,"labelStyle");markdownTransformers=[(t,{messageType:e,availableWidth:s})=>e==="assistant"?st(t,s):t,(t,{messageType:e})=>e==="user"?E(t):it(t)];streamingComponent;streamingToolSeparator;foldedToolSeparatorContents=new Map;pendingTools=new Map;bashComponent;activityLoader;projection=Rt();workingActivity=this.projection.workingActivity;runActive=!1;applyingSnapshot=!1;snapshotGeneration=0;deferredFrames=[];lastAssistantText;transcriptFilePaths=[];copyBlockRecords=[];copyIndex=new Map;condensedCopyBlocks=new WeakMap;constructor(t,e,s={}){if(this.tui=t,this.container=e,this.cwd=s.cwd??process.cwd(),this.showImages=s.showImages??!0,this.imageWidthCells=s.imageWidthCells??60,this.hideThinking=s.hideThinking??!1,this.hiddenThinkingLabel=s.hiddenThinkingLabel??"Thinking...",this.toolOutputExpanded=s.toolOutputExpanded??!1,this.liveCycles=s.liveCycles??Mt(),this.condensedHistory=s.condensedHistory??Et(),this.onFooterEvent=s.onFooterEvent,this.onActivityChange=s.onActivityChange,this.inlinePageBlocks=s.inlinePageBlocks??!1,this.pageOpenHint=s.pageOpenHint??(()=>"crtr human list"),this.backgroundBashHint=s.backgroundBashHint??(()=>null),this.recapPalette=s.palette??Wt,this.spinnerStyle=this.recapPalette.active,this.dimStyle=this.recapPalette.muted,this.errorStyle=this.recapPalette.error,s.banner&&s.banner.length>0){const i=new B;i.addChild(new d(1));for(const o of s.banner)i.addChild(new x(o,1,0));i.addChild(new d(1)),this.bannerContainer=i,this.container.addChild(i)}this.container.addChild(this.historyContainer),this.onActivityChange||this.container.addChild(this.statusContainer),this.transcript=new yt([...this.bannerContainer?[this.bannerContainer]:[],this.historyContainer,...this.onActivityChange?[]:[this.statusContainer]])}transcriptSource(){return this.transcript}async applySnapshot(t){const e=++this.snapshotGeneration;this.applyingSnapshot=!0,this.deferredFrames.length=0,this.resetChat(),this.projection=bt(t,this.projection),this.workingActivity=this.projection.workingActivity,this.runActive=this.projection.isStreaming,this.seedToolGroupSummaries(this.projection.toolGroupSummaryDetails);const s=new Map,i=this.projection.messages,o=i.length-1,n=gt(i,this.liveCycles);if(n>0){const r=await this.buildCondensedBlock(i.slice(0,n),e);if(e!==this.snapshotGeneration)return;r&&this.appendCondensedBlock(r)}for(let r=n;r<i.length;r++){if(!this.projection.isStreaming&&r>n&&(r-n)%_===0&&(await new Promise(l=>setImmediate(l)),e!==this.snapshotGeneration))return;const a=i[r];if(a.role==="assistant"){const l=c(a);l.trim()&&(this.lastAssistantText=l,this.pushTranscriptText(l));const P=r===o&&this.projection.isStreaming&&a.stopReason!=="aborted"&&a.stopReason!=="error",g=c(a).trim()!=="",D=this.assistantToolCalls(a),k=a.stopReason==="aborted"||a.stopReason==="error",y=w(a)?"Interrupted":a.errorMessage??"Error";if(k){for(const m of s.values()){const f={content:[{type:"text",text:y}],isError:!0};m.updateResult(f),this.registerCopyBlock(m,"tool",y),this.settleGroupTool(m,f,!0)}s.clear()}(g||k)&&this.closeOpenGroup();let b;P?(this.streamingComponent=new A(void 0,this.hideThinking,u(),this.hiddenThinkingLabel,this.markdownTransformers),this.appendAssistantPart(this.streamingComponent,!g),this.registerCopyBlock(this.streamingComponent,"assistant",""),this.streamingWasGroupMember=!g,this.streamingComponent.updateContent(a),this.registerCopyBlock(this.streamingComponent,"assistant",c(a)),b=this.streamingToolSeparator=this.appendAssistantSeparator(!g)):b=this.appendAssistantMessage(a,!g&&!k),b&&this.setAssistantSeparatorContent(b,a);for(const m of D){this.pushTranscriptValue(m.arguments);const f=this.appendToolComponent(m.name,m.id,m.arguments);a.stopReason==="aborted"||a.stopReason==="error"?(f.updateResult({content:[{type:"text",text:y}],isError:!0}),this.registerCopyBlock(f,"tool",y),this.settleGroupTool(f,{content:[{type:"text",text:y}],isError:!0},!0)):s.set(m.id,f)}k&&this.closeOpenGroup()}else if(a.role==="toolResult"){this.pushTranscriptText(this.userMessageText(a));const l=s.get(a.toolCallId);l&&(l.updateResult(a),this.registerCopyBlock(l,"tool",this.toolResultText(a)),this.historyContainer.markDirty(l),this.settleGroupTool(l,a,a.isError===!0),s.delete(a.toolCallId),this.maybeAppendPageBlock(a))}else this.addMessageToChat(a)}for(const[r,a]of s)this.pendingTools.set(r,a);this.applyToolDisplay(),this.projection.isStreaming&&this.setActivity(this.makeLoader(this.workingActivity)),this.tui.requestRender(),this.applyingSnapshot=!1,this.replayDeferredFrames()}async buildCondensedBlock(t,e){const s=new j,i=this.appendTarget,o=[];this.appendTarget=s,this.condensedCopyBlocks.set(s,o);try{let n=0;for(const r of t)if(ft(r,this.condensedHistory)){if(n>0&&n%_===0&&(await new Promise(a=>setImmediate(a)),e!==this.snapshotGeneration))return;n++,this.pushTranscriptText(this.userMessageText(r)),this.addMessageToChat(r)}}finally{this.appendTarget=i,this.condensedCopyBlocks.delete(s)}return s.children.length>0?{component:s,copyBlocks:o}:void 0}deferIfBuilding(t){return this.applyingSnapshot?(this.deferredFrames.push(t),!0):!1}replayDeferredFrames(){const t=this.deferredFrames.splice(0);for(const e of t)e()}setWorkingActivity(t){if(this.deferIfBuilding(()=>this.setWorkingActivity(t)))return;const e=this.projection.activity===this.workingActivity;this.projection=St(this.projection,t),this.workingActivity=this.projection.workingActivity,this.runActive&&e&&this.setActivity(this.makeLoader(this.workingActivity))}settleRun(){this.runActive=!1;for(const t of this.pendingTools.values())this.settleGroupTool(t);this.streamingComponent&&(this.historyContainer.removeChild(this.streamingComponent),this.unregisterCopyBlock(this.streamingComponent),this.streamingComponent=void 0),this.streamingToolSeparator=void 0,this.pendingTools.clear(),this.applyToolDisplay(),this.setActivity(void 0),this.settleBashComponent()}dispose(){this.settleRun()}toggleToolsExpanded(){let t;return this.summarizeToolCalls&&this.foldSettledTools?(this.showGroupSummaries=!this.showGroupSummaries,this.toolOutputExpanded=!this.showGroupSummaries,t={kind:"summaries",shown:this.showGroupSummaries}):(this.toolOutputExpanded=!this.toolOutputExpanded,t={kind:"output",expanded:this.toolOutputExpanded}),this.applyToolDisplay(),t}toggleFoldSettledTools(){return this.foldSettledTools=!this.foldSettledTools,Pt(this.foldSettledTools),this.summarizeToolCalls&&this.foldSettledTools&&(this.showGroupSummaries=!0),this.applyToolDisplay(),this.foldSettledTools}applyToolDisplay(){const t=new Set(this.pendingTools.values());for(const e of this.groups)for(const s of e.inFlight)t.add(s);for(const e of this.historyContainer.children)e instanceof G&&e.setMinimized(this.foldSettledTools&&!t.has(e)),Dt(e)&&e.setExpanded(this.toolOutputExpanded);for(const e of this.groups)this.applyGroupDisplay(e);this.updateFoldedToolSeparators(t),this.historyContainer.markDirty(),this.tui.requestRender()}toggleThinking(){this.hideThinking=!this.hideThinking;for(const t of this.historyContainer.children)t instanceof L&&t.setHideThinkingBlock(this.hideThinking);for(const[t,e]of this.foldedToolSeparatorContents)t.setSeparatesToolGroup(e.hasText||!this.hideThinking&&e.hasThinking);return this.historyContainer.markDirty(),this.tui.requestRender(),this.hideThinking}handleEvent(t){if(!this.deferIfBuilding(()=>this.handleEvent(t))){switch(this.projection=Gt(this.projection,t),t.type){case"agent_start":{this.runActive=this.projection.isStreaming;for(const e of this.pendingTools.values())this.settleGroupTool(e);this.pendingTools.clear(),this.setActivity(this.makeLoader(this.workingActivity));break}case"agent_end":{this.settleRun(),ut();break}case"agent_settled":{this.settleRun();break}case"message_start":{if(t.message.role==="custom"||t.message.role==="user")this.addMessageToChat(t.message);else if(t.message.role==="assistant"){const e=c(t.message).trim()!=="";e&&this.closeOpenGroup(),this.streamingComponent=new A(void 0,this.hideThinking,u(),this.hiddenThinkingLabel,this.markdownTransformers),this.streamingWasGroupMember=!e,this.appendAssistantPart(this.streamingComponent,!e),this.registerCopyBlock(this.streamingComponent,"assistant",""),this.streamingComponent.updateContent(t.message),this.registerCopyBlock(this.streamingComponent,"assistant",c(t.message)),this.streamingToolSeparator=this.appendAssistantSeparator(!e),this.setAssistantSeparatorContent(this.streamingToolSeparator,t.message)}break}case"message_update":{if(this.streamingComponent&&t.message.role==="assistant"){this.promoteStreamingAssistantToBoundary(t.message),this.streamingComponent.updateContent(t.message),this.registerCopyBlock(this.streamingComponent,"assistant",c(t.message)),this.historyContainer.markDirty(this.streamingComponent);const e=this.assistantToolCalls(t.message);this.streamingToolSeparator&&this.setAssistantSeparatorContent(this.streamingToolSeparator,t.message);for(const s of e){this.pushTranscriptValue(s.arguments);const i=this.pendingTools.get(s.id);if(i)i.updateArgs(s.arguments),this.noteGroupTool(i,s.name,s.arguments),this.historyContainer.markDirty(i);else{const o=this.appendToolComponent(s.name,s.id,s.arguments);this.pendingTools.set(s.id,o)}}}break}case"message_end":{if(t.message.role!=="assistant")break;const e=t.message.stopReason==="aborted"||t.message.stopReason==="error";if(this.promoteStreamingAssistantToBoundary(t.message,e),this.streamingComponent&&this.registerCopyBlock(this.streamingComponent,"assistant",c(t.message)),t.message.stopReason!=="aborted"&&t.message.stopReason!=="error"){const s=c(t.message);s.trim()&&(this.lastAssistantText=s,this.pushTranscriptText(s))}if(this.streamingComponent){const s=t.message.stopReason;let i=t.message.errorMessage;if(w(t.message)&&(i="Interrupted",t.message.errorMessage=i,t.message.stopReason="aborted"),this.streamingComponent.updateContent(t.message),s==="aborted"||s==="error"){const o=i??"Error";for(const n of this.pendingTools.values())n.updateResult({content:[{type:"text",text:o}],isError:!0}),this.registerCopyBlock(n,"tool",o),this.settleGroupTool(n,{content:[{type:"text",text:o}],isError:!0},!0),this.historyContainer.markDirty(n);this.pendingTools.clear()}else for(const o of this.pendingTools.values())o.setArgsComplete(),this.historyContainer.markDirty(o);this.historyContainer.markDirty(this.streamingComponent),this.streamingComponent=void 0,this.streamingToolSeparator=void 0}e&&(this.closeOpenGroup(),this.applyToolDisplay());break}case"tool_execution_start":{this.pushTranscriptValue(t.args);let e=this.pendingTools.get(t.toolCallId);e?this.noteGroupTool(e,t.toolName,t.args):(e=this.appendToolComponent(t.toolName,t.toolCallId,t.args),this.pendingTools.set(t.toolCallId,e)),e.markExecutionStarted(),this.historyContainer.markDirty(e);break}case"tool_execution_update":{const e=this.projection.partialToolResults.get(t.toolCallId)??t.partialResult;this.pushTranscriptValue(e);const s=this.pendingTools.get(t.toolCallId);s&&(s.updateResult(e,!0),this.registerCopyBlock(s,"tool",this.toolResultText(e)),this.historyContainer.markDirty(s));break}case"tool_execution_end":{const e=this.projection.partialToolResults.get(t.toolCallId)??t.result;this.pushTranscriptValue(e);const s=this.pendingTools.get(t.toolCallId);s&&(s.updateResult(e),this.registerCopyBlock(s,"tool",this.toolResultText(e)),this.pendingTools.delete(t.toolCallId),this.settleGroupTool(s,e,t.isError),this.applyToolDisplay(),this.historyContainer.markDirty(s),this.maybeAppendPageBlock(e));break}case"compaction_start":{const e=t.reason==="manual"?"Compacting context...":"Auto-compacting...";this.setActivity(this.makeLoader(e));break}case"compaction_end":{this.setActivity(this.runActive?this.makeLoader(this.workingActivity):void 0),t.aborted?this.showStatus(t.reason==="manual"?"Compaction cancelled":"Auto-compaction cancelled"):t.result?this.addMessageToChat({role:"compactionSummary",summary:t.result.summary,tokensBefore:t.result.tokensBefore,timestamp:Date.now()}):t.errorMessage&&this.showError(t.errorMessage);break}case"auto_retry_start":{const e=Math.ceil(t.delayMs/1e3);this.setActivity(this.makeLoader(`Retrying (${t.attempt}/${t.maxAttempts}) in ${e}s...`));break}case"auto_retry_end":{this.setActivity(this.runActive?this.makeLoader(this.workingActivity):void 0),t.success||this.showError(`Retry failed after ${t.attempt} attempts: ${t.finalError??"Unknown error"}`);break}case"queue_update":case"session_info_changed":case"thinking_level_changed":this.onFooterEvent?.(t);break;default:break}this.tui.requestRender()}}bashStart(t,e){if(this.deferIfBuilding(()=>this.bashStart(t,e)))return;this.projection=Bt(this.projection,t,e),this.closeOpenGroup(),this.settleBashComponent();let s;s=new M(t,this.componentTui(()=>s),e),this.bashComponent=s,this.append(s),this.tui.requestRender()}bashOutput(t){this.deferIfBuilding(()=>this.bashOutput(t))||(this.projection=At(this.projection,t),this.pushTranscriptText(t),this.bashComponent&&(this.bashComponent.appendOutput(t),this.historyContainer.markDirty(this.bashComponent)),this.tui.requestRender())}bashEnd(t){this.deferIfBuilding(()=>this.bashEnd(t))||(this.projection=wt(this.projection,t),this.settleBashComponent(t),this.tui.requestRender())}addMessageToChat(t){const e=tt(t);if(e!==null&&(t.role!=="custom"||t.display===!0)){this.pushTranscriptText(e.body);const s=e.senders.flatMap(o=>o.entries).filter(o=>o.disposition==="human-answer").map(o=>o.body.trim()).filter(o=>o!=="");if(!(s.length>0&&e.body.replace(Lt,"").trim()===""&&e.senders.every(o=>o.entries.every(n=>n.disposition==="human-answer")))){const o=z(e.kind),n=new U(e,o,this.toolOutputExpanded,this.dimStyle,r=>this.spinnerStyle(this.labelStyle(r)));et(e.kind)?(this.closeOpenGroup(),this.append(n)):this.appendGroupMember(n)?.activity.noteCard(e,o)}for(const o of s)this.appendHumanAnswer(o);return}switch(t.role){case"bashExecution":{this.closeOpenGroup(),this.pushTranscriptText(t.output??"");const s=new M(t.command,this.tui,t.excludeFromContext);t.output&&s.appendOutput(t.output),s.setComplete(t.exitCode,t.cancelled,t.truncated?{truncated:!0}:void 0,t.fullOutputPath),this.append(s);break}case"custom":{if(t.display){if(this.pushTranscriptText(this.userMessageText(t)),t.customType===K){this.appendGroupMember(new X(this.userMessageText(t),this.toolOutputExpanded,this.crtrOutputTheme()));break}if(t.customType===Z){this.closeOpenGroup(),this.append(new d(1)),this.append(new x(this.dimStyle(`\u2500\u2500 ${this.userMessageText(t)} \u2500\u2500`),1,0)),this.append(new d(1));break}const s=new $(ot(t),void 0,u());s.setExpanded(this.toolOutputExpanded),this.appendGroupMember(s)}break}case"compactionSummary":{this.closeOpenGroup(),this.append(new d(1));const s=new W(O(t),u());s.setExpanded(this.toolOutputExpanded),this.append(s);break}case"branchSummary":{this.closeOpenGroup(),this.append(new d(1));const s=new H(O(t),u());s.setExpanded(this.toolOutputExpanded),this.append(s),this.registerCopyBlock(s,"assistant",t.summary);break}case"user":{C(t)&&this.closeOpenGroup();const s=this.userMessageText(t);if(!s)break;this.pushTranscriptText(s),this.chatChildCount()>0&&this.appendUserPart(new d(1),!C(t));const i=q(s);if(i){const o=new V({...i,content:E(i.content)},u());if(o.setExpanded(this.toolOutputExpanded),this.appendUserPart(o,!C(t)),this.registerCopyBlock(o,"user",s),i.userMessage){const n=new S(i.userMessage,u(),void 0,this.markdownTransformers);this.appendUserPart(n,!C(t)),this.registerCopyBlock(n,"user",i.userMessage)}}else{const o=new S(s,u(),void 0,this.markdownTransformers);this.appendUserPart(o,!C(t)),this.registerCopyBlock(o,"user",s)}break}case"assistant":{const s=c(t).trim()!=="";s&&this.closeOpenGroup(),this.appendAssistantMessage(t,!s);break}default:break}}appendAssistantMessage(t,e=!1){const s=new A(void 0,this.hideThinking,u(),this.hiddenThinkingLabel,this.markdownTransformers),i=w(t)?{...t,stopReason:"aborted",errorMessage:"Interrupted"}:t;s.updateContent(i),this.appendAssistantPart(s,e),this.registerCopyBlock(s,"assistant",c(t));const o=this.appendAssistantSeparator(e);return this.setAssistantSeparatorContent(o,t),o}appendAssistantSeparator(t=!1){const e=new R;return t?this.appendGroupMember(e):this.append(e),e}appendAssistantPart(t,e){e?this.appendGroupMember(t):this.append(t)}appendUserPart(t,e){e?this.appendGroupMember(t):this.append(t)}appendHumanAnswer(t){this.closeOpenGroup(),this.chatChildCount()>0&&this.append(new d(1));const e=new S(t,u(),void 0,this.markdownTransformers);this.append(e),this.registerCopyBlock(e,"user",t)}isLiveGroupRegion(){return this.appendTarget===this.historyContainer}ensureGroup(){if(!this.isLiveGroupRegion())return;if(this.openGroup)return this.openGroup;const t=new at,e={members:[],recap:t,activity:new rt(this.cwd,this.nodeRoster),toolCount:0,inFlight:new Set};return this.append(t),this.historyContainer.setHidden(t,!0),this.groups.push(e),this.openGroup=e,e}closeOpenGroup(){this.openGroup=void 0}appendGroupMember(t){const e=this.ensureGroup();return this.append(t),e&&e.members.push(t),e}removeGroupMember(t){for(const e of this.groups){const s=e.members.indexOf(t);s!==-1&&e.members.splice(s,1)}this.historyContainer.setHidden(t,!1)}appendToolComponent(t,e,s){const i=this.isLiveGroupRegion()&&!this.openGroup&&this.historyContainer.children.at(-1)instanceof R?this.historyContainer.children.at(-1):void 0;i&&this.historyContainer.removeChild(i);const o=this.ensureGroup();i&&(this.append(i),o?.members.push(i));const n=this.makeToolComponent(t,e,s);return n.activityCallId=e,this.appendGroupMember(n),this.registerCopyBlock(n,"tool",""),o&&(o.key??=e,o.toolCount++,o.inFlight.add(n),o.activity.noteCall(e,t,s)),n}noteGroupTool(t,e,s){if(t.activityCallId)for(const i of this.groups)i.members.includes(t)&&i.activity.noteCall(t.activityCallId,e,s)}settleGroupTool(t,e,s=!1){for(const i of this.groups)i.inFlight.delete(t),!(!t.activityCallId||!i.members.includes(t))&&(e===void 0?i.activity.resolveWithoutResult(t.activityCallId):i.activity.settle(t.activityCallId,e,s))}promoteStreamingAssistantToBoundary(t,e=!1){!this.streamingWasGroupMember||!e&&c(t).trim()===""||(this.streamingComponent&&this.removeGroupMember(this.streamingComponent),this.streamingToolSeparator&&this.removeGroupMember(this.streamingToolSeparator),this.streamingWasGroupMember=!1,this.closeOpenGroup())}seedToolGroupSummaries(t){this.groupSummaries.clear();for(const[e,s]of Object.entries(t))this.groupSummaries.set(e,s)}applyToolGroupSummary(t,e){if(this.deferIfBuilding(()=>this.applyToolGroupSummary(t,e)))return;this.projection=xt(this.projection,t,e);const s=this.projection.toolGroupSummaryDetails[t];s!==void 0&&(this.groupSummaries.set(t,s),this.applyToolDisplay())}applyGroupDisplay(t){const e=t.key===void 0?void 0:this.groupSummaries.get(t.key),s=this.foldSettledTools&&this.showGroupSummaries&&t.toolCount>0&&t.inFlight.size===0&&e!==void 0;t.recap.setRecap(s?e:void 0,t.toolCount,t.activity.activity(),this.detailedToolRecaps,this.recapPalette),this.historyContainer.setHidden(t.recap,!s);for(const i of t.members)this.historyContainer.setHidden(i,s)}updateFoldedToolSeparators(t=new Set(this.pendingTools.values())){const e=this.historyContainer.children;for(let s=0;s<e.length;s++){const i=e[s];if(!(i instanceof R))continue;const o=e[s+1];i.setFolded(this.foldSettledTools&&!this.historyContainer.hiddenChildren.has(i)&&o instanceof G&&!this.historyContainer.hiddenChildren.has(o)&&!t.has(o)),this.historyContainer.markDirty(i)}}setAssistantSeparatorContent(t,e){const s=e.content,i=Array.isArray(s)?s:[],o=i.some(r=>typeof r=="object"&&r!==null&&r.type==="text"&&typeof r.text=="string"&&r.text.trim()!==""),n=i.some(r=>typeof r=="object"&&r!==null&&r.type==="thinking"&&typeof r.thinking=="string"&&r.thinking.trim()!=="");this.foldedToolSeparatorContents.set(t,{hasText:o,hasThinking:n}),t.setSeparatesToolGroup(o||!this.hideThinking&&n)}makeToolComponent(t,e,s){const i=new ht;let o,n;if(t==="bash"){const a=Q(s,i);a===void 0?n=lt(this.cwd,i,this.backgroundBashHint):(n=a.definition,o=a.observeResult)}else if(t==="edit"){const a=nt(this.cwd,i);n=a.definition,o=a.observeResult}else t==="read"?n=dt(this.cwd,i):t==="write"&&(n=ct(this.cwd,i));let r;return r=new G(t,e,s,{showImages:this.showImages,imageWidthCells:this.imageWidthCells},n,this.componentTui(()=>r),this.cwd),r.setToolView(n===void 0?void 0:i,o),r.setExpanded(this.toolOutputExpanded),r}append(t){this.appendTarget.addChild(t)}chatChildCount(){return this.appendTarget.children.length}resetChat(){this.setActivity(void 0),this.settleBashComponent(),this.streamingComponent=void 0,this.streamingToolSeparator=void 0,this.streamingWasGroupMember=!1,this.foldedToolSeparatorContents.clear(),this.groups.length=0,this.openGroup=void 0,this.groupSummaries.clear(),this.nodeRoster.clear(),this.pendingTools.clear(),this.lastAssistantText=void 0,this.copyBlockRecords.length=0,this.copyIndex.clear(),this.transcriptFilePaths.length=0,this.pageBlocks.clear(),this.historyContainer.clear()}maybeAppendPageBlock(t){if(!this.inlinePageBlocks||this.appendTarget!==this.historyContainer)return;const e=Y(t);if(e===void 0||this.pageBlocks.has(e.pageId))return;const s=new J(e.pageId,this.pageOpenHint);this.pageBlocks.set(e.pageId,s),this.append(s),this.loadPageBlock(s)}async loadPageBlock(t){await t.refresh()&&(this.historyContainer.markDirty(t),this.tui.requestRender())}refreshInFlightTools(){if(this.pendingTools.size!==0){for(const t of this.pendingTools.values())this.historyContainer.markDirty(t);this.tui.requestRender()}}async refreshPageBlocks(){const t=[...this.pageBlocks.values()];(await Promise.all(t.map(async s=>{const i=await s.refresh();return i&&this.historyContainer.markDirty(s),i}))).some(Boolean)&&this.tui.requestRender()}makeLoader(t){let e;const s={requestRender:p(i=>{e&&!this.onActivityChange&&this.statusContainer.markDirty(e),this.tui.requestRender(i)},"requestRender"),terminal:this.tui.terminal};return e=new F(s,this.spinnerStyle,this.dimStyle,t),e}componentTui(t){return{requestRender:p(e=>{this.historyContainer.markDirty(t()),this.tui.requestRender(e)},"requestRender"),terminal:this.tui.terminal}}settleBashComponent(t){if(!this.bashComponent)return;const e=this.bashComponent;e.setComplete(t?.exitCode,t?.cancelled??!0,t?.truncated?{truncated:!0}:void 0,t?.fullOutputPath),this.historyContainer.markDirty(e),this.bashComponent=void 0}setActivity(t){if(this.activityLoader?.stop(),this.activityLoader=t,this.onActivityChange){this.onActivityChange(t);return}this.statusContainer.clear(),t&&this.statusContainer.addChild(t)}showStatus(t){this.closeOpenGroup(),this.append(new d(1)),this.append(new x(this.dimStyle(t),1,0))}showError(t){this.closeOpenGroup(),this.append(new d(1)),this.append(new x(this.errorStyle(t),1,0))}crtrOutputTheme(){return{fg:p((t,e)=>t==="error"?this.errorStyle(e):t==="warning"||t==="accent"||t==="toolTitle"||t==="success"?this.spinnerStyle(e):t==="muted"?this.dimStyle(e):e,"fg"),bg:p((t,e)=>e,"bg"),bold:p(t=>this.labelStyle(t),"bold")}}assistantToolCalls(t){const e=t.content;return Array.isArray(e)?e.filter(s=>typeof s=="object"&&s!==null&&s.type==="toolCall"):[]}getTranscriptFilePathsNewestFirst(){return[...this.transcriptFilePaths]}getLastAssistantText(){const t=this.lastAssistantText?.trim();return t||void 0}blockText(t){const e=this.copyIndex.get(t);return e===void 0?void 0:this.copyBlockRecords[e]?.text}copyBlocks(){return this.copyBlockRecords}getLastToolOutputText(){for(let t=this.copyBlockRecords.length-1;t>=0;t--){const e=this.copyBlockRecords[t];if(e.kind==="tool")return e.text.trim()===""?void 0:e.text}}getTranscriptPlainText(){return this.copyBlockRecords.map(t=>t.text).filter(t=>t.trim()!=="").join(`
|
|
2
|
+
|
|
3
|
+
`)}registerCopyBlock(t,e,s){const i=this.condensedCopyBlocks.get(this.appendTarget);if(i){const n=i.findIndex(r=>r.block===t);n===-1?i.push({block:t,kind:e,text:s}):i[n].text=s;return}const o=this.copyIndex.get(t);o===void 0?(this.copyIndex.set(t,this.copyBlockRecords.length),this.copyBlockRecords.push({block:t,kind:e,text:s})):this.copyBlockRecords[o].text=s}unregisterCopyBlock(t){const e=this.condensedCopyBlocks.get(this.appendTarget);if(e){const i=e.findIndex(o=>o.block===t);i!==-1&&e.splice(i,1);return}const s=this.copyIndex.get(t);if(s!==void 0){this.copyBlockRecords.splice(s,1),this.copyIndex.delete(t);for(let i=s;i<this.copyBlockRecords.length;i++)this.copyIndex.set(this.copyBlockRecords[i].block,i)}}appendCondensedBlock({component:t,copyBlocks:e}){this.append(t),this.registerCopyBlock(t,"condensed",e.map(s=>s.text).filter(s=>s.trim()!=="").join(`
|
|
4
|
+
|
|
5
|
+
`))}toolResultText(t){if(typeof t=="string")return t;if(typeof t=="object"&&t!==null&&"content"in t){const e=t.content;if(typeof e=="string")return e;if(Array.isArray(e))return e.filter(s=>typeof s=="object"&&s!==null&&s.type==="text"&&typeof s.text=="string").map(s=>s.text).join("")}try{const e=JSON.stringify(t);return typeof e=="string"?e:""}catch{return""}}pushTranscriptText(t){const e=t.trim();if(e==="")return;const s=mt([e],this.cwd);if(s.length===0)return;const i=[...s,...this.transcriptFilePaths.filter(o=>!s.includes(o))].slice(0,50);this.transcriptFilePaths.splice(0,this.transcriptFilePaths.length,...i)}pushTranscriptValue(t){try{const e=typeof t=="string"?t:JSON.stringify(t);typeof e=="string"&&this.pushTranscriptText(e)}catch{}}userMessageText(t){const e=t.content;return typeof e=="string"?e:Array.isArray(e)?e.filter(s=>typeof s=="object"&&s!==null&&s.type==="text").map(s=>s.text).join(""):""}}export{ue as ChatView};
|