@pellux/goodvibes-tui 2.0.21 → 2.1.0
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/CHANGELOG.md +58 -0
- package/README.md +16 -16
- package/docs/README.md +4 -4
- package/docs/foundation-artifacts/operator-contract.json +1 -1
- package/package.json +16 -6
- package/src/cli/management.ts +5 -2
- package/src/cli/tui-startup.ts +34 -39
- package/src/core/agent-view-render.ts +157 -0
- package/src/core/approval-alert.ts +49 -11
- package/src/core/bookmark-navigation.ts +7 -1
- package/src/core/budget-breach-notifier.ts +27 -8
- package/src/core/compaction-receipt.ts +1 -1
- package/src/core/context-usage.ts +1 -1
- package/src/core/conversation-compaction-render.ts +3 -3
- package/src/core/conversation-display-only.ts +86 -0
- package/src/core/conversation-event-navigation.ts +27 -0
- package/src/core/conversation-line-cache.ts +216 -447
- package/src/core/conversation-render-context.ts +20 -27
- package/src/core/conversation-rendering.ts +157 -575
- package/src/core/conversation-splash-state.ts +6 -1
- package/src/core/conversation-types.ts +35 -0
- package/src/core/conversation-usage.ts +12 -0
- package/src/core/conversation.ts +130 -131
- package/src/core/long-task-notifier.ts +100 -31
- package/src/core/notices.ts +75 -0
- package/src/core/pairing-tailscale-gateway.ts +1 -1
- package/src/core/process-output-log.ts +143 -0
- package/src/core/rewind-receipt.ts +1 -1
- package/src/core/session-focus.ts +190 -0
- package/src/core/session-resume-core.ts +23 -81
- package/src/core/stream-event-wiring.ts +31 -5
- package/src/core/system-message-noise.ts +2 -2
- package/src/core/system-message-router.ts +16 -18
- package/src/core/turn-event-wiring.ts +272 -33
- package/src/core/work-tree-focus.ts +290 -0
- package/src/core/work-tree-fold-store.ts +143 -0
- package/src/core/work-tree-model.ts +799 -0
- package/src/core/work-tree-render.ts +384 -0
- package/src/core/work-tree-sources.ts +184 -0
- package/src/core/work-tree-wiring.ts +176 -0
- package/src/core/workstream-notification.ts +36 -6
- package/src/core/wrfc-notice-titles.ts +37 -0
- package/src/input/agents-modal-text.ts +119 -0
- package/src/input/agents-modal.ts +699 -0
- package/src/input/bookmark-modal.ts +33 -9
- package/src/input/changes-git.ts +251 -0
- package/src/input/changes-modal.ts +629 -0
- package/src/input/changes-model.ts +125 -0
- package/src/input/command-palette-types.ts +41 -0
- package/src/input/command-palette.ts +272 -0
- package/src/input/command-registry.ts +77 -35
- package/src/input/commands/acp-runtime.ts +19 -9
- package/src/input/commands/channel-runtime.ts +2 -2
- package/src/input/commands/ci-runtime.ts +1 -1
- package/src/input/commands/codebase-runtime.ts +1 -1
- package/src/input/commands/config.ts +7 -1
- package/src/input/commands/context-window.ts +25 -19
- package/src/input/commands/control-room-runtime.ts +18 -18
- package/src/input/commands/conversation-runtime.ts +0 -1
- package/src/input/commands/cost-runtime.ts +29 -20
- package/src/input/commands/diff-runtime.ts +35 -181
- package/src/input/commands/eval.ts +1 -1
- package/src/input/commands/experience-runtime.ts +3 -7
- package/src/input/commands/fresh-conversation.ts +86 -0
- package/src/input/commands/git-runtime.ts +5 -22
- package/src/input/commands/graph-runtime.ts +1 -1
- package/src/input/commands/guidance-runtime.ts +1 -1
- package/src/input/commands/health-runtime.ts +8 -9
- package/src/input/commands/hooks-runtime.ts +2 -2
- package/src/input/commands/hosted-runtime.ts +3 -3
- package/src/input/commands/incident-runtime.ts +3 -3
- package/src/input/commands/intelligence-runtime.ts +6 -9
- package/src/input/commands/knowledge.ts +2 -2
- package/src/input/commands/legacy-panel-command.ts +57 -0
- package/src/input/commands/local-auth-runtime.ts +8 -9
- package/src/input/commands/local-provider-runtime.ts +7 -4
- package/src/input/commands/local-runtime.ts +12 -15
- package/src/input/commands/local-setup-review.ts +1 -1
- package/src/input/commands/local-setup.ts +13 -19
- package/src/input/commands/memory.ts +1 -1
- package/src/input/commands/notify-runtime.ts +9 -0
- package/src/input/commands/operator-runtime.ts +10 -12
- package/src/input/commands/permissions-provenance.ts +3 -3
- package/src/input/commands/planning-runtime.ts +7 -7
- package/src/input/commands/platform-sandbox-runtime.ts +2 -2
- package/src/input/commands/platform-services-runtime.ts +1 -1
- package/src/input/commands/policy-dispatch.ts +2 -2
- package/src/input/commands/policy.ts +3 -3
- package/src/input/commands/provider.ts +1 -1
- package/src/input/commands/remote-runtime.ts +1 -1
- package/src/input/commands/review-runtime.ts +39 -94
- package/src/input/commands/rewind-runtime.ts +81 -108
- package/src/input/commands/runtime-services.ts +15 -17
- package/src/input/commands/services-runtime.ts +2 -2
- package/src/input/commands/session-content.ts +21 -5
- package/src/input/commands/session-workflow.ts +13 -38
- package/src/input/commands/settings-sync-runtime.ts +2 -2
- package/src/input/commands/shell-core.ts +19 -4
- package/src/input/commands/skills-runtime.ts +2 -2
- package/src/input/commands/status-runtime.ts +13 -0
- package/src/input/commands/subscription-runtime.ts +1 -1
- package/src/input/commands/tasks-runtime.ts +2 -8
- package/src/input/commands/work-plan-runtime.ts +4 -4
- package/src/input/commands/workstream-attempts.ts +24 -47
- package/src/input/commands/workstream-runtime.ts +2 -2
- package/src/input/commands/worktree-runtime.ts +3 -3
- package/src/input/commands.ts +3 -1
- package/src/input/composer-editor.ts +44 -0
- package/src/input/concealed-input.ts +1 -1
- package/src/input/config-modal-types.ts +20 -8
- package/src/input/config-modal.ts +106 -105
- package/src/input/confirm-dialog-types.ts +28 -0
- package/src/input/confirm-dialog.ts +70 -0
- package/src/input/delete-key-policy.ts +3 -3
- package/src/input/feed-context-factory.ts +15 -16
- package/src/input/handler-command-route.ts +7 -42
- package/src/input/handler-content-actions.ts +16 -15
- package/src/input/handler-feed-routes.ts +26 -211
- package/src/input/handler-feed.ts +68 -95
- package/src/input/handler-interactions.ts +5 -3
- package/src/input/handler-modal-routes.ts +215 -216
- package/src/input/handler-modal-stack.ts +81 -11
- package/src/input/handler-modal-token-routes.ts +4 -0
- package/src/input/handler-onboarding.ts +0 -1
- package/src/input/handler-picker-routes.ts +65 -107
- package/src/input/handler-session-view-route.ts +149 -0
- package/src/input/handler-shortcuts.ts +16 -154
- package/src/input/handler-types.ts +4 -2
- package/src/input/handler-ui-state.ts +45 -15
- package/src/input/handler-work-tree-route.ts +123 -0
- package/src/input/handler.ts +25 -70
- package/src/input/keybindings.ts +16 -71
- package/src/input/masked-entry-modal.ts +117 -0
- package/src/input/mcp-workspace.ts +48 -17
- package/src/input/model-picker-filter.ts +8 -0
- package/src/input/model-picker-open.ts +99 -0
- package/src/input/model-picker-types.ts +1 -1
- package/src/input/model-picker.ts +92 -9
- package/src/input/notifications-modal.ts +123 -0
- package/src/input/overlay-filter.ts +26 -0
- package/src/input/profile-picker-modal.ts +37 -8
- package/src/input/search.ts +3 -3
- package/src/input/selection-modal-queue.ts +2 -0
- package/src/input/selection-modal.ts +28 -16
- package/src/input/session-picker-modal.ts +33 -8
- package/src/input/settings-modal-activation.ts +7 -2
- package/src/input/settings-modal-data.ts +11 -6
- package/src/input/settings-modal-types.ts +1 -1
- package/src/input/settings-modal.ts +20 -20
- package/src/input/submission-intent.ts +1 -1
- package/src/input/submission-router.ts +4 -9
- package/src/input/surface-modal-host.ts +110 -0
- package/src/input/theme-settings-actions.ts +82 -0
- package/src/input/usage-modal.ts +183 -0
- package/src/input/views.ts +97 -0
- package/src/main.ts +175 -165
- package/src/permissions/hunk-selection.ts +1 -1
- package/src/permissions/prompt-card.ts +511 -0
- package/src/permissions/prompt.ts +59 -622
- package/src/renderer/agents-modal.ts +310 -0
- package/src/renderer/autocomplete-overlay.ts +42 -220
- package/src/renderer/back-to-bottom.ts +80 -0
- package/src/renderer/block-actions-overlay.ts +30 -48
- package/src/renderer/bookmark-modal.ts +48 -79
- package/src/renderer/changes-modal.ts +325 -0
- package/src/renderer/code-block.ts +184 -106
- package/src/renderer/command-palette.ts +93 -0
- package/src/renderer/composer-fragments.ts +4 -4
- package/src/renderer/composer.ts +146 -0
- package/src/renderer/compositor.ts +26 -160
- package/src/renderer/config-modal.ts +185 -81
- package/src/renderer/confirm-dialog.ts +50 -0
- package/src/renderer/context-inspector.ts +116 -154
- package/src/renderer/context-status-hint.ts +4 -4
- package/src/renderer/conversation-layout.ts +20 -0
- package/src/renderer/conversation-overlays.ts +94 -84
- package/src/renderer/conversation-surface.ts +19 -38
- package/src/renderer/diff-tint.ts +98 -0
- package/src/renderer/file-picker-overlay.ts +63 -90
- package/src/renderer/footer-targets.ts +38 -0
- package/src/renderer/git-status.ts +3 -4
- package/src/renderer/header-line.ts +140 -117
- package/src/renderer/help-overlay.ts +133 -219
- package/src/renderer/history-search-overlay.ts +15 -12
- package/src/renderer/lane-graph/bead.ts +800 -0
- package/src/renderer/lane-graph/glyphs.ts +134 -0
- package/src/renderer/lane-graph/layout.ts +248 -0
- package/src/renderer/lane-graph/paint.ts +537 -0
- package/src/renderer/lane-graph/semantic-memo.ts +77 -0
- package/src/renderer/layout-engine.ts +2 -57
- package/src/renderer/layout.ts +7 -13
- package/src/renderer/markdown-inline.ts +2 -1
- package/src/renderer/markdown-table.ts +17 -12
- package/src/renderer/markdown.ts +92 -34
- package/src/renderer/masked-entry-modal.ts +78 -0
- package/src/renderer/mcp-workspace.ts +166 -203
- package/src/renderer/model-workspace.ts +381 -436
- package/src/renderer/notifications-modal.ts +116 -0
- package/src/renderer/onboarding/onboarding-wizard.ts +178 -588
- package/src/renderer/process-view.ts +192 -0
- package/src/renderer/profile-picker-modal.ts +58 -110
- package/src/renderer/search-overlay.ts +6 -3
- package/src/renderer/selection-modal-overlay.ts +87 -327
- package/src/renderer/semantic-diff.ts +2 -2
- package/src/renderer/session-chips.ts +102 -0
- package/src/renderer/session-picker-modal.ts +177 -297
- package/src/renderer/settings-modal-connections.ts +14 -23
- package/src/renderer/settings-modal-context.ts +367 -0
- package/src/renderer/settings-modal-helpers.ts +6 -11
- package/src/renderer/settings-modal.ts +322 -726
- package/src/renderer/shell-surface.ts +277 -175
- package/src/renderer/shortcuts-overlay.ts +217 -0
- package/src/renderer/status-line.ts +475 -0
- package/src/renderer/surface-compose.ts +174 -0
- package/src/renderer/surface-kit-extra.ts +303 -0
- package/src/renderer/surface-kit-list.ts +366 -0
- package/src/renderer/surface-kit-parts.ts +360 -0
- package/src/renderer/surface-kit.ts +568 -0
- package/src/renderer/syntax-highlighter.ts +280 -197
- package/src/renderer/syntax-theme.ts +51 -0
- package/src/renderer/system-message.ts +0 -1
- package/src/renderer/term-caps.ts +42 -1
- package/src/renderer/terminal-bg-probe.ts +116 -19
- package/src/renderer/terminal-palette-probe.ts +322 -0
- package/src/renderer/terminal-palette-reader.ts +183 -0
- package/src/renderer/terminal-palette.ts +58 -0
- package/src/renderer/theme-mode-config.ts +16 -1
- package/src/renderer/theme.ts +234 -207
- package/src/renderer/thinking.ts +0 -1
- package/src/renderer/throbber.ts +188 -0
- package/src/renderer/toast-center.ts +119 -0
- package/src/renderer/ui-factory.ts +39 -602
- package/src/renderer/ui-primitives.ts +8 -25
- package/src/renderer/usage-modal.ts +353 -0
- package/src/renderer/user-message.ts +58 -0
- package/src/renderer/voice-capture-chip.ts +53 -0
- package/src/runtime/bootstrap-command-context.ts +0 -5
- package/src/runtime/bootstrap-command-parts.ts +38 -89
- package/src/runtime/bootstrap-core.ts +13 -15
- package/src/runtime/bootstrap-hook-bridge.ts +12 -21
- package/src/runtime/bootstrap-notifier-sync.ts +17 -1
- package/src/runtime/bootstrap-shell.ts +16 -50
- package/src/runtime/bootstrap.ts +14 -14
- package/src/runtime/client/fleet-union.ts +5 -5
- package/src/runtime/client/hosted-exit.ts +2 -2
- package/src/runtime/client/hosted-sessions.ts +1 -1
- package/src/runtime/client/spine-adoption.ts +1 -1
- package/src/runtime/context-accounting-source.ts +5 -4
- package/src/runtime/index.ts +1 -0
- package/src/runtime/notification-dispatch.ts +102 -29
- package/src/runtime/recovery-offer-wiring.ts +4 -1
- package/src/runtime/recovery-prompt.ts +31 -15
- package/src/runtime/runtime-services-types.ts +10 -6
- package/src/runtime/services.ts +17 -12
- package/src/runtime/session-continuity-hints.ts +2 -5
- package/src/runtime/session-inbound-inputs.ts +1 -1
- package/src/runtime/session-resume-liveness-confirm.ts +14 -2
- package/src/runtime/startup-typeahead-gate.ts +103 -0
- package/src/runtime/store/domains/domain-read-matrix.ts +0 -1
- package/src/runtime/store/domains/index.ts +0 -8
- package/src/runtime/store/selectors/index.ts +0 -28
- package/src/runtime/store/state.ts +0 -8
- package/src/runtime/ui-services.ts +4 -6
- package/src/runtime/usage-tracker.ts +348 -0
- package/src/runtime/wrfc-persistence.ts +4 -4
- package/src/shell/blocking-input.ts +92 -2
- package/src/shell/recovery-input-helpers.ts +1 -1
- package/src/shell/session-views.ts +539 -0
- package/src/shell/status-report.ts +86 -0
- package/src/shell/transcript-scroll.ts +68 -0
- package/src/shell/ui-openers.ts +84 -172
- package/src/shell/view-openers.ts +205 -0
- package/src/tools/wrfc-agent-guard.ts +22 -2
- package/src/utils/format-duration.ts +4 -8
- package/src/utils/splash-lines.ts +9 -1
- package/src/utils/terminal-width.ts +56 -0
- package/src/verification/verification-ledger.ts +18 -16
- package/src/{panels → views}/agent-inspector-shared.ts +2 -2
- package/src/{panels → views}/builtin-modals.ts +22 -21
- package/src/views/builtin-views.ts +135 -0
- package/src/{panels → views}/confirm-state.ts +9 -9
- package/src/{panels → views}/diff-review-model.ts +10 -3
- package/src/{panels → views}/eval-registry.ts +1 -1
- package/src/{panels → views}/fleet-acts.ts +49 -85
- package/src/{panels/fleet-panel-format.ts → views/fleet-format.ts} +40 -40
- package/src/{panels → views}/fleet-gateway.ts +5 -5
- package/src/{panels → views}/fleet-observed-render.ts +16 -16
- package/src/{panels → views}/fleet-read-model.ts +9 -9
- package/src/{panels/fleet-tabs.ts → views/fleet-session-tabs.ts} +13 -13
- package/src/{panels → views}/fleet-spawn.ts +33 -49
- package/src/{panels → views}/fleet-steer.ts +12 -12
- package/src/{panels → views}/fleet-stop.ts +4 -4
- package/src/{panels → views}/fleet-transcript.ts +26 -27
- package/src/{panels/fleet-panel-worktree-detail.ts → views/fleet-worktree-detail.ts} +7 -7
- package/src/{panels → views}/hosted-session-feed.ts +6 -6
- package/src/views/modal-surface-registry.ts +41 -0
- package/src/{panels → views}/modals/devices-modal.ts +2 -2
- package/src/{panels → views}/modals/hooks-modal.ts +13 -13
- package/src/{panels → views}/modals/keybindings-modal.ts +19 -27
- package/src/{panels → views}/modals/knowledge-modal.ts +6 -5
- package/src/{panels → views}/modals/local-auth-modal.ts +22 -21
- package/src/{panels → views}/modals/marketplace-modal.ts +11 -11
- package/src/{panels → views}/modals/memory-modal.ts +8 -8
- package/src/{panels → views}/modals/modal-surface-helpers.ts +15 -5
- package/src/{panels → views}/modals/pairing-modal.ts +9 -9
- package/src/{panels → views}/modals/planning-modal.ts +15 -20
- package/src/{panels → views}/modals/plugins-modal.ts +6 -6
- package/src/{panels → views}/modals/policy-modal.ts +13 -5
- package/src/{panels → views}/modals/provider-health-modal.ts +4 -4
- package/src/{panels → views}/modals/remote-modal.ts +3 -3
- package/src/{panels → views}/modals/sandbox-modal.ts +4 -4
- package/src/{panels → views}/modals/security-modal.ts +22 -16
- package/src/{panels → views}/modals/services-modal.ts +3 -3
- package/src/{panels → views}/modals/settings-sync-modal.ts +4 -4
- package/src/{panels → views}/modals/skills-modal.ts +9 -9
- package/src/{panels → views}/modals/subscription-modal.ts +3 -3
- package/src/{panels → views}/modals/work-plan-modal.ts +10 -13
- package/src/views/notifications-feed.ts +314 -0
- package/src/{panels → views}/polish-core.ts +38 -36
- package/src/{panels → views}/polish-tables.ts +35 -26
- package/src/{panels → views}/polish.ts +101 -95
- package/src/{panels → views}/project-planning-answer-actions.ts +3 -3
- package/src/{panels → views}/provider-health-routes.ts +14 -14
- package/src/{panels → views}/search-focus.ts +8 -8
- package/src/{panels → views}/session-maintenance.ts +11 -11
- package/src/views/skills-discovery.ts +159 -0
- package/src/views/view-deps.ts +80 -0
- package/src/views/view-panel-adapter.ts +53 -0
- package/src/{panels → views}/workstream-graph-render.ts +1 -1
- package/src/core/conversation-fold.ts +0 -101
- package/src/core/conversation-turn-structure.ts +0 -464
- package/src/core/conversation-user-receipts.ts +0 -42
- package/src/input/commands/operator-panel-runtime.ts +0 -186
- package/src/input/panel-integration-actions.ts +0 -33
- package/src/input/panel-mouse-geometry.ts +0 -97
- package/src/input/panel-paste-flood-guard.ts +0 -86
- package/src/panels/base-panel.ts +0 -301
- package/src/panels/builtin/agent.ts +0 -27
- package/src/panels/builtin/development.ts +0 -92
- package/src/panels/builtin/knowledge.ts +0 -12
- package/src/panels/builtin/operations.ts +0 -177
- package/src/panels/builtin/session.ts +0 -81
- package/src/panels/builtin/shared.ts +0 -357
- package/src/panels/builtin-panels.ts +0 -28
- package/src/panels/cost-tracker-panel.ts +0 -746
- package/src/panels/diff-panel.ts +0 -797
- package/src/panels/diff-review-panel.ts +0 -395
- package/src/panels/expandable-list-panel.ts +0 -189
- package/src/panels/fleet-deep-link.ts +0 -31
- package/src/panels/fleet-panel.ts +0 -799
- package/src/panels/git-panel.ts +0 -800
- package/src/panels/hosted-session-panel.ts +0 -221
- package/src/panels/index.ts +0 -21
- package/src/panels/local-auth-panel.ts +0 -478
- package/src/panels/notifications-feed.ts +0 -127
- package/src/panels/notifications-panel.ts +0 -160
- package/src/panels/panel-confirm-overlay.ts +0 -72
- package/src/panels/panel-manager.ts +0 -791
- package/src/panels/plugins-panel.ts +0 -371
- package/src/panels/scrollable-list-panel.ts +0 -498
- package/src/panels/skills-panel.ts +0 -454
- package/src/panels/token-budget-panel.ts +0 -688
- package/src/panels/types.ts +0 -191
- package/src/panels/wrfc-panel-format.ts +0 -133
- package/src/renderer/diff-view.ts +0 -134
- package/src/renderer/fleet-tab-strip.ts +0 -56
- package/src/renderer/footer-tips.ts +0 -53
- package/src/renderer/fullscreen-primitives.ts +0 -146
- package/src/renderer/fullscreen-workspace.ts +0 -194
- package/src/renderer/hint-grammar.ts +0 -52
- package/src/renderer/modal-factory.ts +0 -480
- package/src/renderer/overlay-box.ts +0 -154
- package/src/renderer/overlay-viewport.ts +0 -104
- package/src/renderer/panel-composite.ts +0 -145
- package/src/renderer/panel-workspace-bar.ts +0 -54
- package/src/renderer/process-indicator.ts +0 -163
- package/src/renderer/tab-strip.ts +0 -222
- package/src/renderer/text-layout.ts +0 -31
- package/src/renderer/tool-call.ts +0 -276
- package/src/renderer/tool-result-expanded-lines.ts +0 -48
- package/src/renderer/tool-result-summary.ts +0 -219
- package/src/runtime/diagnostics/panels/index.ts +0 -21
- package/src/runtime/diagnostics/panels/ops.ts +0 -156
- package/src/runtime/perf/panel-contracts.ts +0 -32
- package/src/runtime/store/domains/panels.ts +0 -117
- /package/src/{panels → views}/memory-consolidation-gateway.ts +0 -0
- /package/src/{panels → views}/modals/modal-theme.ts +0 -0
- /package/src/{panels → views}/provider-health-domains.ts +0 -0
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// ---------------------------------------------------------------------------
|
|
2
|
-
// acp-runtime.ts,
|
|
3
|
-
//
|
|
4
|
-
//
|
|
2
|
+
// acp-runtime.ts, `/agents`. Bare `/agents` opens the Agents modal
|
|
3
|
+
// (`--target <id>[:<kind>]` selects a process in it). The scripted path for
|
|
4
|
+
// hosting third-party coding agents drives the SAME verbs the Agents modal's
|
|
5
|
+
// n key does (acp.agents.list / acp.sessions.create). `/agents list` shows what the daemon discovered
|
|
5
6
|
// (read-only, quiet when none); `/agents host <agentId> [dir]` spawns one as a
|
|
6
7
|
// long-lived daemon session that shows up as an acp-agent fleet row. A working
|
|
7
8
|
// directory defaults to the current one; a known workspace root can be named
|
|
@@ -14,17 +15,26 @@
|
|
|
14
15
|
|
|
15
16
|
import type { CommandRegistry } from '../command-registry.ts';
|
|
16
17
|
import { requireShellPaths } from './runtime-services.ts';
|
|
18
|
+
import { takeTargetFlag } from '../views.ts';
|
|
17
19
|
import { describeOperatorRpcError, getOperatorRpc } from './operator-rpc.ts';
|
|
18
20
|
|
|
19
21
|
export function registerAcpRuntimeCommands(registry: CommandRegistry): void {
|
|
20
22
|
registry.register({
|
|
21
23
|
name: 'agents',
|
|
22
24
|
aliases: ['acp'],
|
|
23
|
-
description: '
|
|
24
|
-
usage: 'list | host <agentId> [directory]',
|
|
25
|
-
argsHint: '[list|host]',
|
|
25
|
+
description: 'Open Agents (everything running: agents, chains, workflows, hosted sessions); list or host third-party coding agents over ACP',
|
|
26
|
+
usage: '[--target <id>[:<kind>]] | list | host <agentId> [directory]',
|
|
27
|
+
argsHint: '[list|host|--target <id>]',
|
|
26
28
|
async handler(args, ctx) {
|
|
27
|
-
const
|
|
29
|
+
const rest = [...args];
|
|
30
|
+
const target = takeTargetFlag(rest);
|
|
31
|
+
if (rest.length === 0) {
|
|
32
|
+
// Bare /agents (or /agents --target <id>) opens the Agents modal.
|
|
33
|
+
if (ctx.openAgents) ctx.openAgents({ target });
|
|
34
|
+
else ctx.print('The Agents view is not available in this session; /agents list prints the hostable agents.');
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const sub = (rest[0] ?? 'list').toLowerCase();
|
|
28
38
|
const rpc = getOperatorRpc(ctx);
|
|
29
39
|
if (!rpc.available) { ctx.print(`[agents] ${rpc.reason}`); return; }
|
|
30
40
|
|
|
@@ -46,12 +56,12 @@ export function registerAcpRuntimeCommands(registry: CommandRegistry): void {
|
|
|
46
56
|
}
|
|
47
57
|
|
|
48
58
|
if (sub === 'host') {
|
|
49
|
-
const agentId =
|
|
59
|
+
const agentId = rest[1];
|
|
50
60
|
if (!agentId) {
|
|
51
61
|
ctx.print('Usage: /agents host <agentId> [directory] (agentId from /agents list; directory defaults to the current one)');
|
|
52
62
|
return;
|
|
53
63
|
}
|
|
54
|
-
const cwd =
|
|
64
|
+
const cwd = rest[2] ?? requireShellPaths(ctx).workingDirectory;
|
|
55
65
|
try {
|
|
56
66
|
const { hosted, started } = await rpc.sdk.operator.invoke('acp.sessions.create', { agentId, cwd });
|
|
57
67
|
if (hosted.error) {
|
|
@@ -147,7 +147,7 @@ export function registerChannelRuntimeCommands(registry: CommandRegistry): void
|
|
|
147
147
|
const asJson = args.includes('--json');
|
|
148
148
|
|
|
149
149
|
if (!sub || sub === 'open' || sub === 'panel') {
|
|
150
|
-
|
|
150
|
+
ctx.openView?.('routes');
|
|
151
151
|
return;
|
|
152
152
|
}
|
|
153
153
|
|
|
@@ -269,7 +269,7 @@ export function registerChannelRuntimeCommands(registry: CommandRegistry): void
|
|
|
269
269
|
|
|
270
270
|
ctx.print(
|
|
271
271
|
'Usage: /channel <subcommand>\n'
|
|
272
|
-
+ ' (no args) — open
|
|
272
|
+
+ ' (no args) — open Agents (where routes live now)\n'
|
|
273
273
|
+ ' pair [surface] — guided channel pairing: list adapters, enter declared credentials, verify\n'
|
|
274
274
|
+ ' status — channel overview: routes, sessions, tasks, pending approvals\n'
|
|
275
275
|
+ ' routes — active route binding snapshot\n'
|
|
@@ -83,7 +83,7 @@ export function renderWatch(watch: CiWatchSubscription): string {
|
|
|
83
83
|
export function registerCiRuntimeCommands(registry: CommandRegistry): void {
|
|
84
84
|
registry.register({
|
|
85
85
|
name: 'ci',
|
|
86
|
-
description: 'CI-watch: one-shot per-job status and standing watches
|
|
86
|
+
description: 'CI-watch: one-shot per-job status and standing watches, surfaced in Agents',
|
|
87
87
|
usage: 'status <repo-or-pr> | watch <repo-or-pr> <deliveryChannel> [--fix-session] | watches | unwatch <id>',
|
|
88
88
|
argsHint: '[status|watch|watches|unwatch]',
|
|
89
89
|
async handler(args, ctx) {
|
|
@@ -201,7 +201,7 @@ export function registerCodebaseRuntimeCommands(registry: CommandRegistry): void
|
|
|
201
201
|
return;
|
|
202
202
|
}
|
|
203
203
|
store.scheduleBuild();
|
|
204
|
-
ctx.print('Build scheduled: track progress with /codebase status or
|
|
204
|
+
ctx.print('Build scheduled: track progress with /codebase status or Agents (F2, the code-index row).');
|
|
205
205
|
return;
|
|
206
206
|
}
|
|
207
207
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CommandContext, CommandRegistry } from '../command-registry.ts';
|
|
2
2
|
import type { ConfigKey } from '@pellux/goodvibes-sdk/platform/config';
|
|
3
|
-
import { setActiveThemeMode, type ThemeMode } from '../../renderer/theme.ts';
|
|
3
|
+
import { setActiveThemeMode, setActiveThemeName, type ThemeMode } from '../../renderer/theme.ts';
|
|
4
4
|
import {
|
|
5
5
|
buildGoodVibesSecretKey,
|
|
6
6
|
defaultSecretBackedScope,
|
|
@@ -45,9 +45,15 @@ export function registerConfigCommand(registry: CommandRegistry): void {
|
|
|
45
45
|
ctx.print(`Set ${key}: ${JSON.stringify(before)} → ${JSON.stringify(after)}`);
|
|
46
46
|
// Forced theme modes apply immediately (matches the settings-modal
|
|
47
47
|
// path); 'auto' re-probes on the next launch (stated honestly).
|
|
48
|
+
if (key === 'display.theme') {
|
|
49
|
+
const applied = setActiveThemeName(after);
|
|
50
|
+
ctx.requestFullRepaint?.();
|
|
51
|
+
ctx.print(`Theme applied: ${applied}.`);
|
|
52
|
+
}
|
|
48
53
|
if (key === 'display.themeMode') {
|
|
49
54
|
if (after === 'dark' || after === 'light') {
|
|
50
55
|
setActiveThemeMode(after as ThemeMode);
|
|
56
|
+
ctx.requestFullRepaint?.();
|
|
51
57
|
ctx.print('Theme applied. Note: transcript, modal, and header/footer/thinking chrome all flip; only the background colour follows your terminal.');
|
|
52
58
|
} else {
|
|
53
59
|
ctx.print('Theme mode "auto" probes the terminal background on the next launch.');
|
|
@@ -6,11 +6,13 @@
|
|
|
6
6
|
* control-plane config dir with provenance 'configured_cap'), so it survives
|
|
7
7
|
* restarts, applies to any model (cloud or local), and is honored by every
|
|
8
8
|
* consumer of the same home. Clearing returns the model to its automatic
|
|
9
|
-
* window (catalog / provider API / family fallback).
|
|
9
|
+
* window (catalog / provider API / family fallback). The source line names
|
|
10
|
+
* where the window came from, with the SDK's describeContextWindowSource
|
|
11
|
+
* ('catalog: abacus', 'consensus of 4 providers', 'family default').
|
|
10
12
|
*/
|
|
11
13
|
import type { CommandContext } from '../command-registry.ts';
|
|
12
14
|
import type { ModelDefinition } from '@pellux/goodvibes-sdk/platform/providers';
|
|
13
|
-
import { MAX_CONTEXT_WINDOW_OVERRIDE } from '@pellux/goodvibes-sdk/platform/providers';
|
|
15
|
+
import { MAX_CONTEXT_WINDOW_OVERRIDE, describeContextWindowSource } from '@pellux/goodvibes-sdk/platform/providers';
|
|
14
16
|
|
|
15
17
|
/**
|
|
16
18
|
* Parse a user-supplied context window size. Accepts plain token counts
|
|
@@ -28,26 +30,28 @@ export function parseContextWindowSize(raw: string): number | null {
|
|
|
28
30
|
return value;
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
function describeProvenance(model: ModelDefinition): string {
|
|
32
|
-
switch (model.contextWindowProvenance) {
|
|
33
|
-
case 'configured_cap': return 'custom override';
|
|
34
|
-
case 'observed_limit': return 'learned from a provider rejection';
|
|
35
|
-
case 'provider_api': return 'reported by the provider';
|
|
36
|
-
case 'fallback': return 'family default (no catalog entry)';
|
|
37
|
-
default: return 'model catalog';
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
|
|
41
33
|
/** Status text for the current model's window + override state. */
|
|
42
34
|
export function buildContextWindowStatusText(
|
|
43
35
|
model: ModelDefinition,
|
|
44
|
-
|
|
36
|
+
/** The window a source states, or null when unknown. */
|
|
37
|
+
resolvedWindow: number | null,
|
|
45
38
|
override: number | null,
|
|
46
39
|
observed: number | null = null,
|
|
47
40
|
): string {
|
|
41
|
+
const resolvedText = resolvedWindow === null
|
|
42
|
+
? model.contextWindowProvenance === 'accepted_floor'
|
|
43
|
+
? `unknown (the provider accepted ${model.contextWindow.toLocaleString()} tokens, more than the stated window)`
|
|
44
|
+
: model.contextWindowOrigin?.kind === 'family_default'
|
|
45
|
+
? `unknown (no catalog provider lists this model; the family default of ${model.contextWindow.toLocaleString()} tokens is a guess)`
|
|
46
|
+
: 'unknown (no catalog entry or provider report states it)'
|
|
47
|
+
: `${resolvedWindow.toLocaleString()} tokens`;
|
|
48
|
+
const sourceText = resolvedWindow === null && model.contextWindowProvenance === 'accepted_floor'
|
|
49
|
+
? null
|
|
50
|
+
: describeContextWindowSource(model);
|
|
48
51
|
const lines = [
|
|
49
52
|
`Context window for ${model.displayName} (${model.registryKey}):`,
|
|
50
|
-
` resolved: ${
|
|
53
|
+
` resolved: ${resolvedText}`,
|
|
54
|
+
...(sourceText === null ? [] : [` source: ${sourceText}`]),
|
|
51
55
|
` override: ${override === null ? 'none (automatic)' : `${override.toLocaleString()} tokens`}`,
|
|
52
56
|
];
|
|
53
57
|
if (observed !== null) {
|
|
@@ -71,23 +75,25 @@ export function handleContextWindowSubcommand(args: readonly string[], ctx: Comm
|
|
|
71
75
|
if (arg === '') {
|
|
72
76
|
output = buildContextWindowStatusText(
|
|
73
77
|
model,
|
|
74
|
-
registry.
|
|
78
|
+
registry.getKnownContextWindowForModel(model),
|
|
75
79
|
registry.getModelContextCap(model.registryKey),
|
|
76
80
|
registry.getObservedContextWindow(model.registryKey),
|
|
77
81
|
);
|
|
78
82
|
} else if (arg === 'clear' || arg === 'auto' || arg === 'reset') {
|
|
79
83
|
const existed = registry.clearModelContextCap(model.registryKey);
|
|
80
|
-
const
|
|
84
|
+
const known = registry.getKnownContextWindowForModel(registry.getCurrentModel());
|
|
85
|
+
const resolved = known === null ? 'unknown' : `${known.toLocaleString()} tokens`;
|
|
81
86
|
output = existed
|
|
82
|
-
? `Context window settings cleared for ${model.displayName} (custom override and any learned limit). Back to automatic: ${resolved
|
|
83
|
-
: `${model.displayName} has no custom context window or learned limit set (automatic: ${resolved
|
|
87
|
+
? `Context window settings cleared for ${model.displayName} (custom override and any learned limit). Back to automatic: ${resolved}.`
|
|
88
|
+
: `${model.displayName} has no custom context window or learned limit set (automatic: ${resolved}).`;
|
|
84
89
|
} else {
|
|
85
90
|
const size = parseContextWindowSize(arg);
|
|
86
91
|
if (size === null) {
|
|
87
92
|
output = `Invalid size '${args[0]}'. Use a token count between 1 and ${MAX_CONTEXT_WINDOW_OVERRIDE.toLocaleString()}, e.g. 120000, 200k, 1m, or 'clear'.`;
|
|
88
93
|
} else {
|
|
94
|
+
const was = registry.getKnownContextWindowForModel(model);
|
|
89
95
|
registry.setModelContextCap(model.registryKey, size);
|
|
90
|
-
output = `Context window for ${model.displayName} set to ${size.toLocaleString()} tokens (was ${
|
|
96
|
+
output = `Context window for ${model.displayName} set to ${size.toLocaleString()} tokens (was ${was === null ? 'unknown' : `${was.toLocaleString()} tokens`}). Clear with /context window clear.`;
|
|
91
97
|
}
|
|
92
98
|
}
|
|
93
99
|
|
|
@@ -9,13 +9,13 @@ export function registerControlRoomRuntimeCommands(registry: CommandRegistry): v
|
|
|
9
9
|
registry.register({
|
|
10
10
|
name: 'cockpit',
|
|
11
11
|
aliases: [],
|
|
12
|
-
description: 'Open the
|
|
12
|
+
description: 'Open Agents (the old operator cockpit)',
|
|
13
13
|
handler(_args, ctx) {
|
|
14
|
-
if (ctx.
|
|
15
|
-
ctx.
|
|
14
|
+
if (ctx.openCockpitView) {
|
|
15
|
+
ctx.openCockpitView();
|
|
16
16
|
return;
|
|
17
17
|
}
|
|
18
|
-
ctx.print('
|
|
18
|
+
ctx.print('The Agents view is not available in this runtime.');
|
|
19
19
|
},
|
|
20
20
|
});
|
|
21
21
|
|
|
@@ -27,12 +27,12 @@ export function registerControlRoomRuntimeCommands(registry: CommandRegistry): v
|
|
|
27
27
|
handler(args, ctx) {
|
|
28
28
|
const graphs = [...requireReadModels(ctx).orchestration.getSnapshot().graphs];
|
|
29
29
|
if (args.length === 0) {
|
|
30
|
-
if (ctx.
|
|
31
|
-
ctx.
|
|
30
|
+
if (ctx.openOrchestrationView) {
|
|
31
|
+
ctx.openOrchestrationView();
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
34
|
if (graphs.length === 0) {
|
|
35
|
-
ctx.print('
|
|
35
|
+
ctx.print('The Agents view is not available in this runtime.');
|
|
36
36
|
return;
|
|
37
37
|
}
|
|
38
38
|
}
|
|
@@ -103,11 +103,11 @@ export function registerControlRoomRuntimeCommands(registry: CommandRegistry): v
|
|
|
103
103
|
aliases: ['comms'],
|
|
104
104
|
description: 'Inspect structured agent communication routes and recent activity',
|
|
105
105
|
handler(_args, ctx) {
|
|
106
|
-
if (ctx.
|
|
107
|
-
ctx.
|
|
106
|
+
if (ctx.openCommunicationView) {
|
|
107
|
+
ctx.openCommunicationView();
|
|
108
108
|
return;
|
|
109
109
|
}
|
|
110
|
-
ctx.print('
|
|
110
|
+
ctx.print('The Agents view is not available in this runtime.');
|
|
111
111
|
},
|
|
112
112
|
});
|
|
113
113
|
|
|
@@ -118,11 +118,11 @@ export function registerControlRoomRuntimeCommands(registry: CommandRegistry): v
|
|
|
118
118
|
usage: '[review | attack-paths | tokens]',
|
|
119
119
|
handler(args, ctx) {
|
|
120
120
|
if (args.length === 0) {
|
|
121
|
-
if (ctx.
|
|
122
|
-
ctx.
|
|
121
|
+
if (ctx.openSecurityView) {
|
|
122
|
+
ctx.openSecurityView();
|
|
123
123
|
return;
|
|
124
124
|
}
|
|
125
|
-
ctx.print('Security
|
|
125
|
+
ctx.print('The Security view is not available in this runtime.');
|
|
126
126
|
return;
|
|
127
127
|
}
|
|
128
128
|
|
|
@@ -201,11 +201,11 @@ export function registerControlRoomRuntimeCommands(registry: CommandRegistry): v
|
|
|
201
201
|
async handler(args, ctx) {
|
|
202
202
|
const subcommand = (args[0] ?? 'open').toLowerCase();
|
|
203
203
|
if (subcommand === 'open') {
|
|
204
|
-
if (ctx.
|
|
205
|
-
ctx.
|
|
204
|
+
if (ctx.openMemoryView) {
|
|
205
|
+
ctx.openMemoryView();
|
|
206
206
|
return;
|
|
207
207
|
}
|
|
208
|
-
ctx.print('Memory
|
|
208
|
+
ctx.print('The Memory view is not available in this runtime.');
|
|
209
209
|
return;
|
|
210
210
|
}
|
|
211
211
|
if (subcommand === 'queue') {
|
|
@@ -250,8 +250,8 @@ export function registerControlRoomRuntimeCommands(registry: CommandRegistry): v
|
|
|
250
250
|
ctx.print(prompt ?? 'No reviewed project knowledge matched that task.');
|
|
251
251
|
return;
|
|
252
252
|
}
|
|
253
|
-
if (ctx.
|
|
254
|
-
ctx.
|
|
253
|
+
if (ctx.openMemoryView) {
|
|
254
|
+
ctx.openMemoryView();
|
|
255
255
|
return;
|
|
256
256
|
}
|
|
257
257
|
ctx.print(`Unknown project-memory subcommand: ${subcommand}`);
|
|
@@ -79,7 +79,6 @@ function buildComposerReview(ctx: CommandContext): string[] {
|
|
|
79
79
|
const composer = deriveComposerState({
|
|
80
80
|
text: '',
|
|
81
81
|
commandMode: false,
|
|
82
|
-
panelFocused: false,
|
|
83
82
|
pendingApproval: session.pendingApproval,
|
|
84
83
|
hasAttachments: false,
|
|
85
84
|
turnState: session.turnState,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import type { CommandRegistry } from '../command-registry.ts';
|
|
2
|
-
import {
|
|
3
|
-
import { openCommandPanel, requirePanelManager } from './runtime-services.ts';
|
|
2
|
+
import { BUDGET_ALERT_USD_CONFIG_KEY } from '@pellux/goodvibes-sdk/platform/providers';
|
|
4
3
|
import { describeOperatorRpcError, getOperatorRpc } from './operator-rpc.ts';
|
|
5
4
|
import {
|
|
6
5
|
COST_ATTRIBUTION_OPTIONAL_DIMENSIONS,
|
|
@@ -11,23 +10,37 @@ import {
|
|
|
11
10
|
} from './cost-attribution-format.ts';
|
|
12
11
|
|
|
13
12
|
/**
|
|
14
|
-
* /cost
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* the alert
|
|
19
|
-
* pattern (local-auth-runtime.ts) rather than only printing a signpost.
|
|
13
|
+
* /usage and /cost. `/usage` (and `/cost` or `/cost panel`) opens the Usage
|
|
14
|
+
* modal. `/cost budget <usd>` sets the budget alert: it writes the
|
|
15
|
+
* behavior.budgetAlertUsd setting, the one the Usage modal's b key, the Usage
|
|
16
|
+
* modal's budget row and the background budget-breach notifier all read, so
|
|
17
|
+
* the alert is real wherever it shows. 0 turns it off.
|
|
20
18
|
*/
|
|
21
19
|
export function registerCostRuntimeCommands(registry: CommandRegistry): void {
|
|
20
|
+
registry.register({
|
|
21
|
+
name: 'usage',
|
|
22
|
+
description: 'Context pressure, session tokens and cost, per-turn history, per-agent costs and the budget alert',
|
|
23
|
+
usage: '[turns|agents]',
|
|
24
|
+
handler(args, ctx) {
|
|
25
|
+
const tab = (args[0] ?? '').toLowerCase();
|
|
26
|
+
if (!ctx.openUsage) {
|
|
27
|
+
ctx.print('The Usage view is not available in this session.');
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
ctx.openUsage({ tab: tab === 'turns' || tab === 'agents' ? tab : undefined });
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
|
|
22
34
|
registry.register({
|
|
23
35
|
name: 'cost',
|
|
24
|
-
description: '
|
|
36
|
+
description: 'Open Usage, set the session budget alert, or show windowed cost attribution',
|
|
25
37
|
usage: '[panel|budget <usd>|attribution [24h|7d] [--json]]',
|
|
26
38
|
async handler(args, ctx) {
|
|
27
39
|
const sub = (args[0] ?? 'panel').toLowerCase();
|
|
28
40
|
|
|
29
41
|
if (sub === 'panel' || sub === 'open') {
|
|
30
|
-
|
|
42
|
+
if (ctx.openUsage) ctx.openUsage();
|
|
43
|
+
else ctx.print('The Usage view is not available in this session.');
|
|
31
44
|
return;
|
|
32
45
|
}
|
|
33
46
|
|
|
@@ -38,16 +51,12 @@ export function registerCostRuntimeCommands(registry: CommandRegistry): void {
|
|
|
38
51
|
ctx.print('Usage: /cost budget <usd> (0 disables the alert)');
|
|
39
52
|
return;
|
|
40
53
|
}
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
: 'Cost budget alert disabled.');
|
|
48
|
-
} else {
|
|
49
|
-
ctx.print('Cost tracking is not available in this session.');
|
|
50
|
-
}
|
|
54
|
+
const config = ctx.platform.configManager;
|
|
55
|
+
config.set(BUDGET_ALERT_USD_CONFIG_KEY as Parameters<typeof config.set>[0], usd as never);
|
|
56
|
+
ctx.print(usd > 0
|
|
57
|
+
? `Cost budget alert set to $${usd.toFixed(2)}.`
|
|
58
|
+
: 'Cost budget alert disabled.');
|
|
59
|
+
ctx.renderRequest();
|
|
51
60
|
return;
|
|
52
61
|
}
|
|
53
62
|
|
|
@@ -1,193 +1,47 @@
|
|
|
1
|
-
import { join } from 'path';
|
|
2
|
-
import { logger } from '@pellux/goodvibes-sdk/platform/utils';
|
|
3
|
-
import { GitService } from '@pellux/goodvibes-sdk/platform/git';
|
|
4
1
|
import type { CommandContext, CommandRegistry } from '../command-registry.ts';
|
|
5
|
-
import {
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
*/
|
|
15
|
-
async function runGitNameOnly(args: string[], cwd: string): Promise<{ files: string[]; errText: string; ok: boolean }> {
|
|
16
|
-
const proc = Bun.spawn(args, { stdout: 'pipe', stderr: 'pipe', cwd });
|
|
17
|
-
const [out, errRaw] = await Promise.all([
|
|
18
|
-
new Response(proc.stdout).text(),
|
|
19
|
-
new Response(proc.stderr).text(),
|
|
20
|
-
]);
|
|
21
|
-
const exitCode = await proc.exited;
|
|
22
|
-
return {
|
|
23
|
-
files: out.trim().split('\n').filter(Boolean),
|
|
24
|
-
errText: errRaw.trim(),
|
|
25
|
-
ok: exitCode === 0,
|
|
26
|
-
};
|
|
2
|
+
import type { ChangesSource } from '../changes-git.ts';
|
|
3
|
+
|
|
4
|
+
/** `session` (default), `working` (not staged), `staged`, or `head` (everything vs HEAD). */
|
|
5
|
+
function sourceFor(arg: string | undefined): ChangesSource {
|
|
6
|
+
const sub = (arg ?? 'session').toLowerCase();
|
|
7
|
+
if (sub === 'working' || sub === 'unstaged') return 'working';
|
|
8
|
+
if (sub === 'staged' || sub === 'cached') return 'staged';
|
|
9
|
+
if (sub === 'head' || sub === 'all') return 'head';
|
|
10
|
+
return 'session';
|
|
27
11
|
}
|
|
28
12
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
ctx.
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async function enrichSemanticDiff(
|
|
38
|
-
panel: InstanceType<typeof import('../../panels/diff-panel.ts').DiffPanel>,
|
|
39
|
-
files: string[],
|
|
40
|
-
ref: string,
|
|
41
|
-
renderFn: () => void,
|
|
42
|
-
workingDirectory: string,
|
|
43
|
-
): Promise<void> {
|
|
44
|
-
const { computeSemanticDiff, formatSemanticDiffSummary } = await import('../../renderer/semantic-diff.ts');
|
|
45
|
-
const { relative: pathRelative } = await import('path');
|
|
46
|
-
const repoRootProc = Bun.spawn(['git', 'rev-parse', '--show-toplevel'], { stdout: 'pipe', stderr: 'pipe', cwd: workingDirectory });
|
|
47
|
-
await repoRootProc.exited;
|
|
48
|
-
const repoRoot = (await new Response(repoRootProc.stdout).text()).trim() || workingDirectory;
|
|
49
|
-
await Promise.allSettled(
|
|
50
|
-
files.map(async (filePath) => {
|
|
51
|
-
try {
|
|
52
|
-
const absPath = filePath.startsWith('/') ? filePath : join(workingDirectory, filePath);
|
|
53
|
-
const repoRelPath = filePath.startsWith('/') ? pathRelative(repoRoot, filePath) : filePath;
|
|
54
|
-
const [beforeResult, afterResult] = await Promise.allSettled([
|
|
55
|
-
(async () => {
|
|
56
|
-
const proc = Bun.spawn(
|
|
57
|
-
['git', 'show', `${ref}:${repoRelPath}`],
|
|
58
|
-
{ stdout: 'pipe', stderr: 'pipe', cwd: repoRoot },
|
|
59
|
-
);
|
|
60
|
-
const [text, exitCode] = await Promise.all([new Response(proc.stdout).text(), proc.exited]);
|
|
61
|
-
if (exitCode !== 0) throw new Error(`git show failed for ${repoRelPath}`);
|
|
62
|
-
return text;
|
|
63
|
-
})(),
|
|
64
|
-
Bun.file(absPath).text(),
|
|
65
|
-
]);
|
|
66
|
-
if (beforeResult.status !== 'fulfilled' || afterResult.status !== 'fulfilled') return;
|
|
67
|
-
const semanticDiff = await computeSemanticDiff(filePath, beforeResult.value, afterResult.value);
|
|
68
|
-
if (!semanticDiff) return;
|
|
69
|
-
const summary = formatSemanticDiffSummary(semanticDiff);
|
|
70
|
-
if (summary) {
|
|
71
|
-
panel.setSemanticSummary(filePath, summary);
|
|
72
|
-
renderFn();
|
|
73
|
-
}
|
|
74
|
-
} catch {
|
|
75
|
-
// best-effort only
|
|
76
|
-
}
|
|
77
|
-
}),
|
|
78
|
-
);
|
|
13
|
+
function openChanges(ctx: CommandContext, args: string[]): void {
|
|
14
|
+
if (!ctx.openChanges) {
|
|
15
|
+
ctx.print('The Changes view is not available in this session.');
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
ctx.openChanges({ source: sourceFor(args[0]) });
|
|
79
19
|
}
|
|
80
20
|
|
|
21
|
+
/**
|
|
22
|
+
* `/changes` and `/diff`: the Changes modal over this repository. With no
|
|
23
|
+
* argument it shows the files this session edited against HEAD (everything vs
|
|
24
|
+
* HEAD when none are tracked yet); `working`, `staged` and `head` pick the
|
|
25
|
+
* other views, which v also cycles inside the modal.
|
|
26
|
+
*/
|
|
81
27
|
export function registerDiffRuntimeCommands(registry: CommandRegistry): void {
|
|
28
|
+
registry.register({
|
|
29
|
+
name: 'changes',
|
|
30
|
+
description: 'Changed files with a tinted diff and semantic summary: stage hunks, comment for the model, mark reviewed',
|
|
31
|
+
usage: '[session|working|staged|head]',
|
|
32
|
+
argsHint: '[session|working|staged|head]',
|
|
33
|
+
handler(args, ctx) {
|
|
34
|
+
openChanges(ctx, args);
|
|
35
|
+
},
|
|
36
|
+
});
|
|
82
37
|
registry.register({
|
|
83
38
|
name: 'diff',
|
|
84
39
|
aliases: ['d'],
|
|
85
|
-
description: 'Show
|
|
86
|
-
usage: '[session|head|working|staged
|
|
87
|
-
argsHint: '[session|head|working|staged
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
const workingDirectory = shellPaths.workingDirectory;
|
|
91
|
-
// Gate before any git spawn happens (same defensive check /git already
|
|
92
|
-
// has), every subcommand below shells out to git, and without this
|
|
93
|
-
// they each produced a differently-shaped error for the same
|
|
94
|
-
// not-a-git-repo condition.
|
|
95
|
-
if (!GitService.isGitRepo(workingDirectory)) {
|
|
96
|
-
ctx.print('Not a git repository here. Run /git to initialize one.');
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
const { DiffPanel } = await import('../../panels/diff-panel.ts');
|
|
100
|
-
|
|
101
|
-
const pm = requirePanelManager(ctx);
|
|
102
|
-
let panel = pm.getAllOpen().find(p => p.id === 'diff');
|
|
103
|
-
if (!panel) {
|
|
104
|
-
try {
|
|
105
|
-
panel = pm.open('diff');
|
|
106
|
-
} catch {
|
|
107
|
-
ctx.print('Could not open diff panel.');
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
pm.activateById('diff');
|
|
112
|
-
if (!pm.isVisible()) pm.show();
|
|
113
|
-
ctx.focusPanels?.();
|
|
114
|
-
|
|
115
|
-
const diffPanel = panel as InstanceType<typeof DiffPanel>;
|
|
116
|
-
const sub = (args[0] ?? 'session').toLowerCase();
|
|
117
|
-
|
|
118
|
-
switch (sub) {
|
|
119
|
-
case 'working': {
|
|
120
|
-
ctx.print('Loading working-tree diff...');
|
|
121
|
-
await diffPanel.showGitDiff();
|
|
122
|
-
ctx.print('Diff panel updated: working tree changes.');
|
|
123
|
-
const workingChanged = await runGitNameOnly(['git', 'diff', '--name-only'], workingDirectory);
|
|
124
|
-
if (!workingChanged.ok) {
|
|
125
|
-
reportGitNameOnlyFailure(ctx, 'git diff --name-only', workingChanged.errText);
|
|
126
|
-
} else if (workingChanged.files.length > 0) {
|
|
127
|
-
enrichSemanticDiff(diffPanel, workingChanged.files, 'HEAD', () => ctx.renderRequest(), workingDirectory).catch((err) => { logger.debug('semantic diff enrichment failed', { err }); });
|
|
128
|
-
}
|
|
129
|
-
break;
|
|
130
|
-
}
|
|
131
|
-
case 'staged': {
|
|
132
|
-
ctx.print('Loading staged diff...');
|
|
133
|
-
const proc = Bun.spawn(['/bin/sh', '-c', 'git diff --cached'], { stdout: 'pipe', stderr: 'pipe', cwd: workingDirectory });
|
|
134
|
-
const [raw, errText] = await Promise.all([new Response(proc.stdout).text(), new Response(proc.stderr).text()]);
|
|
135
|
-
const exitCode = await proc.exited;
|
|
136
|
-
if (exitCode !== 0) {
|
|
137
|
-
ctx.print(`git diff --cached failed: ${errText.trim() || 'unknown error'}`);
|
|
138
|
-
return;
|
|
139
|
-
}
|
|
140
|
-
if (!raw.trim()) {
|
|
141
|
-
ctx.print('No staged changes.');
|
|
142
|
-
diffPanel.showDiff('(no staged changes)', '@@ -0,0 +0,0 @@\n No staged changes.');
|
|
143
|
-
} else {
|
|
144
|
-
diffPanel.loadRawDiff(raw);
|
|
145
|
-
ctx.print('Diff panel updated: staged changes.');
|
|
146
|
-
const stagedChanged = await runGitNameOnly(['git', 'diff', '--cached', '--name-only'], workingDirectory);
|
|
147
|
-
if (!stagedChanged.ok) {
|
|
148
|
-
reportGitNameOnlyFailure(ctx, 'git diff --cached --name-only', stagedChanged.errText);
|
|
149
|
-
} else if (stagedChanged.files.length > 0) {
|
|
150
|
-
enrichSemanticDiff(diffPanel, stagedChanged.files, 'HEAD', () => ctx.renderRequest(), workingDirectory).catch((err) => { logger.debug('semantic diff enrichment failed', { err }); });
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
break;
|
|
154
|
-
}
|
|
155
|
-
case 'head': {
|
|
156
|
-
ctx.print('Loading diff vs HEAD...');
|
|
157
|
-
await diffPanel.showGitDiff('HEAD');
|
|
158
|
-
ctx.print('Diff panel updated: all changes vs HEAD.');
|
|
159
|
-
const headChanged = await runGitNameOnly(['git', 'diff', 'HEAD', '--name-only'], workingDirectory);
|
|
160
|
-
if (!headChanged.ok) {
|
|
161
|
-
reportGitNameOnlyFailure(ctx, 'git diff HEAD --name-only', headChanged.errText);
|
|
162
|
-
} else if (headChanged.files.length > 0) {
|
|
163
|
-
enrichSemanticDiff(diffPanel, headChanged.files, 'HEAD', () => ctx.renderRequest(), workingDirectory).catch((err) => { logger.debug('semantic diff enrichment failed', { err }); });
|
|
164
|
-
}
|
|
165
|
-
break;
|
|
166
|
-
}
|
|
167
|
-
case 'session':
|
|
168
|
-
default: {
|
|
169
|
-
const sessionFiles = requireSessionChangeTracker(ctx).getChangedFiles();
|
|
170
|
-
if (sessionFiles.length > 0) {
|
|
171
|
-
ctx.print(`Loading session diff (${sessionFiles.length} file${sessionFiles.length === 1 ? '' : 's'} changed this session)...`);
|
|
172
|
-
await diffPanel.showFileDiffs(sessionFiles, 'HEAD');
|
|
173
|
-
ctx.print(`Diff panel updated: ${sessionFiles.length} session file${sessionFiles.length === 1 ? '' : 's'}.`);
|
|
174
|
-
enrichSemanticDiff(diffPanel, sessionFiles, 'HEAD', () => ctx.renderRequest(), workingDirectory).catch((err) => { logger.debug('semantic diff enrichment failed', { err }); });
|
|
175
|
-
} else {
|
|
176
|
-
ctx.print('No session changes tracked yet. Showing diff vs HEAD...');
|
|
177
|
-
await diffPanel.showGitDiff('HEAD');
|
|
178
|
-
ctx.print('Diff panel updated: all changes vs HEAD.');
|
|
179
|
-
const fallback = await runGitNameOnly(['git', 'diff', 'HEAD', '--name-only'], workingDirectory);
|
|
180
|
-
if (!fallback.ok) {
|
|
181
|
-
reportGitNameOnlyFailure(ctx, 'git diff HEAD --name-only', fallback.errText);
|
|
182
|
-
} else if (fallback.files.length > 0) {
|
|
183
|
-
enrichSemanticDiff(diffPanel, fallback.files, 'HEAD', () => ctx.renderRequest(), workingDirectory).catch((err) => { logger.debug('semantic diff enrichment failed', { err }); });
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
break;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
ctx.renderRequest();
|
|
40
|
+
description: 'Show the diff of this session\'s file changes (or working, staged, or everything vs HEAD) in Changes',
|
|
41
|
+
usage: '[session|head|working|staged]',
|
|
42
|
+
argsHint: '[session|head|working|staged]',
|
|
43
|
+
handler(args, ctx) {
|
|
44
|
+
openChanges(ctx, args);
|
|
191
45
|
},
|
|
192
46
|
});
|
|
193
47
|
}
|
|
@@ -14,7 +14,7 @@ import { EvalRunner } from '@/runtime/index.ts';
|
|
|
14
14
|
import { BUILTIN_SUITES } from '@/runtime/index.ts';
|
|
15
15
|
import { formatScorecard } from '@/runtime/index.ts';
|
|
16
16
|
import { loadBaseline, captureBaseline, formatBaselineComparison, writeBaseline } from '@/runtime/index.ts';
|
|
17
|
-
import type { EvalRegistry } from '../../
|
|
17
|
+
import type { EvalRegistry } from '../../views/eval-registry.ts';
|
|
18
18
|
import { formatSuiteResult, formatGateResult } from '@/runtime/index.ts';
|
|
19
19
|
import { requireShellPaths } from './runtime-services.ts';
|
|
20
20
|
import { summarizeError } from '@pellux/goodvibes-sdk/platform/utils';
|