@pellux/goodvibes-tui 1.1.0 → 1.7.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 +85 -21
- package/README.md +20 -11
- package/docs/foundation-artifacts/operator-contract.json +1 -1
- package/package.json +2 -2
- package/src/core/alert-gating.ts +67 -0
- package/src/core/approval-alert.ts +72 -0
- package/src/core/budget-breach-notifier.ts +106 -0
- package/src/core/conversation-rendering.ts +19 -0
- package/src/core/conversation.ts +18 -0
- package/src/core/focus-tracker.ts +41 -0
- package/src/core/long-task-notifier.ts +33 -6
- package/src/core/system-message-router.ts +37 -51
- package/src/core/turn-cancellation.ts +20 -0
- package/src/core/turn-event-wiring.ts +64 -3
- package/src/export/cost-utils.ts +36 -0
- package/src/input/command-registry.ts +38 -1
- package/src/input/commands/checkpoint-runtime.ts +280 -0
- package/src/input/commands/codebase-runtime.ts +192 -0
- package/src/input/commands/eval.ts +1 -1
- package/src/input/commands/health-runtime.ts +1 -1
- package/src/input/commands/image-runtime.ts +112 -0
- package/src/input/commands/intelligence-runtime.ts +11 -1
- package/src/input/commands/local-auth-runtime.ts +4 -1
- package/src/input/commands/local-runtime.ts +9 -3
- package/src/input/commands/marketplace-runtime.ts +2 -2
- package/src/input/commands/memory.ts +6 -1
- package/src/input/commands/operator-panel-runtime.ts +40 -24
- package/src/input/commands/planning-runtime.ts +26 -3
- package/src/input/commands/platform-sandbox-runtime.ts +1 -6
- package/src/input/commands/plugin-runtime.ts +2 -2
- package/src/input/commands/policy-dispatch.ts +21 -0
- package/src/input/commands/provider-accounts-runtime.ts +1 -1
- package/src/input/commands/qrcode-runtime.ts +3 -3
- package/src/input/commands/recall-review.ts +35 -0
- package/src/input/commands/remote-runtime.ts +3 -3
- package/src/input/commands/runtime-services.ts +54 -13
- package/src/input/commands/services-runtime.ts +1 -1
- package/src/input/commands/session-workflow.ts +16 -1
- package/src/input/commands/settings-sync-runtime.ts +1 -1
- package/src/input/commands/shell-core.ts +15 -7
- package/src/input/commands/skills-runtime.ts +2 -8
- package/src/input/commands/subscription-runtime.ts +2 -2
- package/src/input/commands/test-runtime.ts +277 -0
- package/src/input/commands/websearch-runtime.ts +101 -0
- package/src/input/commands/work-plan-runtime.ts +36 -10
- package/src/input/commands/workstream-runtime.ts +338 -0
- package/src/input/commands.ts +12 -0
- package/src/input/config-modal-types.ts +161 -0
- package/src/input/config-modal.ts +377 -0
- package/src/input/feed-context-factory.ts +7 -8
- package/src/input/handler-command-route.ts +27 -17
- package/src/input/handler-feed-routes.ts +61 -23
- package/src/input/handler-feed.ts +47 -23
- package/src/input/handler-interactions.ts +1 -3
- package/src/input/handler-modal-routes.ts +65 -0
- package/src/input/handler-modal-stack.ts +3 -5
- package/src/input/handler-modal-token-routes.ts +16 -49
- package/src/input/handler-picker-routes.ts +11 -94
- package/src/input/handler-shortcuts.ts +24 -14
- package/src/input/handler-types.ts +2 -6
- package/src/input/handler-ui-state.ts +10 -22
- package/src/input/handler.ts +6 -28
- package/src/input/keybindings.ts +22 -8
- package/src/input/model-picker-types.ts +24 -6
- package/src/input/model-picker.ts +58 -0
- package/src/input/panel-integration-actions.ts +9 -170
- package/src/input/settings-modal-data.ts +95 -0
- package/src/input/settings-modal-mutations.ts +6 -4
- package/src/main.ts +24 -27
- package/src/panels/agent-inspector-shared.ts +2 -1
- package/src/panels/base-panel.ts +22 -1
- package/src/panels/builtin/agent.ts +21 -107
- package/src/panels/builtin/development.ts +15 -61
- package/src/panels/builtin/knowledge.ts +8 -32
- package/src/panels/builtin/operations.ts +84 -428
- package/src/panels/builtin/session.ts +21 -112
- package/src/panels/builtin/shared.ts +9 -43
- package/src/panels/builtin-modals.ts +218 -0
- package/src/panels/builtin-panels.ts +5 -0
- package/src/panels/cost-tracker-panel.ts +36 -10
- package/src/panels/diff-panel.ts +12 -43
- package/src/panels/eval-registry.ts +60 -0
- package/src/panels/fleet-panel.ts +800 -0
- package/src/panels/fleet-read-model.ts +477 -0
- package/src/panels/fleet-steer.ts +92 -0
- package/src/panels/fleet-stop.ts +125 -0
- package/src/panels/fleet-tabs.ts +230 -0
- package/src/panels/fleet-transcript.ts +356 -0
- package/src/panels/index.ts +7 -31
- package/src/panels/modals/hooks-modal.ts +187 -0
- package/src/panels/modals/keybindings-modal.ts +151 -0
- package/src/panels/modals/knowledge-modal.ts +158 -0
- package/src/panels/modals/local-auth-modal.ts +132 -0
- package/src/panels/modals/marketplace-modal.ts +218 -0
- package/src/panels/modals/memory-modal.ts +180 -0
- package/src/panels/modals/modal-surface-helpers.ts +54 -0
- package/src/panels/modals/modal-theme.ts +36 -0
- package/src/panels/modals/pairing-modal.ts +144 -0
- package/src/panels/modals/planning-modal.ts +282 -0
- package/src/panels/modals/plugins-modal.ts +174 -0
- package/src/panels/modals/policy-modal.ts +256 -0
- package/src/panels/modals/provider-health-modal.ts +136 -0
- package/src/panels/modals/remote-modal.ts +115 -0
- package/src/panels/modals/sandbox-modal.ts +150 -0
- package/src/panels/modals/security-modal.ts +217 -0
- package/src/panels/modals/services-modal.ts +179 -0
- package/src/panels/modals/settings-sync-modal.ts +142 -0
- package/src/panels/modals/skills-modal.ts +189 -0
- package/src/panels/modals/subscription-modal.ts +172 -0
- package/src/panels/modals/work-plan-modal.ts +149 -0
- package/src/panels/panel-confirm-overlay.ts +72 -0
- package/src/panels/panel-manager.ts +108 -5
- package/src/panels/project-planning-answer-actions.ts +4 -2
- package/src/panels/skills-panel.ts +7 -51
- package/src/panels/types.ts +13 -0
- package/src/permissions/hunk-selection.ts +179 -0
- package/src/permissions/prompt.ts +60 -4
- package/src/renderer/compaction-history-modal.ts +19 -3
- package/src/renderer/compaction-preview.ts +13 -2
- package/src/renderer/compaction-quality.ts +100 -0
- package/src/renderer/config-modal.ts +81 -0
- package/src/renderer/conversation-overlays.ts +10 -17
- package/src/renderer/fleet-tab-strip.ts +56 -0
- package/src/renderer/footer-tips.ts +10 -2
- package/src/renderer/git-status.ts +40 -0
- package/src/renderer/help-overlay.ts +2 -2
- package/src/renderer/model-workspace.ts +44 -1
- package/src/renderer/panel-workspace-bar.ts +8 -2
- package/src/renderer/turn-injection.ts +114 -0
- package/src/runtime/bootstrap-command-context.ts +21 -1
- package/src/runtime/bootstrap-command-parts.ts +34 -7
- package/src/runtime/bootstrap-core.ts +14 -4
- package/src/runtime/bootstrap-shell.ts +29 -16
- package/src/runtime/bootstrap.ts +11 -17
- package/src/runtime/code-index-services.ts +112 -0
- package/src/runtime/orchestrator-core-services.ts +49 -0
- package/src/runtime/process-lifecycle.ts +3 -1
- package/src/runtime/services.ts +91 -43
- package/src/runtime/ui-services.ts +8 -0
- package/src/runtime/workstream-services.ts +195 -0
- package/src/shell/blocking-input.ts +22 -1
- package/src/shell/ui-openers.ts +129 -17
- package/src/utils/format-duration.ts +8 -18
- package/src/utils/splash-lines.ts +1 -1
- package/src/version.ts +1 -1
- package/src/panels/agent-inspector-panel.ts +0 -786
- package/src/panels/approval-panel.ts +0 -252
- package/src/panels/automation-control-panel.ts +0 -479
- package/src/panels/cockpit-panel.ts +0 -481
- package/src/panels/cockpit-read-model.ts +0 -238
- package/src/panels/communication-panel.ts +0 -256
- package/src/panels/control-plane-panel.ts +0 -470
- package/src/panels/debug-panel.ts +0 -615
- package/src/panels/docs-panel.ts +0 -384
- package/src/panels/eval-panel.ts +0 -627
- package/src/panels/file-explorer-panel.ts +0 -673
- package/src/panels/file-preview-panel.ts +0 -517
- package/src/panels/hooks-panel.ts +0 -401
- package/src/panels/incident-review-panel.ts +0 -406
- package/src/panels/intelligence-panel.ts +0 -383
- package/src/panels/knowledge-graph-panel.ts +0 -515
- package/src/panels/marketplace-panel.ts +0 -399
- package/src/panels/memory-panel.ts +0 -558
- package/src/panels/ops-control-panel.ts +0 -329
- package/src/panels/ops-strategy-panel.ts +0 -321
- package/src/panels/orchestration-panel.ts +0 -465
- package/src/panels/panel-list-panel.ts +0 -566
- package/src/panels/plan-dashboard-panel.ts +0 -707
- package/src/panels/policy-panel.ts +0 -517
- package/src/panels/project-planning-panel.ts +0 -731
- package/src/panels/provider-health-panel.ts +0 -678
- package/src/panels/provider-health-tracker.ts +0 -310
- package/src/panels/provider-health-views.ts +0 -567
- package/src/panels/qr-panel.ts +0 -280
- package/src/panels/remote-panel.ts +0 -534
- package/src/panels/routes-panel.ts +0 -241
- package/src/panels/sandbox-panel.ts +0 -456
- package/src/panels/security-panel.ts +0 -447
- package/src/panels/services-panel.ts +0 -329
- package/src/panels/session-browser-panel.ts +0 -496
- package/src/panels/settings-sync-panel.ts +0 -398
- package/src/panels/subscription-panel.ts +0 -342
- package/src/panels/symbol-outline-panel.ts +0 -619
- package/src/panels/system-messages-panel.ts +0 -364
- package/src/panels/tasks-panel.ts +0 -608
- package/src/panels/thinking-panel.ts +0 -333
- package/src/panels/tool-inspector-panel.ts +0 -537
- package/src/panels/work-plan-panel.ts +0 -540
- package/src/panels/worktree-panel.ts +0 -360
- package/src/panels/wrfc-panel.ts +0 -790
- package/src/renderer/agent-detail-modal.ts +0 -466
- package/src/renderer/live-tail-modal.ts +0 -156
- package/src/renderer/process-modal.ts +0 -671
- package/src/renderer/qr-renderer.ts +0 -120
package/src/runtime/services.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { join } from 'node:path';
|
|
2
|
-
import {
|
|
2
|
+
import { FocusTracker } from '../core/focus-tracker.ts';
|
|
3
|
+
import { ConfigManager, ServiceRegistry, SubscriptionManager, ToolLLM } from '@pellux/goodvibes-sdk/platform/config';
|
|
3
4
|
import { SecretsManager } from '../config/secrets.ts';
|
|
4
|
-
import { ServiceRegistry } from '@pellux/goodvibes-sdk/platform/config';
|
|
5
|
-
import { SubscriptionManager } from '@pellux/goodvibes-sdk/platform/config';
|
|
6
5
|
import { AutomationDeliveryManager, AutomationManager, AutomationRouteStore } from '@pellux/goodvibes-sdk/platform/automation';
|
|
7
|
-
import { ChannelPluginRegistry, ChannelPolicyManager, RouteBindingManager, SurfaceRegistry } from '@pellux/goodvibes-sdk/platform/channels';
|
|
8
|
-
import { ChannelDeliveryRouter } from '@pellux/goodvibes-sdk/platform/channels';
|
|
6
|
+
import { ChannelDeliveryRouter, ChannelPluginRegistry, ChannelPolicyManager, RouteBindingManager, SurfaceRegistry } from '@pellux/goodvibes-sdk/platform/channels';
|
|
9
7
|
import { ApprovalBroker, GatewayMethodCatalog, SharedSessionBroker } from '@pellux/goodvibes-sdk/platform/control-plane';
|
|
10
8
|
import { WatcherRegistry } from '@pellux/goodvibes-sdk/platform/watchers';
|
|
11
9
|
import { ArtifactStore } from '@pellux/goodvibes-sdk/platform/artifacts';
|
|
@@ -23,16 +21,10 @@ import {
|
|
|
23
21
|
} from '@pellux/goodvibes-sdk/platform/knowledge';
|
|
24
22
|
import { MediaProviderRegistry, ensureBuiltinMediaProviders } from '@pellux/goodvibes-sdk/platform/media';
|
|
25
23
|
import { MultimodalService } from '@pellux/goodvibes-sdk/platform/multimodal';
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
30
|
-
import { ArchetypeLoader } from '@pellux/goodvibes-sdk/platform/agents';
|
|
31
|
-
import { ProcessManager } from '@pellux/goodvibes-sdk/platform/tools';
|
|
32
|
-
import { ModeManager } from '@pellux/goodvibes-sdk/platform/state';
|
|
33
|
-
import { FileUndoManager } from '@pellux/goodvibes-sdk/platform/state';
|
|
34
|
-
import { MemoryRegistry } from '@pellux/goodvibes-sdk/platform/state';
|
|
35
|
-
import { MemoryStore } from '@pellux/goodvibes-sdk/platform/state';
|
|
24
|
+
import { AgentMessageBus, AgentOrchestrator, ArchetypeLoader, WrfcController } from '@pellux/goodvibes-sdk/platform/agents';
|
|
25
|
+
import { AgentManager, OverflowHandler, ProcessManager, createWorkflowServices, type WorkflowServices } from '@pellux/goodvibes-sdk/platform/tools';
|
|
26
|
+
import { FileStateCache, FileUndoManager, MemoryEmbeddingProviderRegistry, MemoryRegistry, MemoryStore, ModeManager, ProjectIndex, type CodeIndexStore } from '@pellux/goodvibes-sdk/platform/state';
|
|
27
|
+
import { WorkspaceCheckpointManager } from '@pellux/goodvibes-sdk/platform/workspace';
|
|
36
28
|
import type { RuntimeEventBus } from '@/runtime/index.ts';
|
|
37
29
|
import { createDomainDispatch } from './store/index.ts';
|
|
38
30
|
import type { DomainDispatch, RuntimeStore } from './store/index.ts';
|
|
@@ -41,40 +33,20 @@ import { RemoteRunnerRegistry, RemoteSupervisor } from '@/runtime/index.ts';
|
|
|
41
33
|
import { IntegrationHelperService } from '@/runtime/index.ts';
|
|
42
34
|
import { VoiceProviderRegistry, VoiceService, ensureBuiltinVoiceProviders } from '@pellux/goodvibes-sdk/platform/voice';
|
|
43
35
|
import { WebSearchProviderRegistry, WebSearchService } from '@pellux/goodvibes-sdk/platform/web-search';
|
|
44
|
-
import { MemoryEmbeddingProviderRegistry } from '@pellux/goodvibes-sdk/platform/state';
|
|
45
36
|
import { PanelManager } from '../panels/panel-manager.ts';
|
|
46
37
|
import { HookActivityTracker } from '@pellux/goodvibes-sdk/platform/hooks';
|
|
47
38
|
import { HookDispatcher, createHookWorkbench, type HookWorkbench } from '@pellux/goodvibes-sdk/platform/hooks';
|
|
48
39
|
import { PluginManager } from '@pellux/goodvibes-sdk/platform/plugins';
|
|
49
40
|
import { BookmarkManager } from '@pellux/goodvibes-sdk/platform/bookmarks';
|
|
50
41
|
import { ProfileManager } from '@pellux/goodvibes-sdk/platform/profiles';
|
|
51
|
-
import { SessionManager } from '@pellux/goodvibes-sdk/platform/sessions';
|
|
52
|
-
import {
|
|
53
|
-
import { ApiTokenAuditor } from '@pellux/goodvibes-sdk/platform/security';
|
|
54
|
-
import { UserAuthManager } from '@pellux/goodvibes-sdk/platform/security';
|
|
42
|
+
import { SessionManager, CrossSessionTaskRegistry, SessionChangeTracker } from '@pellux/goodvibes-sdk/platform/sessions';
|
|
43
|
+
import { ApiTokenAuditor, UserAuthManager } from '@pellux/goodvibes-sdk/platform/security';
|
|
55
44
|
import { WebhookNotifier } from '@pellux/goodvibes-sdk/platform/integrations';
|
|
56
45
|
import { McpRegistry } from '@pellux/goodvibes-sdk/platform/mcp';
|
|
57
|
-
import {
|
|
58
|
-
import { ProviderOptimizer } from '@pellux/goodvibes-sdk/platform/providers';
|
|
59
|
-
import { ProviderRegistry } from '@pellux/goodvibes-sdk/platform/providers';
|
|
60
|
-
import type { ModelDefinition } from '@pellux/goodvibes-sdk/platform/providers';
|
|
61
|
-
import { ProviderCapabilityRegistry } from '@pellux/goodvibes-sdk/platform/providers';
|
|
62
|
-
import { CacheHitTracker } from '@pellux/goodvibes-sdk/platform/providers';
|
|
63
|
-
import { FavoritesStore } from '@pellux/goodvibes-sdk/platform/providers';
|
|
64
|
-
import { BenchmarkStore } from '@pellux/goodvibes-sdk/platform/providers';
|
|
65
|
-
import { ModelLimitsService } from '@pellux/goodvibes-sdk/platform/providers';
|
|
66
|
-
import { inferFallbackContextWindow } from '@pellux/goodvibes-sdk/platform/providers';
|
|
46
|
+
import { BenchmarkStore, CacheHitTracker, FavoritesStore, inferFallbackContextWindow, type ModelDefinition, ModelLimitsService, ProviderCapabilityRegistry, ProviderOptimizer, ProviderRegistry } from '@pellux/goodvibes-sdk/platform/providers';
|
|
67
47
|
import { KeybindingsManager } from '../input/keybindings.ts';
|
|
68
|
-
import { SessionMemoryStore } from '@pellux/goodvibes-sdk/platform/core';
|
|
69
|
-
import { SessionLineageTracker } from '@pellux/goodvibes-sdk/platform/core';
|
|
70
|
-
import { SessionChangeTracker } from '@pellux/goodvibes-sdk/platform/sessions';
|
|
71
|
-
import { ExecutionPlanManager } from '@pellux/goodvibes-sdk/platform/core';
|
|
72
|
-
import { AdaptivePlanner } from '@pellux/goodvibes-sdk/platform/core';
|
|
73
|
-
import { FileStateCache } from '@pellux/goodvibes-sdk/platform/state';
|
|
74
|
-
import { ProjectIndex } from '@pellux/goodvibes-sdk/platform/state';
|
|
48
|
+
import { AdaptivePlanner, DeterministicReplayEngine, ExecutionPlanManager, SessionLineageTracker, SessionMemoryStore } from '@pellux/goodvibes-sdk/platform/core';
|
|
75
49
|
import { IdempotencyStore } from '@/runtime/index.ts';
|
|
76
|
-
import { OverflowHandler } from '@pellux/goodvibes-sdk/platform/tools';
|
|
77
|
-
import { ToolLLM } from '@pellux/goodvibes-sdk/platform/config';
|
|
78
50
|
import { ComponentHealthMonitor } from '@/runtime/index.ts';
|
|
79
51
|
import { WorktreeRegistry } from '@/runtime/index.ts';
|
|
80
52
|
import { SandboxSessionRegistry } from '@/runtime/index.ts';
|
|
@@ -83,10 +55,10 @@ import { isFeatureFlagEnabled } from './surface-feature-flags.ts';
|
|
|
83
55
|
import type { FeatureFlagManager } from '@/runtime/index.ts';
|
|
84
56
|
import { createFeatureFlagManager } from '@/runtime/index.ts';
|
|
85
57
|
import { PolicyRuntimeState } from '@/runtime/index.ts';
|
|
86
|
-
import {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
} from '
|
|
58
|
+
import { createProcessRegistry, type ProcessRegistry } from '@pellux/goodvibes-sdk/platform/runtime/fleet';
|
|
59
|
+
import { calcSessionCost, isModelPriced } from '../export/cost-utils.ts';
|
|
60
|
+
import { createWorkstreamServices, type OrchestrationEngine, type WorkstreamCommandService } from './workstream-services.ts';
|
|
61
|
+
import { codeIndexDbPath, createCodeIndexServices } from './code-index-services.ts';
|
|
90
62
|
import { WorkPlanStore } from '../work-plans/work-plan-store.ts';
|
|
91
63
|
import {
|
|
92
64
|
registerDaemonHandlers,
|
|
@@ -221,6 +193,8 @@ export interface RuntimeServices {
|
|
|
221
193
|
readonly worktreeRegistry: WorktreeRegistry;
|
|
222
194
|
readonly sandboxSessionRegistry: SandboxSessionRegistry;
|
|
223
195
|
readonly webhookNotifier: WebhookNotifier;
|
|
196
|
+
/** Terminal focus tracker (W2.3) — fed by input/handler-feed.ts, read by the alert notifiers in core/. */
|
|
197
|
+
readonly focusTracker: FocusTracker;
|
|
224
198
|
readonly replayEngine: DeterministicReplayEngine;
|
|
225
199
|
readonly providerOptimizer: ProviderOptimizer;
|
|
226
200
|
readonly providerCapabilityRegistry: ProviderCapabilityRegistry;
|
|
@@ -248,8 +222,16 @@ export interface RuntimeServices {
|
|
|
248
222
|
readonly agentOrchestrator: AgentOrchestrator;
|
|
249
223
|
readonly wrfcController: WrfcController;
|
|
250
224
|
readonly processManager: ProcessManager;
|
|
225
|
+
/** Wave 4 (wo703): the phase/work-item orchestration engine — see runtime/workstream-services.ts. */
|
|
226
|
+
readonly orchestrationEngine: OrchestrationEngine;
|
|
227
|
+
readonly workstreamCommands: WorkstreamCommandService;
|
|
228
|
+
/** Wave 5 (wo804): the repo source-tree code index — see runtime/code-index-services.ts. */
|
|
229
|
+
readonly codeIndexStore: CodeIndexStore;
|
|
230
|
+
/** W2.1/W2.2: unified live process registry (agents, WRFC chains, workflows, watchers, background processes) backing the Fleet panel. */
|
|
231
|
+
readonly processRegistry: ProcessRegistry;
|
|
251
232
|
readonly modeManager: ModeManager;
|
|
252
233
|
readonly fileUndoManager: FileUndoManager;
|
|
234
|
+
readonly workspaceCheckpointManager: WorkspaceCheckpointManager;
|
|
253
235
|
readonly integrationHelpers: IntegrationHelperService;
|
|
254
236
|
/**
|
|
255
237
|
* Re-root path-bound stores (MemoryStore, ProjectIndex) to a new working directory.
|
|
@@ -272,6 +254,9 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
272
254
|
const runtimeDispatch = createDomainDispatch(options.runtimeStore);
|
|
273
255
|
const gatewayMethods = new GatewayMethodCatalog();
|
|
274
256
|
const panelManager = new PanelManager();
|
|
257
|
+
// W6.1 (the purge): MIGRATE-TO-MODAL surface + redirect registration moved to
|
|
258
|
+
// registerBuiltinPanels (builtin-panels.ts), where the panels' resolved deps
|
|
259
|
+
// are available for the surfaces to close over.
|
|
275
260
|
const keybindingsManager = new KeybindingsManager({
|
|
276
261
|
configPath: shellPaths.resolveUserPath('tui', 'keybindings.json'),
|
|
277
262
|
});
|
|
@@ -352,6 +337,10 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
352
337
|
executor: agentOrchestrator,
|
|
353
338
|
configManager,
|
|
354
339
|
});
|
|
340
|
+
agentOrchestrator.setConversationSink({ // Wave-3 Part C6 bridge (mirrors the SDK's own createRuntimeServices)
|
|
341
|
+
register: (agentId, source) => agentManager.registerConversationSource(agentId, source),
|
|
342
|
+
release: (agentId) => agentManager.releaseConversationSource(agentId),
|
|
343
|
+
});
|
|
355
344
|
agentManager.setRuntimeBus(options.runtimeBus);
|
|
356
345
|
const wrfcController = new WrfcController(options.runtimeBus, agentMessageBus, {
|
|
357
346
|
agentManager,
|
|
@@ -580,6 +569,7 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
580
569
|
const componentHealthMonitor = new ComponentHealthMonitor();
|
|
581
570
|
const worktreeRegistry = new WorktreeRegistry(workingDirectory);
|
|
582
571
|
const webhookNotifier = new WebhookNotifier();
|
|
572
|
+
const focusTracker = new FocusTracker();
|
|
583
573
|
const replayEngine = new DeterministicReplayEngine(workingDirectory);
|
|
584
574
|
const providerOptimizer = new ProviderOptimizer(
|
|
585
575
|
providerRegistry,
|
|
@@ -603,8 +593,57 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
603
593
|
artifactStore,
|
|
604
594
|
});
|
|
605
595
|
const processManager = new ProcessManager();
|
|
596
|
+
// Wave 4 (wo703): the phase/work-item orchestration engine, constructed
|
|
597
|
+
// before the process registry so its fleet nodes (workstream/phase/
|
|
598
|
+
// work-item) can be folded in below via the registry's optional
|
|
599
|
+
// orchestrationEngine dep.
|
|
600
|
+
const { orchestrationEngine, workstreamCommands } = createWorkstreamServices({
|
|
601
|
+
agentManager, configManager, adaptivePlanner, runtimeBus: options.runtimeBus, projectRoot: workingDirectory,
|
|
602
|
+
});
|
|
603
|
+
// Wave 5 (wo804): repo source-tree code index, sharing memoryEmbeddingRegistry
|
|
604
|
+
// with MemoryStore above. Auto-build is config-gated (default off) — see
|
|
605
|
+
// code-index-services.ts's header doc.
|
|
606
|
+
const { codeIndexStore } = createCodeIndexServices({ workingDirectory, configManager, memoryEmbeddingRegistry });
|
|
607
|
+
// W2.1/W2.2: one shared process registry aggregating the managers above —
|
|
608
|
+
// the Fleet panel (panels/fleet-read-model.ts) is its first consumer.
|
|
609
|
+
// Constructed once here (not per-consumer) so the coalesced tick and the
|
|
610
|
+
// agent-activity side-table are shared, not duplicated.
|
|
611
|
+
const processRegistry = createProcessRegistry({
|
|
612
|
+
agentManager,
|
|
613
|
+
wrfcController,
|
|
614
|
+
orchestrationEngine, // Wave 4 (wo703): folds workstream/phase/work-item nodes into the fleet
|
|
615
|
+
codeIndexService: codeIndexStore, // Wave 5 (wo804): folds a single 'code-index' node into the fleet
|
|
616
|
+
processManager,
|
|
617
|
+
watcherRegistry,
|
|
618
|
+
workflow,
|
|
619
|
+
approvalBroker,
|
|
620
|
+
sessionBroker,
|
|
621
|
+
messageBus: agentMessageBus, // Wave-3: backs steer()/`steerable` (wo612 builds the composer UI on top)
|
|
622
|
+
automationManager, // Wave 6 (wo-F item d4): folds /schedule AutomationJobs into the fleet as 'schedule' nodes
|
|
623
|
+
runtimeBus: options.runtimeBus,
|
|
624
|
+
// Honest pricing: never fabricate a cost for an unrecognized model.
|
|
625
|
+
priceUsage: (model, usage) => {
|
|
626
|
+
const modelId = model ?? 'unknown';
|
|
627
|
+
if (!isModelPriced(modelId)) return null;
|
|
628
|
+
return calcSessionCost(usage.inputTokens, usage.outputTokens, usage.cacheReadTokens, usage.cacheWriteTokens, modelId);
|
|
629
|
+
},
|
|
630
|
+
});
|
|
606
631
|
const modeManager = new ModeManager();
|
|
607
632
|
const fileUndoManager = new FileUndoManager();
|
|
633
|
+
const workspaceCheckpointManager = new WorkspaceCheckpointManager({
|
|
634
|
+
workspaceRoot: workingDirectory,
|
|
635
|
+
runtimeBus: options.runtimeBus,
|
|
636
|
+
});
|
|
637
|
+
// Fire-and-forget: subscriptions go live immediately if init() succeeds.
|
|
638
|
+
// If it rejects, WorkspaceCheckpointManager caches that rejection on
|
|
639
|
+
// `initPromise` and never clears it, so every later call (create/list/
|
|
640
|
+
// diff/restore — each awaits init() first) re-throws the same error
|
|
641
|
+
// forever: checkpointing becomes entirely unavailable for the rest of the
|
|
642
|
+
// session, not "degraded to manual-only". The `.catch(() => {})` here only
|
|
643
|
+
// exists to prevent an unhandled rejection at startup; the checkpoint
|
|
644
|
+
// commands (checkpoint-runtime.ts) are what actually catch and report the
|
|
645
|
+
// failure to the user, on first use.
|
|
646
|
+
void workspaceCheckpointManager.init().catch(() => {});
|
|
608
647
|
const integrationHelpers = new IntegrationHelperService({
|
|
609
648
|
workingDirectory,
|
|
610
649
|
homeDirectory,
|
|
@@ -709,6 +748,7 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
709
748
|
worktreeRegistry,
|
|
710
749
|
sandboxSessionRegistry,
|
|
711
750
|
webhookNotifier,
|
|
751
|
+
focusTracker,
|
|
712
752
|
replayEngine,
|
|
713
753
|
providerOptimizer,
|
|
714
754
|
providerCapabilityRegistry,
|
|
@@ -736,12 +776,20 @@ export function createRuntimeServices(options: RuntimeServicesOptions): RuntimeS
|
|
|
736
776
|
agentOrchestrator,
|
|
737
777
|
wrfcController,
|
|
738
778
|
processManager,
|
|
779
|
+
orchestrationEngine,
|
|
780
|
+
workstreamCommands,
|
|
781
|
+
codeIndexStore,
|
|
782
|
+
processRegistry,
|
|
739
783
|
modeManager,
|
|
740
784
|
fileUndoManager,
|
|
785
|
+
workspaceCheckpointManager,
|
|
741
786
|
integrationHelpers,
|
|
742
787
|
async rerootStores(newWorkingDir: string): Promise<void> {
|
|
743
788
|
const newMemoryDbPath = join(newWorkingDir, '.goodvibes', 'tui', 'memory.sqlite');
|
|
744
789
|
await memoryStore.reroot(newMemoryDbPath);
|
|
790
|
+
// Wave 5 (wo804) risk #7: the code index must follow memory to the new
|
|
791
|
+
// tree, or it keeps pointing at the old working directory.
|
|
792
|
+
await codeIndexStore.reroot(newWorkingDir, codeIndexDbPath(newWorkingDir));
|
|
745
793
|
await projectIndex.reroot(newWorkingDir);
|
|
746
794
|
},
|
|
747
795
|
};
|
|
@@ -55,6 +55,7 @@ export interface UiPlatformServices {
|
|
|
55
55
|
readonly tokenAuditor: RuntimeServices['tokenAuditor'];
|
|
56
56
|
readonly replayEngine: RuntimeServices['replayEngine'];
|
|
57
57
|
readonly webhookNotifier: RuntimeServices['webhookNotifier'];
|
|
58
|
+
readonly focusTracker: RuntimeServices['focusTracker'];
|
|
58
59
|
readonly policyRuntimeState: RuntimeServices['policyRuntimeState'];
|
|
59
60
|
readonly externalServices?: {
|
|
60
61
|
inspect(): {
|
|
@@ -101,6 +102,10 @@ export interface UiRuntimeSharedServices {
|
|
|
101
102
|
readonly distributedRuntime: RuntimeServices['distributedRuntime'];
|
|
102
103
|
readonly remoteRunnerRegistry: RuntimeServices['remoteRunnerRegistry'] & RemoteRunnerRegistry;
|
|
103
104
|
readonly remoteSupervisor: RuntimeServices['remoteSupervisor'] & RemoteSupervisor;
|
|
105
|
+
/** W2.2: the shared live process registry backing the Fleet panel. */
|
|
106
|
+
readonly processRegistry: RuntimeServices['processRegistry'];
|
|
107
|
+
/** Wave-3 (W3.2): the shared runtime event bus — the Fleet panel subscribes to its 'communication' domain for the honest steer-consumed signal. */
|
|
108
|
+
readonly runtimeBus: RuntimeServices['runtimeBus'];
|
|
104
109
|
};
|
|
105
110
|
}
|
|
106
111
|
|
|
@@ -167,6 +172,7 @@ export function createUiRuntimeServices(
|
|
|
167
172
|
tokenAuditor: runtimeServices.tokenAuditor,
|
|
168
173
|
replayEngine: runtimeServices.replayEngine,
|
|
169
174
|
webhookNotifier: runtimeServices.webhookNotifier,
|
|
175
|
+
focusTracker: runtimeServices.focusTracker,
|
|
170
176
|
policyRuntimeState: runtimeServices.policyRuntimeState,
|
|
171
177
|
},
|
|
172
178
|
planning: {
|
|
@@ -183,6 +189,8 @@ export function createUiRuntimeServices(
|
|
|
183
189
|
distributedRuntime: runtimeServices.distributedRuntime,
|
|
184
190
|
remoteRunnerRegistry: runtimeServices.remoteRunnerRegistry,
|
|
185
191
|
remoteSupervisor: runtimeServices.remoteSupervisor,
|
|
192
|
+
processRegistry: runtimeServices.processRegistry,
|
|
193
|
+
runtimeBus: runtimeServices.runtimeBus,
|
|
186
194
|
},
|
|
187
195
|
events: createUiRuntimeEvents(runtimeServices.runtimeBus),
|
|
188
196
|
readModels: createUiReadModels(runtimeServices, options),
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// workstream-services.ts — Wave 4 (wo703)
|
|
3
|
+
//
|
|
4
|
+
// Constructs the TUI's OrchestrationEngine instance (@pellux/goodvibes-sdk/
|
|
5
|
+
// platform/orchestration, landed on SDK main as wo701/W4.1) and a thin
|
|
6
|
+
// command-facing facade around it. Extracted into its own module rather than
|
|
7
|
+
// built inline in services.ts: services.ts sits at the architecture check's
|
|
8
|
+
// 800-line cap (scripts/check-architecture.ts), so any new service gets its
|
|
9
|
+
// own construction module and a single wiring call there (mirrors
|
|
10
|
+
// createWorkflowServices's one-function-bundle shape).
|
|
11
|
+
//
|
|
12
|
+
// Why a facade, not the bare engine: createOrchestrationEngine() is a pure
|
|
13
|
+
// construction call with no auto-start and NO concept of a not-yet-launched
|
|
14
|
+
// "proposal" a human can review/edit before anything is spent — its only
|
|
15
|
+
// creation entry point, createWorkstream(), immediately materializes a real,
|
|
16
|
+
// ticking-eligible Workstream. The /workstream command module
|
|
17
|
+
// (input/commands/workstream-runtime.ts) needs a create -> propose -> approve
|
|
18
|
+
// -> launch flow (Pillar-3 doctrine: render the plan in the transcript before
|
|
19
|
+
// spending anything, mirroring /plan's approve step). REALITY-WINS DIVERGENCE
|
|
20
|
+
// from the wo703 design brief: the brief recommended an "engine-owned/
|
|
21
|
+
// journal-backed" draft so `/workstream status` could re-render a pending
|
|
22
|
+
// proposal after a restart; the real engine (verified against the linked SDK
|
|
23
|
+
// build) exposes no pre-creation draft concept at all, so WorkstreamDraft
|
|
24
|
+
// below is process-lifetime-only state, owned by this module's facade
|
|
25
|
+
// instance (constructed once, threaded onto CommandContext) — never a
|
|
26
|
+
// module-level ambient global. A draft that existed only in memory is lost on
|
|
27
|
+
// restart, same as an unsent chat draft; that is a real, stated limitation,
|
|
28
|
+
// not a bug.
|
|
29
|
+
// ---------------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
import {
|
|
32
|
+
createOrchestrationEngine,
|
|
33
|
+
fromChainSpec,
|
|
34
|
+
type CreateWorkstreamInput,
|
|
35
|
+
type OrchestrationEngine,
|
|
36
|
+
} from '@pellux/goodvibes-sdk/platform/orchestration';
|
|
37
|
+
export type { OrchestrationEngine } from '@pellux/goodvibes-sdk/platform/orchestration';
|
|
38
|
+
import { AdaptivePlanner, type DecompositionGate, type PlannerInputs } from '@pellux/goodvibes-sdk/platform/core';
|
|
39
|
+
import type { ConfigManager } from '@pellux/goodvibes-sdk/platform/config';
|
|
40
|
+
import type { AgentManager } from '@pellux/goodvibes-sdk/platform/tools';
|
|
41
|
+
import type { RuntimeEventBus } from '@/runtime/index.ts';
|
|
42
|
+
import { calcSessionCost, isModelPriced } from '../export/cost-utils.ts';
|
|
43
|
+
|
|
44
|
+
export interface WorkstreamServicesDeps {
|
|
45
|
+
readonly agentManager: Pick<AgentManager, 'spawn' | 'getStatus' | 'cancel' | 'registerCancellationSignal' | 'releaseCancellationSignal'>;
|
|
46
|
+
readonly configManager: Pick<ConfigManager, 'get' | 'getCategory'>;
|
|
47
|
+
readonly adaptivePlanner: AdaptivePlanner;
|
|
48
|
+
readonly runtimeBus: RuntimeEventBus;
|
|
49
|
+
readonly projectRoot: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** A not-yet-launched /workstream proposal. See this file's header doc for why it lives here rather than on the engine. */
|
|
53
|
+
export interface WorkstreamDraft {
|
|
54
|
+
readonly id: string;
|
|
55
|
+
task: string;
|
|
56
|
+
spec: CreateWorkstreamInput;
|
|
57
|
+
readonly gate: DecompositionGate;
|
|
58
|
+
approved: boolean;
|
|
59
|
+
readonly createdAt: number;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** `ctx.session.workstreamEngine`'s real shape: the live engine plus the draft-proposal bookkeeping the engine itself has no concept of. */
|
|
63
|
+
export interface WorkstreamCommandService {
|
|
64
|
+
readonly engine: OrchestrationEngine;
|
|
65
|
+
proposeDraft(task: string): WorkstreamDraft;
|
|
66
|
+
getDraft(id: string): WorkstreamDraft | undefined;
|
|
67
|
+
listDrafts(): WorkstreamDraft[];
|
|
68
|
+
/** Re-derive a held draft's spec from a new task string. Clears any prior approval — an edit must be re-approved. */
|
|
69
|
+
editDraft(id: string, task: string): WorkstreamDraft | undefined;
|
|
70
|
+
approveDraft(id: string): WorkstreamDraft | undefined;
|
|
71
|
+
removeDraft(id: string): boolean;
|
|
72
|
+
/** Materialize an approved draft into a real, running Workstream (engine.createWorkstream + start), then drop the draft. Null when the draft is missing or not approved. */
|
|
73
|
+
launchDraft(id: string): { workstreamId: string } | null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface WorkstreamServices {
|
|
77
|
+
readonly orchestrationEngine: OrchestrationEngine;
|
|
78
|
+
readonly workstreamCommands: WorkstreamCommandService;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Placeholder planner inputs until a richer risk/latency signal is wired in.
|
|
83
|
+
* `/workstream create` is inherently a multi-step authoring surface, so
|
|
84
|
+
* isMultiStep is always true; the rest are neutral defaults that let
|
|
85
|
+
* AdaptivePlanner's real scoring run rather than short-circuiting it.
|
|
86
|
+
*/
|
|
87
|
+
function buildPlannerInputs(task: string): PlannerInputs {
|
|
88
|
+
return {
|
|
89
|
+
riskScore: 0.3,
|
|
90
|
+
latencyBudgetMs: Number.POSITIVE_INFINITY,
|
|
91
|
+
isMultiStep: true,
|
|
92
|
+
remoteAvailable: false,
|
|
93
|
+
backgroundEligible: false,
|
|
94
|
+
taskDescription: task,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function createWorkstreamCommandService(
|
|
99
|
+
engine: OrchestrationEngine,
|
|
100
|
+
adaptivePlanner: AdaptivePlanner,
|
|
101
|
+
configManager: Pick<ConfigManager, 'get' | 'getCategory'>,
|
|
102
|
+
): WorkstreamCommandService {
|
|
103
|
+
const drafts = new Map<string, WorkstreamDraft>();
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* fromChainSpec is the SDK's own bridge from "a task string" to a real,
|
|
107
|
+
* launchable engineer -> review CreateWorkstreamInput — the same two-phase
|
|
108
|
+
* shape WrfcController.createChain would otherwise start (see
|
|
109
|
+
* controller-compat.ts). AdaptivePlanner.proposeWorkstream's own
|
|
110
|
+
* PlanProposal is deliberately NOT used for the rendered shape: it always
|
|
111
|
+
* degrades to a fictional single-phase fallback in this wave (nothing yet
|
|
112
|
+
* supplies it a `raw` LLM decomposition — no planning-agent-spawn pipeline
|
|
113
|
+
* exists in the shipped SDK surface this item compiles against), which
|
|
114
|
+
* would silently disagree with what launchDraft actually creates. Showing
|
|
115
|
+
* the real fromChainSpec shape keeps the proposal and the launch
|
|
116
|
+
* byte-for-byte the same plan. proposeWorkstream is still called (below)
|
|
117
|
+
* for its `gate` — the real strategy/reason-code rationale — which stays
|
|
118
|
+
* meaningful even without a raw decomposition.
|
|
119
|
+
*/
|
|
120
|
+
function buildSpec(task: string): CreateWorkstreamInput {
|
|
121
|
+
return fromChainSpec({ id: `item-${crypto.randomUUID().slice(0, 8)}`, task }, configManager);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
engine,
|
|
126
|
+
proposeDraft(task: string): WorkstreamDraft {
|
|
127
|
+
const { gate } = adaptivePlanner.proposeWorkstream(buildPlannerInputs(task));
|
|
128
|
+
const draft: WorkstreamDraft = {
|
|
129
|
+
id: `wsd_${crypto.randomUUID().slice(0, 8)}`,
|
|
130
|
+
task,
|
|
131
|
+
spec: buildSpec(task),
|
|
132
|
+
gate,
|
|
133
|
+
approved: false,
|
|
134
|
+
createdAt: Date.now(),
|
|
135
|
+
};
|
|
136
|
+
drafts.set(draft.id, draft);
|
|
137
|
+
return draft;
|
|
138
|
+
},
|
|
139
|
+
getDraft: (id) => drafts.get(id),
|
|
140
|
+
listDrafts: () => Array.from(drafts.values()).sort((a, b) => a.createdAt - b.createdAt),
|
|
141
|
+
editDraft(id, task) {
|
|
142
|
+
const draft = drafts.get(id);
|
|
143
|
+
if (!draft) return undefined;
|
|
144
|
+
draft.task = task;
|
|
145
|
+
draft.spec = buildSpec(task);
|
|
146
|
+
draft.approved = false;
|
|
147
|
+
return draft;
|
|
148
|
+
},
|
|
149
|
+
approveDraft(id) {
|
|
150
|
+
const draft = drafts.get(id);
|
|
151
|
+
if (!draft) return undefined;
|
|
152
|
+
draft.approved = true;
|
|
153
|
+
return draft;
|
|
154
|
+
},
|
|
155
|
+
removeDraft: (id) => drafts.delete(id),
|
|
156
|
+
launchDraft(id) {
|
|
157
|
+
const draft = drafts.get(id);
|
|
158
|
+
if (!draft || !draft.approved) return null;
|
|
159
|
+
const workstream = engine.createWorkstream(draft.spec);
|
|
160
|
+
engine.start(workstream.id);
|
|
161
|
+
drafts.delete(id);
|
|
162
|
+
return { workstreamId: workstream.id };
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Constructs the TUI's OrchestrationEngine instance and its command-facing
|
|
169
|
+
* facade. `persist` and `createWorktree` are left at the engine's own
|
|
170
|
+
* defaults: journal-backed snapshots under .goodvibes/orchestration/ (so
|
|
171
|
+
* resumeAllFromDisk below has something to resume) and a plain
|
|
172
|
+
* AgentWorktree(projectRoot) — the same "shared working directory, no real
|
|
173
|
+
* per-item isolation" behavior WrfcController itself uses today (see
|
|
174
|
+
* phase-runner.ts's own REALITY-WINS divergence doc in the SDK).
|
|
175
|
+
*/
|
|
176
|
+
export function createWorkstreamServices(deps: WorkstreamServicesDeps): WorkstreamServices {
|
|
177
|
+
const orchestrationEngine = createOrchestrationEngine({
|
|
178
|
+
agentManager: deps.agentManager,
|
|
179
|
+
configManager: deps.configManager,
|
|
180
|
+
runtimeBus: deps.runtimeBus,
|
|
181
|
+
projectRoot: deps.projectRoot,
|
|
182
|
+
priceUsage: (model, usage) => {
|
|
183
|
+
const modelId = model ?? 'unknown';
|
|
184
|
+
if (!isModelPriced(modelId)) return null;
|
|
185
|
+
return calcSessionCost(usage.inputTokens, usage.outputTokens, usage.cacheReadTokens, usage.cacheWriteTokens, modelId);
|
|
186
|
+
},
|
|
187
|
+
});
|
|
188
|
+
// Honest resume: a prior process's still-in-flight workstreams pick back up
|
|
189
|
+
// (and reappear in the fleet tree) instead of silently vanishing on
|
|
190
|
+
// restart. Never throws — persistence.ts guards every read/parse and
|
|
191
|
+
// quarantines an unrecognized snapshot rather than propagating.
|
|
192
|
+
orchestrationEngine.resumeAllFromDisk();
|
|
193
|
+
const workstreamCommands = createWorkstreamCommandService(orchestrationEngine, deps.adaptivePlanner, deps.configManager);
|
|
194
|
+
return { orchestrationEngine, workstreamCommands };
|
|
195
|
+
}
|
|
@@ -4,9 +4,12 @@ import type { SessionSnapshot } from '@/runtime/index.ts';
|
|
|
4
4
|
import type { SystemMessageRouter } from '../core/system-message-router.ts';
|
|
5
5
|
import type { ConversationMessageSnapshot } from '@pellux/goodvibes-sdk/platform/core';
|
|
6
6
|
import { replayJournalForSession } from '../core/session-recovery.ts';
|
|
7
|
+
import { applyHunkKey, buildModifiedEditArgs, type HunkSelectionState } from '../permissions/hunk-selection.ts';
|
|
7
8
|
|
|
8
9
|
export type PendingPermissionState = PermissionRequest & {
|
|
9
|
-
resolve: (approved: boolean, remember?: boolean) => void;
|
|
10
|
+
resolve: (approved: boolean, remember?: boolean, modifiedArgs?: Record<string, unknown>) => void;
|
|
11
|
+
/** Present only when isHunkSelectable(request) was true when the prompt was opened. */
|
|
12
|
+
hunkState?: HunkSelectionState;
|
|
10
13
|
};
|
|
11
14
|
|
|
12
15
|
export type BlockingInputHandlerOptions = {
|
|
@@ -73,6 +76,24 @@ export function handleBlockingShellInput(
|
|
|
73
76
|
|
|
74
77
|
if (pendingPermission) {
|
|
75
78
|
const req = pendingPermission;
|
|
79
|
+
|
|
80
|
+
if (req.hunkState) {
|
|
81
|
+
const { state, commit } = applyHunkKey(req.hunkState, data);
|
|
82
|
+
if (commit === 'apply') {
|
|
83
|
+
req.resolve(true, false, buildModifiedEditArgs(req, state));
|
|
84
|
+
render();
|
|
85
|
+
return { handled: true, pendingPermission: null, recoveryPending };
|
|
86
|
+
}
|
|
87
|
+
if (commit === 'cancel') {
|
|
88
|
+
req.resolve(false, false);
|
|
89
|
+
abortTurn();
|
|
90
|
+
render();
|
|
91
|
+
return { handled: true, pendingPermission: null, recoveryPending };
|
|
92
|
+
}
|
|
93
|
+
render();
|
|
94
|
+
return { handled: true, pendingPermission: { ...req, hunkState: state }, recoveryPending };
|
|
95
|
+
}
|
|
96
|
+
|
|
76
97
|
const key = data.toLowerCase().trim();
|
|
77
98
|
|
|
78
99
|
if (key === 'y') {
|