@pellux/goodvibes-agent 0.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/.goodvibes/GOODVIBES.md +35 -0
- package/.goodvibes/agents/reviewer.md +48 -0
- package/.goodvibes/skills/add-provider/SKILL.md +199 -0
- package/CHANGELOG.md +25 -0
- package/README.md +74 -0
- package/bin/goodvibes-agent.ts +2 -0
- package/docs/README.md +23 -0
- package/docs/deployment-and-services.md +57 -0
- package/docs/getting-started.md +53 -0
- package/docs/release-and-publishing.md +46 -0
- package/package.json +134 -0
- package/scripts/check-bun.sh +20 -0
- package/src/audio/player.ts +156 -0
- package/src/audio/spoken-turn-controller.ts +203 -0
- package/src/audio/spoken-turn-model-routing.ts +117 -0
- package/src/audio/spoken-turn-wiring.ts +44 -0
- package/src/audio/text-chunker.ts +110 -0
- package/src/cli/bundle-command.ts +227 -0
- package/src/cli/completion.ts +90 -0
- package/src/cli/config-overrides.ts +159 -0
- package/src/cli/endpoints.ts +63 -0
- package/src/cli/entrypoint.ts +172 -0
- package/src/cli/help.ts +299 -0
- package/src/cli/index.ts +11 -0
- package/src/cli/management-commands.ts +426 -0
- package/src/cli/management.ts +744 -0
- package/src/cli/network-posture.ts +46 -0
- package/src/cli/package-verification.ts +123 -0
- package/src/cli/parser.ts +369 -0
- package/src/cli/provider-auth-routes.ts +22 -0
- package/src/cli/provider-classification.ts +107 -0
- package/src/cli/redaction.ts +105 -0
- package/src/cli/service-command.ts +26 -0
- package/src/cli/service-posture.ts +482 -0
- package/src/cli/status.ts +383 -0
- package/src/cli/surface-command.ts +247 -0
- package/src/cli/tui-startup.ts +32 -0
- package/src/cli/types.ts +69 -0
- package/src/cli-flags.ts +21 -0
- package/src/config/goodvibes-home-audit.ts +465 -0
- package/src/config/index.ts +57 -0
- package/src/config/provider-model.ts +23 -0
- package/src/config/secret-config.ts +119 -0
- package/src/config/secrets.ts +71 -0
- package/src/config/surface.ts +1 -0
- package/src/core/composer-state.ts +61 -0
- package/src/core/conversation-rendering.ts +359 -0
- package/src/core/conversation.ts +551 -0
- package/src/core/history.ts +45 -0
- package/src/core/orchestrator.ts +7 -0
- package/src/core/system-message-router.ts +171 -0
- package/src/daemon/cli.ts +55 -0
- package/src/daemon/safe-serve.ts +61 -0
- package/src/input/agent-workspace.ts +428 -0
- package/src/input/autocomplete.ts +96 -0
- package/src/input/bookmark-modal.ts +115 -0
- package/src/input/command-args-hint.ts +36 -0
- package/src/input/command-registry.ts +329 -0
- package/src/input/commands/agent-externalized-tui.ts +73 -0
- package/src/input/commands/agent-workspace-runtime.ts +17 -0
- package/src/input/commands/branch-runtime.ts +72 -0
- package/src/input/commands/cloudflare-runtime.ts +370 -0
- package/src/input/commands/config.ts +18 -0
- package/src/input/commands/control-room-runtime.ts +255 -0
- package/src/input/commands/conversation-runtime.ts +207 -0
- package/src/input/commands/discovery-runtime.ts +52 -0
- package/src/input/commands/eval.ts +204 -0
- package/src/input/commands/experience-runtime.ts +278 -0
- package/src/input/commands/guidance-runtime.ts +106 -0
- package/src/input/commands/health-runtime.ts +434 -0
- package/src/input/commands/hooks-runtime.ts +148 -0
- package/src/input/commands/incident-runtime.ts +95 -0
- package/src/input/commands/integration-runtime.ts +394 -0
- package/src/input/commands/intelligence-runtime.ts +223 -0
- package/src/input/commands/knowledge.ts +531 -0
- package/src/input/commands/local-auth-runtime.ts +105 -0
- package/src/input/commands/local-provider-runtime.ts +170 -0
- package/src/input/commands/local-runtime.ts +392 -0
- package/src/input/commands/local-setup-review.ts +199 -0
- package/src/input/commands/local-setup-transfer.ts +135 -0
- package/src/input/commands/local-setup.ts +282 -0
- package/src/input/commands/managed-runtime.ts +209 -0
- package/src/input/commands/marketplace-runtime.ts +290 -0
- package/src/input/commands/mcp-runtime.ts +432 -0
- package/src/input/commands/memory-product-runtime.ts +111 -0
- package/src/input/commands/memory.ts +151 -0
- package/src/input/commands/notify-runtime.ts +83 -0
- package/src/input/commands/onboarding-runtime.ts +14 -0
- package/src/input/commands/operator-panel-runtime.ts +146 -0
- package/src/input/commands/operator-runtime.ts +392 -0
- package/src/input/commands/planning-runtime.ts +205 -0
- package/src/input/commands/platform-access-runtime.ts +422 -0
- package/src/input/commands/platform-services-runtime.ts +246 -0
- package/src/input/commands/policy-dispatch.ts +339 -0
- package/src/input/commands/policy.ts +17 -0
- package/src/input/commands/product-runtime.ts +351 -0
- package/src/input/commands/profile-sync-runtime.ts +99 -0
- package/src/input/commands/provider-accounts-runtime.ts +113 -0
- package/src/input/commands/provider.ts +363 -0
- package/src/input/commands/qrcode-runtime.ts +20 -0
- package/src/input/commands/quit-shared.ts +162 -0
- package/src/input/commands/recall-bundle.ts +132 -0
- package/src/input/commands/recall-capture.ts +152 -0
- package/src/input/commands/recall-query.ts +229 -0
- package/src/input/commands/recall-review.ts +98 -0
- package/src/input/commands/recall-shared.ts +22 -0
- package/src/input/commands/remote-runtime-pool.ts +106 -0
- package/src/input/commands/remote-runtime-setup.ts +199 -0
- package/src/input/commands/remote-runtime.ts +431 -0
- package/src/input/commands/replay-runtime.ts +18 -0
- package/src/input/commands/runtime-services.ts +291 -0
- package/src/input/commands/schedule-runtime.ts +91 -0
- package/src/input/commands/services-runtime.ts +209 -0
- package/src/input/commands/session-content.ts +408 -0
- package/src/input/commands/session-workflow.ts +464 -0
- package/src/input/commands/session.ts +375 -0
- package/src/input/commands/settings-sync-runtime.ts +174 -0
- package/src/input/commands/share-runtime.ts +119 -0
- package/src/input/commands/shell-core.ts +307 -0
- package/src/input/commands/skills-runtime.ts +221 -0
- package/src/input/commands/subscription-runtime.ts +434 -0
- package/src/input/commands/tasks-runtime.ts +230 -0
- package/src/input/commands/teamwork-runtime.ts +339 -0
- package/src/input/commands/teleport-runtime.ts +57 -0
- package/src/input/commands/tts-runtime.ts +29 -0
- package/src/input/commands/work-plan-runtime.ts +169 -0
- package/src/input/commands.ts +131 -0
- package/src/input/feed-context-factory.ts +254 -0
- package/src/input/file-picker.ts +192 -0
- package/src/input/handler-command-route.ts +180 -0
- package/src/input/handler-content-actions.ts +497 -0
- package/src/input/handler-feed-routes.ts +648 -0
- package/src/input/handler-feed.ts +452 -0
- package/src/input/handler-interactions.ts +281 -0
- package/src/input/handler-modal-routes.ts +418 -0
- package/src/input/handler-modal-stack.ts +263 -0
- package/src/input/handler-modal-token-routes.ts +329 -0
- package/src/input/handler-onboarding-cloudflare.ts +391 -0
- package/src/input/handler-onboarding.ts +620 -0
- package/src/input/handler-picker-routes.ts +472 -0
- package/src/input/handler-prompt-buffer.ts +320 -0
- package/src/input/handler-shortcuts.ts +213 -0
- package/src/input/handler-ui-state.ts +372 -0
- package/src/input/handler.ts +729 -0
- package/src/input/input-history.ts +297 -0
- package/src/input/keybindings.ts +292 -0
- package/src/input/mcp-workspace.ts +554 -0
- package/src/input/model-picker-provider-filter.ts +28 -0
- package/src/input/model-picker-types.ts +137 -0
- package/src/input/model-picker.ts +797 -0
- package/src/input/onboarding/handler-onboarding-routes.ts +125 -0
- package/src/input/onboarding/onboarding-runtime-status.ts +87 -0
- package/src/input/onboarding/onboarding-wizard-apply.ts +277 -0
- package/src/input/onboarding/onboarding-wizard-cloudflare-step.ts +494 -0
- package/src/input/onboarding/onboarding-wizard-cloudflare.ts +204 -0
- package/src/input/onboarding/onboarding-wizard-constants.ts +158 -0
- package/src/input/onboarding/onboarding-wizard-external-surface-extra-specs.ts +130 -0
- package/src/input/onboarding/onboarding-wizard-external-surfaces.ts +762 -0
- package/src/input/onboarding/onboarding-wizard-helpers.ts +167 -0
- package/src/input/onboarding/onboarding-wizard-rules.ts +256 -0
- package/src/input/onboarding/onboarding-wizard-state.ts +365 -0
- package/src/input/onboarding/onboarding-wizard-steps.ts +798 -0
- package/src/input/onboarding/onboarding-wizard-types.ts +195 -0
- package/src/input/onboarding/onboarding-wizard.ts +711 -0
- package/src/input/panel-integration-actions.ts +78 -0
- package/src/input/profile-picker-modal.ts +222 -0
- package/src/input/search.ts +100 -0
- package/src/input/selection-modal.ts +163 -0
- package/src/input/selection.ts +135 -0
- package/src/input/session-picker-modal.ts +136 -0
- package/src/input/settings-modal-behavior.ts +37 -0
- package/src/input/settings-modal-secrets.ts +41 -0
- package/src/input/settings-modal-subscriptions.ts +95 -0
- package/src/input/settings-modal-types.ts +91 -0
- package/src/input/settings-modal.ts +793 -0
- package/src/input/submission-intent.ts +17 -0
- package/src/input/submission-router.ts +59 -0
- package/src/input/tts-settings-actions.ts +100 -0
- package/src/main.ts +792 -0
- package/src/mcp/runtime-reload.ts +81 -0
- package/src/panels/agent-inspector-panel.ts +521 -0
- package/src/panels/agent-inspector-shared.ts +94 -0
- package/src/panels/agent-logs-panel.ts +559 -0
- package/src/panels/agent-logs-shared.ts +129 -0
- package/src/panels/approval-panel.ts +150 -0
- package/src/panels/automation-control-panel.ts +212 -0
- package/src/panels/base-panel.ts +254 -0
- package/src/panels/builtin/agent.ts +117 -0
- package/src/panels/builtin/development.ts +31 -0
- package/src/panels/builtin/knowledge.ts +26 -0
- package/src/panels/builtin/operations.ts +349 -0
- package/src/panels/builtin/session.ts +129 -0
- package/src/panels/builtin/shared.ts +274 -0
- package/src/panels/builtin-panels.ts +23 -0
- package/src/panels/cockpit-panel.ts +183 -0
- package/src/panels/communication-panel.ts +153 -0
- package/src/panels/confirm-state.ts +61 -0
- package/src/panels/context-visualizer-panel.ts +204 -0
- package/src/panels/control-plane-panel.ts +211 -0
- package/src/panels/cost-tracker-panel.ts +444 -0
- package/src/panels/debug-panel.ts +432 -0
- package/src/panels/diff-panel.ts +520 -0
- package/src/panels/docs-panel.ts +283 -0
- package/src/panels/eval-panel.ts +399 -0
- package/src/panels/file-explorer-panel.ts +584 -0
- package/src/panels/file-preview-panel.ts +434 -0
- package/src/panels/forensics-panel.ts +364 -0
- package/src/panels/git-panel.ts +638 -0
- package/src/panels/hooks-panel.ts +239 -0
- package/src/panels/incident-review-panel.ts +197 -0
- package/src/panels/index.ts +46 -0
- package/src/panels/intelligence-panel.ts +176 -0
- package/src/panels/knowledge-panel.ts +345 -0
- package/src/panels/local-auth-panel.ts +130 -0
- package/src/panels/marketplace-panel.ts +212 -0
- package/src/panels/memory-panel.ts +225 -0
- package/src/panels/ops-control-panel.ts +150 -0
- package/src/panels/ops-strategy-panel.ts +235 -0
- package/src/panels/orchestration-panel.ts +273 -0
- package/src/panels/panel-list-panel.ts +509 -0
- package/src/panels/panel-manager.ts +570 -0
- package/src/panels/panel-picker.ts +106 -0
- package/src/panels/plan-dashboard-panel.ts +274 -0
- package/src/panels/plugins-panel.ts +178 -0
- package/src/panels/policy-panel.ts +308 -0
- package/src/panels/polish.ts +717 -0
- package/src/panels/project-planning-panel.ts +711 -0
- package/src/panels/provider-account-snapshot.ts +259 -0
- package/src/panels/provider-accounts-panel.ts +218 -0
- package/src/panels/provider-health-domains.ts +215 -0
- package/src/panels/provider-health-panel.ts +727 -0
- package/src/panels/provider-health-tracker.ts +115 -0
- package/src/panels/provider-stats-panel.ts +366 -0
- package/src/panels/qr-panel.ts +182 -0
- package/src/panels/remote-panel.ts +449 -0
- package/src/panels/routes-panel.ts +178 -0
- package/src/panels/sandbox-panel.ts +283 -0
- package/src/panels/schedule-panel.ts +329 -0
- package/src/panels/scrollable-list-panel.ts +491 -0
- package/src/panels/search-focus.ts +32 -0
- package/src/panels/security-panel.ts +295 -0
- package/src/panels/services-panel.ts +231 -0
- package/src/panels/session-browser-panel.ts +400 -0
- package/src/panels/session-maintenance.ts +125 -0
- package/src/panels/settings-sync-panel.ts +120 -0
- package/src/panels/skills-panel.ts +431 -0
- package/src/panels/subscription-panel.ts +263 -0
- package/src/panels/symbol-outline-panel.ts +486 -0
- package/src/panels/system-messages-panel.ts +230 -0
- package/src/panels/tasks-panel.ts +399 -0
- package/src/panels/thinking-panel.ts +304 -0
- package/src/panels/token-budget-panel.ts +475 -0
- package/src/panels/tool-inspector-panel.ts +429 -0
- package/src/panels/types.ts +54 -0
- package/src/panels/watchers-panel.ts +193 -0
- package/src/panels/work-plan-panel.ts +175 -0
- package/src/panels/worktree-panel.ts +182 -0
- package/src/panels/wrfc-panel.ts +609 -0
- package/src/permissions/prompt.ts +165 -0
- package/src/planning/project-planning-coordinator.ts +543 -0
- package/src/plugins/loader.ts +15 -0
- package/src/renderer/agent-detail-modal.ts +331 -0
- package/src/renderer/agent-workspace.ts +238 -0
- package/src/renderer/ansi-sanitize.ts +76 -0
- package/src/renderer/autocomplete-overlay.ts +154 -0
- package/src/renderer/block-actions.ts +76 -0
- package/src/renderer/bookmark-modal.ts +101 -0
- package/src/renderer/bottom-bar.ts +58 -0
- package/src/renderer/buffer.ts +113 -0
- package/src/renderer/code-block.ts +373 -0
- package/src/renderer/compositor.ts +283 -0
- package/src/renderer/context-inspector.ts +219 -0
- package/src/renderer/conversation-layout.ts +67 -0
- package/src/renderer/conversation-overlays.ts +140 -0
- package/src/renderer/conversation-surface.ts +260 -0
- package/src/renderer/diff-view.ts +132 -0
- package/src/renderer/diff.ts +130 -0
- package/src/renderer/file-picker-overlay.ts +101 -0
- package/src/renderer/file-tree.ts +153 -0
- package/src/renderer/fullscreen-primitives.ts +130 -0
- package/src/renderer/fullscreen-workspace.ts +199 -0
- package/src/renderer/git-status.ts +89 -0
- package/src/renderer/help-overlay.ts +267 -0
- package/src/renderer/history-search-overlay.ts +73 -0
- package/src/renderer/layout-engine.ts +97 -0
- package/src/renderer/layout.ts +32 -0
- package/src/renderer/live-tail-modal.ts +156 -0
- package/src/renderer/markdown.ts +635 -0
- package/src/renderer/mcp-workspace.ts +237 -0
- package/src/renderer/modal-factory.ts +467 -0
- package/src/renderer/modal-utils.ts +24 -0
- package/src/renderer/model-picker-overlay.ts +473 -0
- package/src/renderer/model-workspace.ts +488 -0
- package/src/renderer/onboarding/onboarding-wizard.ts +615 -0
- package/src/renderer/overlay-box.ts +146 -0
- package/src/renderer/overlay-viewport.ts +104 -0
- package/src/renderer/panel-composite.ts +158 -0
- package/src/renderer/panel-picker-overlay.ts +202 -0
- package/src/renderer/panel-tab-bar.ts +69 -0
- package/src/renderer/panel-workspace-bar.ts +42 -0
- package/src/renderer/process-indicator.ts +96 -0
- package/src/renderer/process-modal.ts +656 -0
- package/src/renderer/process-summary.ts +67 -0
- package/src/renderer/profile-picker-modal.ts +129 -0
- package/src/renderer/progress.ts +98 -0
- package/src/renderer/qr-renderer.ts +120 -0
- package/src/renderer/search-overlay.ts +54 -0
- package/src/renderer/selection-modal-overlay.ts +214 -0
- package/src/renderer/semantic-diff.ts +369 -0
- package/src/renderer/session-picker-modal.ts +127 -0
- package/src/renderer/settings-modal-helpers.ts +193 -0
- package/src/renderer/settings-modal.ts +537 -0
- package/src/renderer/shell-surface.ts +88 -0
- package/src/renderer/status-glyphs.ts +21 -0
- package/src/renderer/status-token.ts +67 -0
- package/src/renderer/surface-layout.ts +101 -0
- package/src/renderer/syntax-highlighter.ts +542 -0
- package/src/renderer/system-message.ts +83 -0
- package/src/renderer/tab-strip.ts +108 -0
- package/src/renderer/text-layout.ts +31 -0
- package/src/renderer/thinking.ts +17 -0
- package/src/renderer/tool-call.ts +234 -0
- package/src/renderer/ui-factory.ts +524 -0
- package/src/renderer/ui-primitives.ts +96 -0
- package/src/runtime/bootstrap-command-context.ts +278 -0
- package/src/runtime/bootstrap-command-parts.ts +386 -0
- package/src/runtime/bootstrap-core.ts +540 -0
- package/src/runtime/bootstrap-hook-bridge.ts +112 -0
- package/src/runtime/bootstrap-shell.ts +283 -0
- package/src/runtime/bootstrap.ts +575 -0
- package/src/runtime/cloudflare-control-plane.ts +349 -0
- package/src/runtime/context.ts +142 -0
- package/src/runtime/diagnostics/panels/index.ts +24 -0
- package/src/runtime/diagnostics/panels/ops.ts +156 -0
- package/src/runtime/diagnostics/panels/panel-resources.ts +118 -0
- package/src/runtime/diagnostics/panels/policy.ts +177 -0
- package/src/runtime/index.ts +662 -0
- package/src/runtime/onboarding/apply.ts +642 -0
- package/src/runtime/onboarding/derivation.ts +534 -0
- package/src/runtime/onboarding/index.ts +7 -0
- package/src/runtime/onboarding/markers.ts +148 -0
- package/src/runtime/onboarding/snapshot.ts +406 -0
- package/src/runtime/onboarding/state.ts +141 -0
- package/src/runtime/onboarding/types.ts +404 -0
- package/src/runtime/onboarding/verify.ts +171 -0
- package/src/runtime/operator-token-cleanup.ts +27 -0
- package/src/runtime/perf/panel-contracts.ts +32 -0
- package/src/runtime/perf/panel-health-monitor.ts +18 -0
- package/src/runtime/sandbox-public-gaps.ts +358 -0
- package/src/runtime/services.ts +670 -0
- package/src/runtime/store/domains/domain-read-matrix.ts +15 -0
- package/src/runtime/store/domains/index.ts +222 -0
- package/src/runtime/store/domains/panels.ts +117 -0
- package/src/runtime/store/domains/ui-perf.ts +103 -0
- package/src/runtime/store/index.ts +305 -0
- package/src/runtime/store/selectors/index.ts +359 -0
- package/src/runtime/store/state.ts +145 -0
- package/src/runtime/surface-feature-flags.ts +65 -0
- package/src/runtime/terminal-output-guard.ts +228 -0
- package/src/runtime/ui/index.ts +39 -0
- package/src/runtime/ui/model-picker/data-provider.ts +182 -0
- package/src/runtime/ui/model-picker/health-enrichment.ts +228 -0
- package/src/runtime/ui/model-picker/index.ts +59 -0
- package/src/runtime/ui/model-picker/types.ts +149 -0
- package/src/runtime/ui/provider-health/data-provider.ts +244 -0
- package/src/runtime/ui/provider-health/fallback-visualizer.ts +71 -0
- package/src/runtime/ui/provider-health/index.ts +46 -0
- package/src/runtime/ui/provider-health/types.ts +146 -0
- package/src/runtime/ui-events.ts +1 -0
- package/src/runtime/ui-read-model-helpers.ts +1 -0
- package/src/runtime/ui-read-models-observability-maintenance.ts +1 -0
- package/src/runtime/ui-read-models-observability-options.ts +1 -0
- package/src/runtime/ui-read-models-observability-remote.ts +1 -0
- package/src/runtime/ui-read-models-observability-security.ts +1 -0
- package/src/runtime/ui-read-models-observability-system.ts +1 -0
- package/src/runtime/ui-read-models-observability.ts +1 -0
- package/src/runtime/ui-read-models.ts +61 -0
- package/src/runtime/ui-service-queries.ts +1 -0
- package/src/runtime/ui-services.ts +190 -0
- package/src/scripts/process-messages.ts +42 -0
- package/src/shell/blocking-input.ts +98 -0
- package/src/shell/service-settings-sync.ts +273 -0
- package/src/shell/ui-openers.ts +352 -0
- package/src/tools/index.ts +1 -0
- package/src/tools/wrfc-agent-guard.ts +49 -0
- package/src/types/grid.ts +48 -0
- package/src/types/sql-js.d.ts +15 -0
- package/src/utils/clipboard.ts +22 -0
- package/src/utils/splash-lines.ts +46 -0
- package/src/utils/terminal-width.ts +185 -0
- package/src/verification/live-verifier.ts +430 -0
- package/src/verification/verification-ledger.ts +242 -0
- package/src/version.ts +17 -0
- package/src/widget/index.ts +2 -0
- package/src/widget/types.ts +9 -0
- package/src/widget/widget.ts +8 -0
- package/src/work-plans/work-plan-store.ts +374 -0
- package/tsconfig.json +18 -0
|
@@ -0,0 +1,729 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
import { InputTokenizer } from '@pellux/goodvibes-sdk/platform/core';
|
|
4
|
+
import { createOAuthLocalListener } from '@pellux/goodvibes-sdk/platform/config';
|
|
5
|
+
import { clearModalStackForHandler, cleanupMarkerRegistryForHandler, executeBlockActionForHandler, expandPromptForHandler, findMarkerAtPosForHandler, getImageAttachmentsForHandler, handleBlockCopyForHandler, handleBlockRerunForHandler, handleBlockSaveForHandler, handleBlockToggleForHandler, handleBookmarkForHandler, handleCopyForHandler, handleCtrlCForHandler, handleDiffApplyForHandler, handleEscapeForHandler, hydrateOnboardingWizardFromRuntimeForHandler, modalOpenedForHandler, openOnboardingWizardForHandler, registerPasteForHandler } from './handler-interactions.ts';
|
|
6
|
+
import { clearOnboardingModelPickerCancelStateForHandler, clearOnboardingPendingModelPickerTargetForHandler, completeOpenAiSubscriptionFromListenerForHandler, getOnboardingConfigValueForHandler, getOnboardingRuntimePostureForHandler, handleModelPickerCommitForHandler, handleOnboardingActionForHandler, handleOpenAiSubscriptionFinishForHandler, handleOpenAiSubscriptionStartForHandler, openModelPickerWithTargetForHandler, openProviderModelPickerWithTargetForHandler, refreshOnboardingHydrationForHandler, restartOnboardingExternalServicesIfNeededForHandler, restoreOnboardingModelPickerCancelStateForHandler, syncRuntimeFromOnboardingRequestForHandler, verifyOnboardingRuntimePostureForHandler, type OnboardingRuntimePosture } from './handler-onboarding.ts';
|
|
7
|
+
import { beginOpenAICodexLogin, exchangeOpenAICodexCode } from '@pellux/goodvibes-sdk/platform/config';
|
|
8
|
+
import { openExternalUrl } from '@pellux/goodvibes-sdk/platform/utils';
|
|
9
|
+
import { buildProviderAccountSnapshot } from '@/runtime/index.ts';
|
|
10
|
+
import { SelectionManager } from './selection.ts';
|
|
11
|
+
import type { InfiniteBuffer } from '../core/history.ts';
|
|
12
|
+
import type { CommandRegistry, CommandContext } from './command-registry.ts';
|
|
13
|
+
import { AutocompleteEngine } from './autocomplete.ts';
|
|
14
|
+
import { FilePickerModal } from './file-picker.ts';
|
|
15
|
+
import { ModelPickerModal } from './model-picker.ts';
|
|
16
|
+
import { SelectionModal } from './selection-modal.ts';
|
|
17
|
+
import type { SelectionResult, SelectionAction } from './selection-modal.ts';
|
|
18
|
+
import { SearchManager } from './search.ts';
|
|
19
|
+
import { InputHistory, HistorySearch } from './input-history.ts';
|
|
20
|
+
import type { BlockMeta, ConversationManager } from '../core/conversation';
|
|
21
|
+
import { ProcessModal } from '../renderer/process-modal.ts';
|
|
22
|
+
import { LiveTailModal } from '../renderer/live-tail-modal.ts';
|
|
23
|
+
import { BlockActionsMenu } from '../renderer/block-actions.ts';
|
|
24
|
+
import { AgentDetailModal } from '../renderer/agent-detail-modal.ts';
|
|
25
|
+
import { ContextInspectorModal } from '../renderer/context-inspector.ts';
|
|
26
|
+
import { BookmarkModal } from './bookmark-modal.ts';
|
|
27
|
+
import { SettingsModal } from './settings-modal.ts';
|
|
28
|
+
import { McpWorkspace } from './mcp-workspace.ts';
|
|
29
|
+
import { AgentWorkspace } from './agent-workspace.ts';
|
|
30
|
+
import { SessionPickerModal } from './session-picker-modal.ts';
|
|
31
|
+
import { GOODVIBES_AGENT_SURFACE_ROOT } from '../config/surface.ts';
|
|
32
|
+
import { ProfilePickerModal } from './profile-picker-modal.ts';
|
|
33
|
+
import { OnboardingWizardController, type OnboardingWizardAction, type OnboardingWizardMode } from './onboarding/onboarding-wizard.ts';
|
|
34
|
+
import {
|
|
35
|
+
applyOnboardingRequest,
|
|
36
|
+
collectOnboardingSnapshot,
|
|
37
|
+
getOnboardingCheckMarkerPath,
|
|
38
|
+
verifyOnboardingRequest,
|
|
39
|
+
} from '../runtime/onboarding/index.ts';
|
|
40
|
+
import type {
|
|
41
|
+
OnboardingApplyOperation,
|
|
42
|
+
OnboardingApplyRequest,
|
|
43
|
+
OnboardingShellPaths,
|
|
44
|
+
OnboardingVerificationItem,
|
|
45
|
+
} from '../runtime/onboarding/index.ts';
|
|
46
|
+
import {
|
|
47
|
+
IMAGE_EXTENSIONS,
|
|
48
|
+
cleanupMarkerRegistry,
|
|
49
|
+
expandPrompt,
|
|
50
|
+
findMarkerAtPos,
|
|
51
|
+
formatFileSize,
|
|
52
|
+
handleBlockCopy,
|
|
53
|
+
handleBlockRerun,
|
|
54
|
+
handleBlockSave,
|
|
55
|
+
handleBlockToggle,
|
|
56
|
+
handleBookmark,
|
|
57
|
+
handleClipboardPaste,
|
|
58
|
+
handleCopy,
|
|
59
|
+
handleCtrlC,
|
|
60
|
+
handleDiffApply,
|
|
61
|
+
mediaTypeFromExt,
|
|
62
|
+
registerPaste,
|
|
63
|
+
} from './handler-content-actions.ts';
|
|
64
|
+
import {
|
|
65
|
+
handleIndicatorFocusToken,
|
|
66
|
+
handleMouseToken,
|
|
67
|
+
handlePanelFocusToken,
|
|
68
|
+
handlePromptKeyToken,
|
|
69
|
+
handlePromptTextToken,
|
|
70
|
+
type PanelMouseLayout,
|
|
71
|
+
} from './handler-feed-routes.ts';
|
|
72
|
+
import {
|
|
73
|
+
ensureInputCursorVisible,
|
|
74
|
+
findPathToken,
|
|
75
|
+
getWrappedPromptInfo,
|
|
76
|
+
handlePathCompletion,
|
|
77
|
+
moveCursorVertical,
|
|
78
|
+
redoPromptState,
|
|
79
|
+
saveUndoState,
|
|
80
|
+
undoPromptState,
|
|
81
|
+
wordWrapLine,
|
|
82
|
+
type WrappedPromptInfo,
|
|
83
|
+
} from './handler-prompt-buffer.ts';
|
|
84
|
+
import { clearModalStack, handleEscape, modalOpened } from './handler-modal-stack.ts';
|
|
85
|
+
import { handleModalTokenRoutes } from './handler-modal-token-routes.ts';
|
|
86
|
+
import {
|
|
87
|
+
captureOnboardingWizardSnapshot,
|
|
88
|
+
handleHistorySearchToken,
|
|
89
|
+
handleOverlayToken,
|
|
90
|
+
openOnboardingWizardState,
|
|
91
|
+
restoreOnboardingWizardSnapshot,
|
|
92
|
+
handleSearchModeToken,
|
|
93
|
+
type OnboardingWizardSnapshot,
|
|
94
|
+
type OpenOnboardingWizardOptions,
|
|
95
|
+
} from './handler-ui-state.ts';
|
|
96
|
+
import {
|
|
97
|
+
handleBookmarkModalToken,
|
|
98
|
+
handleProfilePickerToken,
|
|
99
|
+
handleSelectionModalToken,
|
|
100
|
+
handleSessionPickerToken,
|
|
101
|
+
handleSettingsModalToken,
|
|
102
|
+
} from './handler-modal-routes.ts';
|
|
103
|
+
import { handleCommandModeToken } from './handler-command-route.ts';
|
|
104
|
+
import {
|
|
105
|
+
handleBlockActionsToken,
|
|
106
|
+
handleEscapeOnlyModalToken,
|
|
107
|
+
handleFilePickerToken,
|
|
108
|
+
handleLiveTailToken,
|
|
109
|
+
handleModelPickerToken,
|
|
110
|
+
handleProcessModalToken,
|
|
111
|
+
} from './handler-picker-routes.ts';
|
|
112
|
+
import { handleGlobalShortcutToken } from './handler-shortcuts.ts';
|
|
113
|
+
import { feedInputTokens } from './handler-feed.ts';
|
|
114
|
+
import { buildInitialFeedContext, syncFeedContextMutableFields } from './feed-context-factory.ts';
|
|
115
|
+
import { handlePanelIntegrationAction as runPanelIntegrationAction } from './panel-integration-actions.ts';
|
|
116
|
+
import type { Panel } from '../panels/types.ts';
|
|
117
|
+
import type { UiRuntimeServices } from '../runtime/ui-services.ts';
|
|
118
|
+
export { handlePanelIntegrationAction } from './panel-integration-actions.ts';
|
|
119
|
+
import type { ModelPickerTarget } from './model-picker.ts';
|
|
120
|
+
|
|
121
|
+
type SelectionModalCallback = (result: SelectionResult | null) => void;
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* InputHandler - Owns prompt text, paste registry, and keyboard/mouse handling.
|
|
126
|
+
* Extracted from main.ts and StateManager.
|
|
127
|
+
*/
|
|
128
|
+
export class InputHandler {
|
|
129
|
+
public prompt = '';
|
|
130
|
+
public cursorPos = 0;
|
|
131
|
+
public showExitNotice = false;
|
|
132
|
+
/** Max visible rows for the input area. Content beyond this scrolls internally. */
|
|
133
|
+
public static readonly MAX_INPUT_ROWS = 8;
|
|
134
|
+
/** Internal scroll offset for the input area when content exceeds MAX_INPUT_ROWS. */
|
|
135
|
+
public inputScrollTop = 0;
|
|
136
|
+
public lastCopyTime = 0;
|
|
137
|
+
/** True when the user has entered slash-command mode (prompt starts with '/'). */
|
|
138
|
+
public commandMode = false;
|
|
139
|
+
/** True when the process indicator bar has keyboard focus. */
|
|
140
|
+
public indicatorFocused = false;
|
|
141
|
+
/** True when keyboard focus is on the active panel (arrow/enter go to panel, not prompt). */
|
|
142
|
+
public panelFocused = false;
|
|
143
|
+
|
|
144
|
+
public tokenizer = new InputTokenizer();
|
|
145
|
+
public pasteRegistry = new Map<string, string>();
|
|
146
|
+
public nextPasteId = 1;
|
|
147
|
+
public lastCtrlCTime = 0;
|
|
148
|
+
/** Long-lived feed context — reused across every feed() call to avoid per-keystroke allocation. */
|
|
149
|
+
public feedContext!: import('./handler-feed.ts').InputFeedContext;
|
|
150
|
+
public commandRegistry: CommandRegistry | null = null;
|
|
151
|
+
public commandContext: CommandContext | undefined = undefined;
|
|
152
|
+
public autocomplete: AutocompleteEngine | null = null;
|
|
153
|
+
public modelPicker: ModelPickerModal;
|
|
154
|
+
public selectionModal = new SelectionModal();
|
|
155
|
+
public searchManager = new SearchManager();
|
|
156
|
+
public processModal: ProcessModal;
|
|
157
|
+
public liveTailModal: LiveTailModal;
|
|
158
|
+
public agentDetailModal: AgentDetailModal;
|
|
159
|
+
public contextInspectorModal = new ContextInspectorModal();
|
|
160
|
+
public bookmarkModal: BookmarkModal;
|
|
161
|
+
public blockActionsMenu = new BlockActionsMenu();
|
|
162
|
+
public settingsModal = new SettingsModal();
|
|
163
|
+
public mcpWorkspace = new McpWorkspace();
|
|
164
|
+
public agentWorkspace = new AgentWorkspace();
|
|
165
|
+
public onboardingWizard = new OnboardingWizardController();
|
|
166
|
+
public onboardingModelPickerCancelSnapshot: OnboardingWizardSnapshot | null = null;
|
|
167
|
+
public onboardingHydrationSerial = 0;
|
|
168
|
+
public onboardingApplyPending = false;
|
|
169
|
+
public onboardingOpenAiListenerSerial = 0;
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Modal navigation stack. Each element is the name of an open modal.
|
|
173
|
+
* Used to support back-navigation via Escape.
|
|
174
|
+
*/
|
|
175
|
+
public modalStack: string[] = [];
|
|
176
|
+
public modalReturnFocus: 'prompt' | 'panel' | 'indicator' = 'prompt';
|
|
177
|
+
public sessionPickerModal: SessionPickerModal;
|
|
178
|
+
public profilePickerModal: ProfilePickerModal;
|
|
179
|
+
/** True when the help overlay is visible. */
|
|
180
|
+
public helpOverlayActive = false;
|
|
181
|
+
public helpScrollOffset = 0;
|
|
182
|
+
public shortcutsOverlayActive = false;
|
|
183
|
+
public shortcutsScrollOffset = 0;
|
|
184
|
+
public inputHistory: InputHistory | null = null;
|
|
185
|
+
public filePicker: FilePickerModal;
|
|
186
|
+
public historySearch: HistorySearch = new HistorySearch(() => this.inputHistory?.getEntries() ?? []);
|
|
187
|
+
public conversationManager: ConversationManager | null = null;
|
|
188
|
+
public selectionCallback: SelectionModalCallback | null = null;
|
|
189
|
+
public syncFeedSelectionCallback: ((callback: SelectionModalCallback | null) => void) | null = null;
|
|
190
|
+
/** Time of last [COPIED] block feedback, for brief display. */
|
|
191
|
+
public lastBlockCopyTime = 0;
|
|
192
|
+
public mouseDownRow = -1;
|
|
193
|
+
public mouseDownCol = -1;
|
|
194
|
+
|
|
195
|
+
/** Pasted images: maps marker IDs to base64 image data. */
|
|
196
|
+
public imageRegistry = new Map<string, { data: string; mediaType: string }>();
|
|
197
|
+
public nextImageId = 1;
|
|
198
|
+
|
|
199
|
+
// ── Undo / Redo ────────────────────────────────────────────────────────────
|
|
200
|
+
public undoStack: Array<{ prompt: string; cursorPos: number }> = [];
|
|
201
|
+
public redoStack: Array<{ prompt: string; cursorPos: number }> = [];
|
|
202
|
+
public static readonly MAX_UNDO = 50;
|
|
203
|
+
|
|
204
|
+
// ── Path completion (Tab on path-like token) ───────────────────────────────
|
|
205
|
+
/** Current list of path completions cycling on repeated Tab presses. */
|
|
206
|
+
public pathCompletions: string[] = [];
|
|
207
|
+
/** Index into pathCompletions for Tab cycling. */
|
|
208
|
+
public pathCompletionIndex = -1;
|
|
209
|
+
/** The raw prefix that triggered path completion (e.g. 'src/in'). */
|
|
210
|
+
public pathCompletionPrefix = '';
|
|
211
|
+
/** Start offset in prompt where the path token begins. */
|
|
212
|
+
public pathCompletionStart = 0;
|
|
213
|
+
|
|
214
|
+
constructor(
|
|
215
|
+
public requestRender: () => void,
|
|
216
|
+
public selection: SelectionManager,
|
|
217
|
+
public getScrollTop: () => number,
|
|
218
|
+
public getViewportHeight: () => number,
|
|
219
|
+
public getHistory: () => InfiniteBuffer,
|
|
220
|
+
public scroll: (delta: number) => void,
|
|
221
|
+
public exitApp: () => void,
|
|
222
|
+
public readonly uiServices: Pick<UiRuntimeServices,
|
|
223
|
+
'agents'
|
|
224
|
+
| 'environment'
|
|
225
|
+
| 'platform'
|
|
226
|
+
| 'providers'
|
|
227
|
+
| 'sessions'
|
|
228
|
+
| 'shell'
|
|
229
|
+
>,
|
|
230
|
+
) {
|
|
231
|
+
this.filePicker = new FilePickerModal(uiServices.environment.shellPaths);
|
|
232
|
+
this.modelPicker = new ModelPickerModal(
|
|
233
|
+
uiServices.providers.favoritesStore,
|
|
234
|
+
uiServices.providers.benchmarkStore,
|
|
235
|
+
uiServices.providers.providerRegistry,
|
|
236
|
+
);
|
|
237
|
+
this.processModal = new ProcessModal({
|
|
238
|
+
agentManager: uiServices.agents.agentManager,
|
|
239
|
+
processManager: uiServices.shell.processManager,
|
|
240
|
+
wrfcController: uiServices.agents.wrfcController,
|
|
241
|
+
});
|
|
242
|
+
this.liveTailModal = new LiveTailModal({
|
|
243
|
+
agentManager: uiServices.agents.agentManager,
|
|
244
|
+
processManager: uiServices.shell.processManager,
|
|
245
|
+
});
|
|
246
|
+
this.agentDetailModal = new AgentDetailModal({
|
|
247
|
+
agentManager: uiServices.agents.agentManager,
|
|
248
|
+
agentMessageBus: uiServices.agents.agentMessageBus,
|
|
249
|
+
sessionLogPathResolver: (agentId) => uiServices.environment.shellPaths.resolveProjectPath(GOODVIBES_AGENT_SURFACE_ROOT, 'sessions', `${agentId}.jsonl`),
|
|
250
|
+
// SDK 0.23.0: supply wrfcController so the modal can show constraint data
|
|
251
|
+
wrfcController: uiServices.agents.wrfcController,
|
|
252
|
+
});
|
|
253
|
+
this.bookmarkModal = new BookmarkModal(uiServices.shell.bookmarkManager);
|
|
254
|
+
this.sessionPickerModal = new SessionPickerModal(uiServices.sessions.sessionManager);
|
|
255
|
+
this.profilePickerModal = new ProfilePickerModal(uiServices.shell.profileManager);
|
|
256
|
+
this.initFeedContext();
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* initFeedContext — Build the long-lived InputFeedContext once via factory.
|
|
261
|
+
* See feed-context-factory.ts for full field documentation.
|
|
262
|
+
*/
|
|
263
|
+
public initFeedContext(): void {
|
|
264
|
+
this.feedContext = buildInitialFeedContext(
|
|
265
|
+
{
|
|
266
|
+
prompt: this.prompt, cursorPos: this.cursorPos, inputScrollTop: this.inputScrollTop, commandMode: this.commandMode,
|
|
267
|
+
panelFocused: this.panelFocused, indicatorFocused: this.indicatorFocused,
|
|
268
|
+
helpOverlayActive: this.helpOverlayActive, helpScrollOffset: this.helpScrollOffset,
|
|
269
|
+
shortcutsOverlayActive: this.shortcutsOverlayActive, shortcutsScrollOffset: this.shortcutsScrollOffset,
|
|
270
|
+
nextPasteId: this.nextPasteId, nextImageId: this.nextImageId,
|
|
271
|
+
mouseDownRow: this.mouseDownRow, mouseDownCol: this.mouseDownCol,
|
|
272
|
+
contentWidth: this.contentWidth, panelMouseLayout: this.panelMouseLayout,
|
|
273
|
+
selectionCallback: this.selectionCallback,
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
selection: this.selection,
|
|
277
|
+
pasteRegistry: this.pasteRegistry,
|
|
278
|
+
imageRegistry: this.imageRegistry,
|
|
279
|
+
projectRoot: this.uiServices.environment.shellPaths.workingDirectory,
|
|
280
|
+
selectionModal: this.selectionModal,
|
|
281
|
+
bookmarkModal: this.bookmarkModal,
|
|
282
|
+
settingsModal: this.settingsModal,
|
|
283
|
+
mcpWorkspace: this.mcpWorkspace,
|
|
284
|
+
agentWorkspace: this.agentWorkspace,
|
|
285
|
+
sessionPickerModal: this.sessionPickerModal,
|
|
286
|
+
profilePickerModal: this.profilePickerModal,
|
|
287
|
+
historySearch: this.historySearch,
|
|
288
|
+
commandRegistry: this.commandRegistry,
|
|
289
|
+
commandContext: this.commandContext,
|
|
290
|
+
autocomplete: this.autocomplete,
|
|
291
|
+
filePicker: this.filePicker,
|
|
292
|
+
modelPicker: this.modelPicker,
|
|
293
|
+
onboardingWizard: this.onboardingWizard,
|
|
294
|
+
processModal: this.processModal,
|
|
295
|
+
liveTailModal: this.liveTailModal,
|
|
296
|
+
agentDetailModal: this.agentDetailModal,
|
|
297
|
+
contextInspectorModal: this.contextInspectorModal,
|
|
298
|
+
blockActionsMenu: this.blockActionsMenu,
|
|
299
|
+
searchManager: this.searchManager,
|
|
300
|
+
modalStack: this.modalStack,
|
|
301
|
+
inputHistory: this.inputHistory,
|
|
302
|
+
conversationManager: this.conversationManager,
|
|
303
|
+
panelManager: this.uiServices.shell.panelManager,
|
|
304
|
+
keybindingsManager: this.uiServices.shell.keybindingsManager,
|
|
305
|
+
getHistory: this.getHistory,
|
|
306
|
+
getViewportHeight: this.getViewportHeight,
|
|
307
|
+
getScrollTop: this.getScrollTop,
|
|
308
|
+
scroll: this.scroll,
|
|
309
|
+
exitApp: this.exitApp,
|
|
310
|
+
},
|
|
311
|
+
{
|
|
312
|
+
modalOpened: (name: string) => this.modalOpened(name),
|
|
313
|
+
handleEscape: () => { this.handleEscape(); this.syncFeedContextMutableFields(); },
|
|
314
|
+
handleCopy: () => this.handleCopy(),
|
|
315
|
+
handleCtrlC: () => { this.handleCtrlC(); this.syncFeedContextMutableFields(); },
|
|
316
|
+
handleBlockCopy: () => this.handleBlockCopy(),
|
|
317
|
+
handleBookmark: () => this.handleBookmark(),
|
|
318
|
+
handleBlockSave: () => this.handleBlockSave(),
|
|
319
|
+
handleDiffApply: () => this.handleDiffApply(),
|
|
320
|
+
handleUndo: () => { this.handleUndo(); this.syncFeedContextMutableFields(); },
|
|
321
|
+
handleRedo: () => { this.handleRedo(); this.syncFeedContextMutableFields(); },
|
|
322
|
+
handlePaste: () => { this.handlePaste(); this.syncFeedContextMutableFields(); },
|
|
323
|
+
saveUndoState: () => this.saveUndoState(),
|
|
324
|
+
ensureInputCursorVisible: (contentWidth?: number) => this.ensureInputCursorVisible(contentWidth),
|
|
325
|
+
registerPaste: (content: string) => this.registerPaste(content),
|
|
326
|
+
executeBlockAction: (id: string) => this.executeBlockAction(id),
|
|
327
|
+
cyclePanelTab: (direction: 'next' | 'prev') => this.cyclePanelTab(direction),
|
|
328
|
+
onPanelInputConsumed: (activePanel: Panel | null, key: string) => this.handlePanelIntegrationAction(activePanel, key),
|
|
329
|
+
getWrappedPromptInfo: (contentWidth: number) => this.getWrappedPromptInfo(contentWidth),
|
|
330
|
+
moveCursorVertical: (direction: -1 | 1) => this.moveCursorVertical(direction),
|
|
331
|
+
handlePathCompletion: () => this.handlePathCompletion(),
|
|
332
|
+
handleBlockToggle: () => this.handleBlockToggle(),
|
|
333
|
+
findMarkerAtPos: (pos: number) => this.findMarkerAtPos(pos),
|
|
334
|
+
cleanupMarkerRegistry: (text: string) => this.cleanupMarkerRegistry(text),
|
|
335
|
+
expandPrompt: (text: string) => this.expandPrompt(text),
|
|
336
|
+
openModelPickerWithTarget: (target: ModelPickerTarget, source?: 'settings' | 'onboarding') =>
|
|
337
|
+
this.openModelPickerWithTarget(target, source),
|
|
338
|
+
openProviderModelPickerWithTarget: (target: ModelPickerTarget, source?: 'settings' | 'onboarding') =>
|
|
339
|
+
this.openProviderModelPickerWithTarget(target, source),
|
|
340
|
+
onModelPickerCommit: () => this.handleModelPickerCommit(),
|
|
341
|
+
onOnboardingAction: (action: OnboardingWizardAction) => { void this.handleOnboardingAction(action); },
|
|
342
|
+
},
|
|
343
|
+
);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
/** Sync mutable handler fields back into feedContext after in-feed mutations. */
|
|
347
|
+
public syncFeedContextMutableFields(): void {
|
|
348
|
+
const h = this;
|
|
349
|
+
syncFeedContextMutableFields({ prompt: h.prompt, cursorPos: h.cursorPos, inputScrollTop: h.inputScrollTop, commandMode: h.commandMode,
|
|
350
|
+
panelFocused: h.panelFocused, indicatorFocused: h.indicatorFocused, helpOverlayActive: h.helpOverlayActive,
|
|
351
|
+
helpScrollOffset: h.helpScrollOffset, shortcutsOverlayActive: h.shortcutsOverlayActive,
|
|
352
|
+
shortcutsScrollOffset: h.shortcutsScrollOffset, selectionCallback: h.selectionCallback,
|
|
353
|
+
nextPasteId: h.nextPasteId, nextImageId: h.nextImageId, mouseDownRow: h.mouseDownRow,
|
|
354
|
+
mouseDownCol: h.mouseDownCol, contentWidth: h.contentWidth,
|
|
355
|
+
panelMouseLayout: h.panelMouseLayout }, this.feedContext);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/** Wire in the InputHistory instance. Optional; disables history navigation if unset. */
|
|
359
|
+
public setHistory(history: InputHistory): void { this.inputHistory = history; }
|
|
360
|
+
|
|
361
|
+
/** Wire in the slash command registry and context. Must be called before commands work. */
|
|
362
|
+
public setCommandRegistry(registry: CommandRegistry, context: CommandContext): void {
|
|
363
|
+
this.commandRegistry = registry;
|
|
364
|
+
this.commandContext = context;
|
|
365
|
+
this.autocomplete = new AutocompleteEngine(registry);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
/** Wire in the conversation manager for block copy/apply/collapse. */
|
|
369
|
+
public setConversationManager(cm: ConversationManager): void { this.conversationManager = cm; }
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* openSelection - Open the generic selection modal with a callback.
|
|
373
|
+
* The callback receives SelectionResult on selection, or null on cancel/escape.
|
|
374
|
+
*/
|
|
375
|
+
public openSelection(
|
|
376
|
+
title: string,
|
|
377
|
+
items: import('./selection-modal.ts').SelectionItem[],
|
|
378
|
+
opts: {
|
|
379
|
+
preSelectId?: string;
|
|
380
|
+
allowSearch?: boolean;
|
|
381
|
+
customActions?: Map<string, SelectionAction>;
|
|
382
|
+
} | undefined,
|
|
383
|
+
callback: SelectionModalCallback,
|
|
384
|
+
): void {
|
|
385
|
+
this.modalOpened('selection');
|
|
386
|
+
this.selectionModal.open(title, items, opts);
|
|
387
|
+
this.selectionCallback = callback;
|
|
388
|
+
this.syncFeedSelectionCallback?.(callback);
|
|
389
|
+
this.requestRender();
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
public openOnboardingWizard(
|
|
394
|
+
modeOrOptions: OnboardingWizardMode | OpenOnboardingWizardOptions = 'new',
|
|
395
|
+
): void { openOnboardingWizardForHandler(this, modeOrOptions); }
|
|
396
|
+
|
|
397
|
+
public async hydrateOnboardingWizardFromRuntime(hydrationSerial: number): Promise<void> { await hydrateOnboardingWizardFromRuntimeForHandler(this, hydrationSerial); }
|
|
398
|
+
public registerPaste(content: string): string { return registerPasteForHandler(this, content); }
|
|
399
|
+
public expandPrompt(text: string) { return expandPromptForHandler(this, text); }
|
|
400
|
+
public getImageAttachments(): Map<string, { data: string; mediaType: string }> { return getImageAttachmentsForHandler(this); }
|
|
401
|
+
public cleanupMarkerRegistry(markerText: string): void { cleanupMarkerRegistryForHandler(this, markerText); }
|
|
402
|
+
public findMarkerAtPos(pos: number): { start: number; end: number } | null { return findMarkerAtPosForHandler(this, pos); }
|
|
403
|
+
public handleCopy(): void { handleCopyForHandler(this); }
|
|
404
|
+
public handleBlockCopy(): void { handleBlockCopyForHandler(this); }
|
|
405
|
+
public handleBookmark(): void { handleBookmarkForHandler(this); }
|
|
406
|
+
public handleBlockSave(): void { handleBlockSaveForHandler(this); }
|
|
407
|
+
public executeBlockAction(actionId: string): void { executeBlockActionForHandler(this, actionId); }
|
|
408
|
+
public handleBlockRerun(): void { handleBlockRerunForHandler(this); }
|
|
409
|
+
public handleBlockToggle(): void { handleBlockToggleForHandler(this); }
|
|
410
|
+
public handleDiffApply(): boolean { return handleDiffApplyForHandler(this); }
|
|
411
|
+
public handleCtrlC(): void { handleCtrlCForHandler(this); }
|
|
412
|
+
public modalOpened(name: string): void { modalOpenedForHandler(this, name); }
|
|
413
|
+
public clearModalStack(): void { clearModalStackForHandler(this); }
|
|
414
|
+
public handleEscape(): void { handleEscapeForHandler(this); }
|
|
415
|
+
|
|
416
|
+
public clearOnboardingPendingModelPickerTarget(): void { clearOnboardingPendingModelPickerTargetForHandler(this); }
|
|
417
|
+
public clearOnboardingModelPickerCancelState(): void { clearOnboardingModelPickerCancelStateForHandler(this); }
|
|
418
|
+
public restoreOnboardingModelPickerCancelState(): void { restoreOnboardingModelPickerCancelStateForHandler(this); }
|
|
419
|
+
public openModelPickerWithTarget(target: ModelPickerTarget, source: 'settings' | 'onboarding' = 'settings'): boolean { return openModelPickerWithTargetForHandler(this, target, source); }
|
|
420
|
+
public openProviderModelPickerWithTarget(target: ModelPickerTarget, source: 'settings' | 'onboarding' = 'settings'): boolean { return openProviderModelPickerWithTargetForHandler(this, target, source); }
|
|
421
|
+
public openMcpWorkspace(context: CommandContext): void {
|
|
422
|
+
this.panelFocused = false;
|
|
423
|
+
this.indicatorFocused = false;
|
|
424
|
+
this.modalOpened('mcpWorkspace');
|
|
425
|
+
this.mcpWorkspace.open(context);
|
|
426
|
+
this.requestRender();
|
|
427
|
+
}
|
|
428
|
+
public openAgentWorkspace(context: CommandContext): void {
|
|
429
|
+
this.panelFocused = false;
|
|
430
|
+
this.indicatorFocused = false;
|
|
431
|
+
this.modalOpened('agentWorkspace');
|
|
432
|
+
this.agentWorkspace.open(context, (command) => this.dispatchAgentWorkspaceCommand(command, context));
|
|
433
|
+
this.requestRender();
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
private dispatchAgentWorkspaceCommand(command: string, context: CommandContext): void {
|
|
437
|
+
this.agentWorkspace.close();
|
|
438
|
+
for (let index = this.modalStack.length - 1; index >= 0; index -= 1) {
|
|
439
|
+
if (this.modalStack[index] === 'agentWorkspace') this.modalStack.splice(index, 1);
|
|
440
|
+
}
|
|
441
|
+
const [name, ...args] = command.trim().replace(/^\//, '').split(/\s+/);
|
|
442
|
+
if (!name) return;
|
|
443
|
+
void context.executeCommand?.(name, args).catch((error: unknown) => {
|
|
444
|
+
context.print(`Agent workspace command failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
445
|
+
this.requestRender();
|
|
446
|
+
});
|
|
447
|
+
this.requestRender();
|
|
448
|
+
}
|
|
449
|
+
public handleModelPickerCommit(): boolean { return handleModelPickerCommitForHandler(this); }
|
|
450
|
+
public async handleOnboardingAction(action: OnboardingWizardAction): Promise<void> { await handleOnboardingActionForHandler(this, action); }
|
|
451
|
+
public async refreshOnboardingHydration(options: { readonly preserveValues?: boolean; readonly targetStepId?: string } = {}): Promise<void> { await refreshOnboardingHydrationForHandler(this, options); }
|
|
452
|
+
public async handleOpenAiSubscriptionStart(): Promise<void> { await handleOpenAiSubscriptionStartForHandler(this); }
|
|
453
|
+
public async completeOpenAiSubscriptionFromListener(listener: Awaited<ReturnType<typeof createOAuthLocalListener>>, verifier: string, serial: number): Promise<void> { await completeOpenAiSubscriptionFromListenerForHandler(this, listener, verifier, serial); }
|
|
454
|
+
public async handleOpenAiSubscriptionFinish(): Promise<void> { await handleOpenAiSubscriptionFinishForHandler(this); }
|
|
455
|
+
public syncRuntimeFromOnboardingRequest(request: ReturnType<OnboardingWizardController['buildApplyRequest']>): void { syncRuntimeFromOnboardingRequestForHandler(this, request); }
|
|
456
|
+
public getOnboardingConfigValue(request: OnboardingApplyRequest, key: string): unknown { return getOnboardingConfigValueForHandler(this, request, key); }
|
|
457
|
+
public getOnboardingRuntimePosture(request: OnboardingApplyRequest): OnboardingRuntimePosture { return getOnboardingRuntimePostureForHandler(this, request); }
|
|
458
|
+
public async restartOnboardingExternalServicesIfNeeded(request: OnboardingApplyRequest): Promise<OnboardingVerificationItem[]> { return await restartOnboardingExternalServicesIfNeededForHandler(this, request); }
|
|
459
|
+
public verifyOnboardingRuntimePosture(request: OnboardingApplyRequest): OnboardingVerificationItem[] { return verifyOnboardingRuntimePostureForHandler(this, request); }
|
|
460
|
+
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* feed - Process raw stdin data through the tokenizer.
|
|
464
|
+
* Reuses the long-lived this.feedContext to avoid per-keystroke object allocation.
|
|
465
|
+
*/
|
|
466
|
+
public feed(data: string): void {
|
|
467
|
+
const immediateRequestRender = this.requestRender;
|
|
468
|
+
let renderRequested = false;
|
|
469
|
+
let isFeeding = true;
|
|
470
|
+
const bufferedRequestRender = (): void => {
|
|
471
|
+
if (isFeeding) {
|
|
472
|
+
renderRequested = true;
|
|
473
|
+
return;
|
|
474
|
+
}
|
|
475
|
+
immediateRequestRender();
|
|
476
|
+
};
|
|
477
|
+
|
|
478
|
+
this.requestRender = bufferedRequestRender;
|
|
479
|
+
try {
|
|
480
|
+
const context = this.feedContext;
|
|
481
|
+
// Sync mutable scalars from handler into the reused context.
|
|
482
|
+
context.prompt = this.prompt;
|
|
483
|
+
context.cursorPos = this.cursorPos;
|
|
484
|
+
context.inputScrollTop = this.inputScrollTop;
|
|
485
|
+
context.commandMode = this.commandMode;
|
|
486
|
+
context.panelFocused = this.panelFocused;
|
|
487
|
+
context.indicatorFocused = this.indicatorFocused;
|
|
488
|
+
context.helpOverlayActive = this.helpOverlayActive;
|
|
489
|
+
context.helpScrollOffset = this.helpScrollOffset;
|
|
490
|
+
context.shortcutsOverlayActive = this.shortcutsOverlayActive;
|
|
491
|
+
context.shortcutsScrollOffset = this.shortcutsScrollOffset;
|
|
492
|
+
context.selectionCallback = this.selectionCallback;
|
|
493
|
+
context.nextPasteId = this.nextPasteId;
|
|
494
|
+
context.nextImageId = this.nextImageId;
|
|
495
|
+
context.mouseDownRow = this.mouseDownRow;
|
|
496
|
+
context.mouseDownCol = this.mouseDownCol;
|
|
497
|
+
context.contentWidth = this.contentWidth;
|
|
498
|
+
context.panelMouseLayout = this.panelMouseLayout;
|
|
499
|
+
// Sync semi-stable refs that may be wired after construction.
|
|
500
|
+
context.commandRegistry = this.commandRegistry;
|
|
501
|
+
context.commandContext = this.commandContext;
|
|
502
|
+
context.autocomplete = this.autocomplete;
|
|
503
|
+
context.inputHistory = this.inputHistory;
|
|
504
|
+
context.conversationManager = this.conversationManager;
|
|
505
|
+
// Swap requestRender to buffered version for this feed.
|
|
506
|
+
context.requestRender = bufferedRequestRender;
|
|
507
|
+
this.syncFeedSelectionCallback = (callback) => {
|
|
508
|
+
context.selectionCallback = callback;
|
|
509
|
+
};
|
|
510
|
+
feedInputTokens(context, this.tokenizer.feed(data));
|
|
511
|
+
this.prompt = context.prompt;
|
|
512
|
+
this.cursorPos = context.cursorPos;
|
|
513
|
+
this.inputScrollTop = context.inputScrollTop;
|
|
514
|
+
this.commandMode = context.commandMode;
|
|
515
|
+
this.panelFocused = context.panelFocused;
|
|
516
|
+
this.indicatorFocused = context.indicatorFocused;
|
|
517
|
+
this.helpOverlayActive = context.helpOverlayActive;
|
|
518
|
+
this.helpScrollOffset = context.helpScrollOffset;
|
|
519
|
+
this.shortcutsOverlayActive = context.shortcutsOverlayActive;
|
|
520
|
+
this.shortcutsScrollOffset = context.shortcutsScrollOffset;
|
|
521
|
+
this.selectionCallback = context.selectionCallback;
|
|
522
|
+
this.nextPasteId = context.nextPasteId;
|
|
523
|
+
this.nextImageId = context.nextImageId;
|
|
524
|
+
this.mouseDownRow = context.mouseDownRow;
|
|
525
|
+
this.mouseDownCol = context.mouseDownCol;
|
|
526
|
+
} finally {
|
|
527
|
+
this.syncFeedSelectionCallback = null;
|
|
528
|
+
isFeeding = false;
|
|
529
|
+
this.requestRender = immediateRequestRender;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
if (renderRequested) {
|
|
533
|
+
immediateRequestRender();
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* handlePaste - Shared paste logic for Ctrl+V and middle-click.
|
|
539
|
+
* Tries image clipboard first, falls back to text paste.
|
|
540
|
+
*/
|
|
541
|
+
public handlePaste(): ReturnType<typeof handleClipboardPaste> {
|
|
542
|
+
const result = handleClipboardPaste({
|
|
543
|
+
prompt: this.prompt,
|
|
544
|
+
cursorPos: this.cursorPos,
|
|
545
|
+
pasteRegistry: this.pasteRegistry,
|
|
546
|
+
nextPasteId: this.nextPasteId,
|
|
547
|
+
imageRegistry: this.imageRegistry,
|
|
548
|
+
nextImageId: this.nextImageId,
|
|
549
|
+
saveUndoState: () => this.saveUndoState(),
|
|
550
|
+
ensureInputCursorVisible: () => this.ensureInputCursorVisible(),
|
|
551
|
+
requestRender: this.requestRender,
|
|
552
|
+
}, this.uiServices.environment.shellPaths.workingDirectory);
|
|
553
|
+
this.prompt = result.prompt;
|
|
554
|
+
this.cursorPos = result.cursorPos;
|
|
555
|
+
this.nextImageId = result.nextImageId;
|
|
556
|
+
this.nextPasteId = result.nextPasteId;
|
|
557
|
+
if (!result.pasted) {
|
|
558
|
+
this.conversationManager?.log('[Paste: clipboard does not contain supported text or image data]', { fg: '240' });
|
|
559
|
+
this.requestRender();
|
|
560
|
+
}
|
|
561
|
+
return result;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/** Content width for wrapping — set by main.ts via setContentWidth(). */
|
|
565
|
+
public contentWidth = 76;
|
|
566
|
+
public panelMouseLayout: PanelMouseLayout | null = null;
|
|
567
|
+
|
|
568
|
+
/** Set the content width used for wrapping calculations. Call from main.ts. */
|
|
569
|
+
public setContentWidth(w: number): void {
|
|
570
|
+
this.contentWidth = w;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
public setPanelMouseLayout(layout: PanelMouseLayout | null): void {
|
|
574
|
+
this.panelMouseLayout = layout;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
/**
|
|
578
|
+
* Move cursor up or down by one WRAPPED line.
|
|
579
|
+
* Uses the segment table to navigate visual lines, not raw \n lines.
|
|
580
|
+
* Returns true if the cursor moved, false if at boundary.
|
|
581
|
+
*/
|
|
582
|
+
public moveCursorVertical(direction: -1 | 1): boolean {
|
|
583
|
+
const result = moveCursorVertical(
|
|
584
|
+
this.prompt,
|
|
585
|
+
this.cursorPos,
|
|
586
|
+
this.inputScrollTop,
|
|
587
|
+
this.contentWidth,
|
|
588
|
+
InputHandler.MAX_INPUT_ROWS,
|
|
589
|
+
direction,
|
|
590
|
+
);
|
|
591
|
+
this.cursorPos = result.cursorPos;
|
|
592
|
+
this.inputScrollTop = result.inputScrollTop;
|
|
593
|
+
return result.moved;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Ensure the cursor's wrapped line is visible within the input scroll window.
|
|
598
|
+
*/
|
|
599
|
+
public ensureInputCursorVisible(contentWidth?: number): void {
|
|
600
|
+
this.inputScrollTop = ensureInputCursorVisible(
|
|
601
|
+
this.prompt,
|
|
602
|
+
this.cursorPos,
|
|
603
|
+
this.inputScrollTop,
|
|
604
|
+
contentWidth ?? this.contentWidth,
|
|
605
|
+
InputHandler.MAX_INPUT_ROWS,
|
|
606
|
+
);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/**
|
|
610
|
+
* Get the number of visible prompt lines (capped at MAX_INPUT_ROWS),
|
|
611
|
+
* accounting for word-wrapping within the content width.
|
|
612
|
+
*/
|
|
613
|
+
public getVisiblePromptLineCount(contentWidth?: number): number {
|
|
614
|
+
const info = this.getWrappedPromptInfo(contentWidth ?? 76);
|
|
615
|
+
return Math.min(info.wrappedLines.length, InputHandler.MAX_INPUT_ROWS);
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
/**
|
|
619
|
+
* Word-wrap the prompt and compute cursor display coordinates.
|
|
620
|
+
* Returns wrapped lines, the cursor's position in wrapped coordinates,
|
|
621
|
+
* and the visible slice respecting inputScrollTop.
|
|
622
|
+
*/
|
|
623
|
+
public getWrappedPromptInfo(contentWidth: number): WrappedPromptInfo {
|
|
624
|
+
return getWrappedPromptInfo(
|
|
625
|
+
this.prompt,
|
|
626
|
+
this.cursorPos,
|
|
627
|
+
this.inputScrollTop,
|
|
628
|
+
contentWidth,
|
|
629
|
+
InputHandler.MAX_INPUT_ROWS,
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
// ── Undo / Redo methods ─────────────────────────────────────────────────
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* saveUndoState - Snapshot current prompt + cursor onto the undo stack.
|
|
637
|
+
* Clears the redo stack because a new edit invalidates future states.
|
|
638
|
+
*/
|
|
639
|
+
public saveUndoState(): void {
|
|
640
|
+
saveUndoState(this.undoStack, this.redoStack, this.prompt, this.cursorPos, InputHandler.MAX_UNDO);
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/**
|
|
644
|
+
* handleUndo - Ctrl+Z: pop from undo stack, push current to redo stack.
|
|
645
|
+
*/
|
|
646
|
+
public handleUndo(): void {
|
|
647
|
+
const state = undoPromptState(this.undoStack, this.redoStack, this.prompt, this.cursorPos);
|
|
648
|
+
if (!state) return;
|
|
649
|
+
this.prompt = state.prompt;
|
|
650
|
+
this.cursorPos = state.cursorPos;
|
|
651
|
+
this.ensureInputCursorVisible();
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
/**
|
|
655
|
+
* handleRedo - Ctrl+Shift+Z: pop from redo stack, push current to undo stack.
|
|
656
|
+
*/
|
|
657
|
+
public handleRedo(): void {
|
|
658
|
+
const state = redoPromptState(this.undoStack, this.redoStack, this.prompt, this.cursorPos);
|
|
659
|
+
if (!state) return;
|
|
660
|
+
this.prompt = state.prompt;
|
|
661
|
+
this.cursorPos = state.cursorPos;
|
|
662
|
+
this.ensureInputCursorVisible();
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
// ── Path completion methods ─────────────────────────────────────────────
|
|
666
|
+
|
|
667
|
+
/**
|
|
668
|
+
* findPathToken - Scan backward from cursor to find a path-like token.
|
|
669
|
+
* Detects:
|
|
670
|
+
* - !@<partial> (inject mode)
|
|
671
|
+
* - @<partial> (normal file ref)
|
|
672
|
+
* - plain word containing '/'
|
|
673
|
+
* Returns { start, prefix } or null if no path token found.
|
|
674
|
+
*/
|
|
675
|
+
/**
|
|
676
|
+
* handlePathCompletion - Tab on a path-like token: fuzzy-complete from filePicker.allFiles.
|
|
677
|
+
* Repeated Tab cycles through matches.
|
|
678
|
+
* Returns true if path completion was performed.
|
|
679
|
+
*/
|
|
680
|
+
public findPathToken(): { start: number; prefix: string } | null {
|
|
681
|
+
return findPathToken(this.prompt, this.cursorPos);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
public handlePathCompletion(): boolean {
|
|
685
|
+
const result = handlePathCompletion({
|
|
686
|
+
prompt: this.prompt,
|
|
687
|
+
cursorPos: this.cursorPos,
|
|
688
|
+
inputScrollTop: this.inputScrollTop,
|
|
689
|
+
contentWidth: this.contentWidth,
|
|
690
|
+
maxRows: InputHandler.MAX_INPUT_ROWS,
|
|
691
|
+
pathCompletions: this.pathCompletions,
|
|
692
|
+
pathCompletionIndex: this.pathCompletionIndex,
|
|
693
|
+
pathCompletionPrefix: this.pathCompletionPrefix,
|
|
694
|
+
pathCompletionStart: this.pathCompletionStart,
|
|
695
|
+
allFiles: this.filePicker.allFiles,
|
|
696
|
+
saveUndoState: () => this.saveUndoState(),
|
|
697
|
+
});
|
|
698
|
+
if (!result.handled) return false;
|
|
699
|
+
this.prompt = result.prompt;
|
|
700
|
+
this.cursorPos = result.cursorPos;
|
|
701
|
+
this.inputScrollTop = result.inputScrollTop;
|
|
702
|
+
this.pathCompletions = result.pathCompletions;
|
|
703
|
+
this.pathCompletionIndex = result.pathCompletionIndex;
|
|
704
|
+
this.pathCompletionPrefix = result.pathCompletionPrefix;
|
|
705
|
+
this.pathCompletionStart = result.pathCompletionStart;
|
|
706
|
+
return true;
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
/**
|
|
710
|
+
* Word-wrap a single line to fit within maxW columns.
|
|
711
|
+
* Breaks at spaces; words wider than maxW are force-broken.
|
|
712
|
+
*/
|
|
713
|
+
public cyclePanelTab(direction: 'next' | 'prev'): void {
|
|
714
|
+
const pm = this.uiServices.shell.panelManager;
|
|
715
|
+
if (pm.isVisible()) {
|
|
716
|
+
if (direction === 'next') pm.nextWorkspaceTab();
|
|
717
|
+
else pm.prevWorkspaceTab();
|
|
718
|
+
this.requestRender();
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
public handlePanelIntegrationAction(activePanel: Panel | null, key: string): void {
|
|
723
|
+
runPanelIntegrationAction(this.uiServices.shell.panelManager, activePanel, key, this.commandContext);
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
public wordWrapLine(line: string, maxW: number): string[] {
|
|
727
|
+
return wordWrapLine(line, maxW);
|
|
728
|
+
}
|
|
729
|
+
}
|