@pellux/goodvibes-agent 0.1.116 → 1.0.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 +48 -661
- package/README.md +64 -57
- package/bin/goodvibes-agent.ts +16 -2
- package/dist/package/main.js +199180 -192185
- package/docs/README.md +15 -8
- package/docs/channels-remote-and-api.md +50 -0
- package/docs/connected-host.md +59 -0
- package/docs/getting-started.md +61 -50
- package/docs/knowledge-artifacts-and-multimodal.md +91 -0
- package/docs/project-planning.md +79 -0
- package/docs/providers-and-routing.md +46 -0
- package/docs/release-and-publishing.md +48 -11
- package/docs/tools-and-commands.md +123 -0
- package/docs/voice-and-live-tts.md +51 -0
- package/package.json +3 -6
- package/src/agent/behavior-discovery-summary.ts +1 -3
- package/src/agent/channel-delivery.ts +201 -0
- package/src/agent/media-generation.ts +159 -0
- package/src/agent/memory-prompt.ts +0 -1
- package/src/agent/note-registry.ts +329 -0
- package/src/agent/operator-actions.ts +343 -0
- package/src/agent/persona-discovery.ts +1 -3
- package/src/agent/persona-registry.ts +19 -16
- package/src/agent/record-labels.ts +107 -0
- package/src/agent/reminder-schedule-format.ts +33 -24
- package/src/agent/reminder-schedule.ts +27 -26
- package/src/agent/routine-registry.ts +54 -14
- package/src/agent/routine-schedule-args.ts +2 -1
- package/src/agent/routine-schedule-format.ts +77 -53
- package/src/agent/routine-schedule-promotion.ts +35 -33
- package/src/agent/routine-schedule-receipts.ts +29 -27
- package/src/agent/runtime-profile-starters.ts +5 -5
- package/src/agent/runtime-profile.ts +91 -12
- package/src/agent/skill-registry.ts +210 -32
- package/src/cli/agent-knowledge-args.ts +5 -1
- package/src/cli/agent-knowledge-command.ts +40 -34
- package/src/cli/agent-knowledge-format.ts +80 -67
- package/src/cli/agent-knowledge-methods.ts +1 -1
- package/src/cli/agent-knowledge-runtime.ts +32 -26
- package/src/cli/bundle-command.ts +14 -9
- package/src/cli/config-overrides.ts +37 -36
- package/src/cli/entrypoint.ts +16 -7
- package/src/cli/external-runtime.ts +10 -4
- package/src/cli/help.ts +54 -29
- package/src/cli/local-library-command.ts +203 -83
- package/src/cli/management-commands.ts +105 -68
- package/src/cli/management.ts +55 -74
- package/src/cli/memory-command.ts +66 -32
- package/src/cli/parser.ts +37 -3
- package/src/cli/profiles-command.ts +166 -31
- package/src/cli/provider-auth-routes.ts +2 -1
- package/src/cli/routines-command.ts +176 -40
- package/src/cli/service-posture.ts +16 -16
- package/src/cli/status.ts +56 -135
- package/src/core/conversation-message-snapshot.ts +131 -0
- package/src/input/agent-workspace-access-command-editor-submission.ts +149 -0
- package/src/input/agent-workspace-access-command-editors.ts +170 -0
- package/src/input/agent-workspace-activation.ts +35 -8
- package/src/input/agent-workspace-basic-command-editor-submission.ts +351 -94
- package/src/input/agent-workspace-basic-command-editors.ts +502 -9
- package/src/input/agent-workspace-categories.ts +423 -51
- package/src/input/agent-workspace-channel-command-editor-submission.ts +83 -0
- package/src/input/agent-workspace-channel-command-editors.ts +65 -0
- package/src/input/agent-workspace-channels.ts +35 -2
- package/src/input/agent-workspace-command-editor.ts +41 -3
- package/src/input/agent-workspace-config-reader.ts +16 -0
- package/src/input/agent-workspace-delegation-editor-submission.ts +55 -0
- package/src/input/agent-workspace-editors.ts +166 -1
- package/src/input/agent-workspace-knowledge-command-editor-submission.ts +132 -0
- package/src/input/agent-workspace-knowledge-command-editors.ts +110 -0
- package/src/input/agent-workspace-knowledge-query-editor.ts +1 -1
- package/src/input/agent-workspace-learned-behavior.ts +67 -0
- package/src/input/agent-workspace-library-command-editor-submission.ts +50 -0
- package/src/input/agent-workspace-library-command-editors.ts +35 -0
- package/src/input/agent-workspace-local-operations.ts +218 -0
- package/src/input/agent-workspace-local-selection.ts +75 -0
- package/src/input/agent-workspace-mcp-command-editor-submission.ts +95 -0
- package/src/input/agent-workspace-media-command-editor-submission.ts +62 -0
- package/src/input/agent-workspace-media-command-editors.ts +27 -0
- package/src/input/agent-workspace-memory-command-editor-submission.ts +232 -0
- package/src/input/agent-workspace-memory-command-editors.ts +180 -0
- package/src/input/agent-workspace-memory-editor.ts +2 -2
- package/src/input/agent-workspace-navigation.ts +81 -0
- package/src/input/agent-workspace-notify-editor-submission.ts +121 -0
- package/src/input/agent-workspace-operations-command-editor-submission.ts +208 -0
- package/src/input/agent-workspace-operations-command-editors.ts +196 -0
- package/src/input/agent-workspace-panel-route.ts +43 -0
- package/src/input/agent-workspace-provider-command-editor-submission.ts +155 -0
- package/src/input/agent-workspace-provider-command-editors.ts +93 -0
- package/src/input/agent-workspace-reminder-schedule-editor.ts +1 -1
- package/src/input/agent-workspace-requirements.ts +11 -0
- package/src/input/agent-workspace-routine-schedule-editor.ts +2 -2
- package/src/input/agent-workspace-search.ts +169 -0
- package/src/input/agent-workspace-secret-editor-submission.ts +153 -0
- package/src/input/agent-workspace-session-command-editor-submission.ts +199 -0
- package/src/input/agent-workspace-session-command-editors.ts +249 -0
- package/src/input/agent-workspace-setup.ts +37 -16
- package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +101 -0
- package/src/input/agent-workspace-skill-bundle-command-editors.ts +110 -0
- package/src/input/agent-workspace-snapshot.ts +162 -21
- package/src/input/agent-workspace-task-command-editor-submission.ts +61 -0
- package/src/input/agent-workspace-task-command-editors.ts +47 -0
- package/src/input/agent-workspace-token.ts +18 -2
- package/src/input/agent-workspace-types.ts +212 -4
- package/src/input/agent-workspace-voice-media.ts +4 -7
- package/src/input/agent-workspace-web-research-editor.ts +104 -0
- package/src/input/agent-workspace-workplan-editor-submission.ts +153 -0
- package/src/input/agent-workspace.ts +178 -240
- package/src/input/command-registry.ts +5 -2
- package/src/input/commands/agent-runtime-profile-runtime.ts +126 -37
- package/src/input/commands/agent-skills-runtime.ts +149 -72
- package/src/input/commands/agent-workspace-runtime.ts +23 -6
- package/src/input/commands/brief-runtime.ts +55 -25
- package/src/input/commands/channels-runtime.ts +147 -33
- package/src/input/commands/compat-runtime.ts +32 -0
- package/src/input/commands/delegation-runtime.ts +29 -23
- package/src/input/commands/experience-runtime.ts +6 -4
- package/src/input/commands/guidance-runtime.ts +4 -4
- package/src/input/commands/health-runtime.ts +149 -126
- package/src/input/commands/knowledge.ts +82 -60
- package/src/input/commands/local-provider-runtime.ts +43 -21
- package/src/input/commands/local-runtime.ts +138 -16
- package/src/input/commands/local-setup-review.ts +10 -20
- package/src/input/commands/mcp-runtime.ts +63 -46
- package/src/input/commands/notify-runtime.ts +38 -9
- package/src/input/commands/operator-actions-runtime.ts +138 -0
- package/src/input/commands/operator-runtime.ts +6 -76
- package/src/input/commands/personas-runtime.ts +46 -31
- package/src/input/commands/planning-runtime.ts +1 -1
- package/src/input/commands/platform-access-runtime.ts +35 -98
- package/src/input/commands/product-runtime.ts +2 -2
- package/src/input/commands/provider-accounts-runtime.ts +60 -39
- package/src/input/commands/qrcode-runtime.ts +50 -9
- package/src/input/commands/recall-bundle.ts +11 -11
- package/src/input/commands/recall-capture.ts +13 -11
- package/src/input/commands/recall-query.ts +29 -21
- package/src/input/commands/recall-review.ts +2 -1
- package/src/input/commands/routines-runtime.ts +99 -45
- package/src/input/commands/runtime-services.ts +1 -14
- package/src/input/commands/schedule-runtime.ts +33 -20
- package/src/input/commands/security-runtime.ts +6 -11
- package/src/input/commands/session-content.ts +80 -78
- package/src/input/commands/session-workflow.ts +134 -104
- package/src/input/commands/session.ts +3 -174
- package/src/input/commands/shell-core.ts +38 -17
- package/src/input/commands/subscription-runtime.ts +54 -185
- package/src/input/commands/support-bundle-runtime.ts +53 -0
- package/src/input/commands/tasks-runtime.ts +21 -21
- package/src/input/commands/work-plan-runtime.ts +33 -8
- package/src/input/commands.ts +6 -2
- package/src/input/feed-context-factory.ts +2 -2
- package/src/input/file-picker.ts +3 -2
- package/src/input/handler-command-route.ts +4 -7
- package/src/input/handler-content-actions.ts +89 -26
- package/src/input/handler-feed-routes.ts +19 -12
- package/src/input/handler-feed.ts +6 -5
- package/src/input/handler-interactions.ts +9 -36
- package/src/input/handler-modal-stack.ts +3 -3
- package/src/input/handler-onboarding.ts +52 -91
- package/src/input/handler-shortcuts.ts +16 -7
- package/src/input/handler.ts +50 -23
- package/src/input/input-history.ts +5 -6
- package/src/input/keybindings.ts +27 -16
- package/src/input/mcp-workspace.ts +90 -26
- package/src/input/onboarding/handler-onboarding-routes.ts +3 -1
- package/src/input/onboarding/onboarding-wizard-apply.ts +62 -0
- package/src/input/onboarding/onboarding-wizard-constants.ts +1 -0
- package/src/input/onboarding/onboarding-wizard-helpers.ts +1 -1
- package/src/input/onboarding/onboarding-wizard-operator-steps.ts +223 -55
- package/src/input/onboarding/onboarding-wizard-steps.ts +59 -35
- package/src/input/onboarding/onboarding-wizard-types.ts +4 -1
- package/src/input/onboarding/onboarding-wizard.ts +87 -2
- package/src/input/profile-picker-modal.ts +31 -12
- package/src/input/session-picker-modal.ts +21 -4
- package/src/input/settings-modal-agent-policy.ts +6 -6
- package/src/input/settings-modal-behavior.ts +0 -3
- package/src/input/settings-modal-subscriptions.ts +3 -3
- package/src/input/settings-modal-types.ts +2 -13
- package/src/input/settings-modal.ts +20 -66
- package/src/input/submission-intent.ts +0 -1
- package/src/input/submission-router.ts +3 -3
- package/src/main.ts +18 -10
- package/src/panels/approval-panel.ts +8 -8
- package/src/panels/automation-control-panel.ts +4 -4
- package/src/panels/base-panel.ts +1 -1
- package/src/panels/builtin/agent.ts +1 -1
- package/src/panels/builtin/operations.ts +3 -12
- package/src/panels/builtin/session.ts +32 -24
- package/src/panels/builtin/shared.ts +7 -7
- package/src/panels/cost-tracker-panel.ts +1 -1
- package/src/panels/docs-panel.ts +5 -3
- package/src/panels/index.ts +0 -1
- package/src/panels/knowledge-panel.ts +6 -5
- package/src/panels/memory-panel.ts +7 -6
- package/src/panels/panel-list-panel.ts +36 -80
- package/src/panels/project-planning-panel.ts +19 -12
- package/src/panels/provider-account-snapshot.ts +51 -25
- package/src/panels/provider-accounts-panel.ts +33 -18
- package/src/panels/provider-health-domains.ts +48 -7
- package/src/panels/provider-health-panel.ts +5 -4
- package/src/panels/qr-panel.ts +44 -20
- package/src/panels/schedule-panel.ts +9 -17
- package/src/panels/security-panel.ts +8 -8
- package/src/panels/session-browser-panel.ts +10 -10
- package/src/panels/subscription-panel.ts +6 -6
- package/src/panels/system-messages-panel.ts +3 -3
- package/src/panels/tasks-panel.ts +21 -14
- package/src/panels/tool-inspector-panel.ts +19 -12
- package/src/panels/work-plan-panel.ts +5 -5
- package/src/planning/project-planning-coordinator.ts +3 -3
- package/src/provider-auth-route-display.ts +9 -0
- package/src/renderer/agent-workspace-style.ts +34 -0
- package/src/renderer/agent-workspace.ts +254 -57
- package/src/renderer/autocomplete-overlay.ts +25 -6
- package/src/renderer/block-actions.ts +1 -3
- package/src/renderer/bookmark-modal.ts +19 -4
- package/src/renderer/buffer.ts +4 -2
- package/src/renderer/context-inspector.ts +50 -13
- package/src/renderer/diff.ts +1 -1
- package/src/renderer/file-picker-overlay.ts +19 -6
- package/src/renderer/help-overlay.ts +112 -34
- package/src/renderer/history-search-overlay.ts +19 -4
- package/src/renderer/live-tail-modal.ts +27 -5
- package/src/renderer/mcp-workspace.ts +176 -43
- package/src/renderer/model-picker-overlay.ts +58 -3
- package/src/renderer/model-workspace.ts +104 -22
- package/src/renderer/onboarding/onboarding-wizard.ts +20 -4
- package/src/renderer/process-modal.ts +27 -6
- package/src/renderer/profile-picker-modal.ts +21 -5
- package/src/renderer/search-overlay.ts +25 -5
- package/src/renderer/selection-modal-overlay.ts +46 -14
- package/src/renderer/session-picker-modal.ts +18 -1
- package/src/renderer/settings-modal-helpers.ts +2 -40
- package/src/renderer/settings-modal.ts +88 -55
- package/src/renderer/system-message.ts +1 -1
- package/src/renderer/tool-call.ts +20 -11
- package/src/runtime/agent-runtime-events.ts +129 -0
- package/src/runtime/bootstrap-command-context.ts +7 -1
- package/src/runtime/bootstrap-command-parts.ts +11 -8
- package/src/runtime/bootstrap-core.ts +23 -65
- package/src/runtime/bootstrap-hook-bridge.ts +7 -18
- package/src/runtime/bootstrap-shell.ts +46 -8
- package/src/runtime/bootstrap.ts +36 -46
- package/src/runtime/connected-host-auth.ts +47 -0
- package/src/runtime/diagnostics/panels/index.ts +2 -2
- package/src/runtime/diagnostics/panels/panel-resources.ts +1 -1
- package/src/runtime/diagnostics/panels/policy.ts +7 -7
- package/src/runtime/index.ts +2 -5
- package/src/runtime/onboarding/apply-file-helpers.ts +66 -0
- package/src/runtime/onboarding/apply.ts +288 -74
- package/src/runtime/onboarding/derivation.ts +10 -13
- package/src/runtime/onboarding/snapshot.ts +2 -17
- package/src/runtime/onboarding/types.ts +34 -20
- package/src/runtime/onboarding/verify.ts +105 -4
- package/src/runtime/operator-token-cleanup.ts +3 -3
- package/src/runtime/services.ts +95 -11
- package/src/runtime/store/selectors/index.ts +3 -3
- package/src/runtime/store/state.ts +1 -4
- package/src/runtime/surface-feature-flags.ts +41 -6
- package/src/runtime/ui-read-models.ts +3 -4
- package/src/runtime/ui-services.ts +6 -6
- package/src/shell/blocking-input.ts +2 -1
- package/src/shell/service-settings-sync.ts +7 -7
- package/src/shell/ui-openers.ts +17 -38
- package/src/tools/agent-analysis-registry-policy.ts +0 -1
- package/src/tools/agent-channel-send-tool.ts +133 -0
- package/src/tools/agent-context-policy.ts +1 -1
- package/src/tools/agent-knowledge-ingest-tool.ts +405 -0
- package/src/tools/agent-knowledge-tool.ts +170 -0
- package/src/tools/agent-local-registry-tool.ts +279 -73
- package/src/tools/agent-media-generate-tool.ts +133 -0
- package/src/tools/agent-notify-tool.ts +143 -0
- package/src/tools/agent-operator-action-tool.ts +137 -0
- package/src/tools/agent-operator-briefing-tool.ts +217 -0
- package/src/tools/agent-reminder-schedule-tool.ts +237 -0
- package/src/tools/agent-tool-policy-guard.ts +13 -15
- package/src/tools/agent-work-plan-tool.ts +256 -0
- package/src/version.ts +1 -1
- package/docs/connected-services.md +0 -51
- package/src/cli/package-verification.ts +0 -274
- package/src/input/commands/policy-dispatch.ts +0 -339
- package/src/input/commands/policy.ts +0 -17
- package/src/panels/panel-picker.ts +0 -105
- package/src/panels/policy-panel.ts +0 -308
- package/src/renderer/panel-picker-overlay.ts +0 -202
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { createOAuthLocalListener } from '@pellux/goodvibes-sdk/platform/config';
|
|
2
1
|
import { beginOpenAICodexLogin, exchangeOpenAICodexCode } from '@pellux/goodvibes-sdk/platform/config';
|
|
3
2
|
import { openExternalUrl } from '@pellux/goodvibes-sdk/platform/utils';
|
|
4
3
|
import { getProviderIdFromModel } from '../config/provider-model.ts';
|
|
5
|
-
import { buildProviderAccountSnapshot } from '
|
|
4
|
+
import { buildProviderAccountSnapshot } from '../panels/provider-account-snapshot.ts';
|
|
6
5
|
import { OnboardingWizardController, type OnboardingWizardAction, type OnboardingWizardApplyFeedback } from './onboarding/onboarding-wizard.ts';
|
|
7
|
-
import { applyOnboardingRequest, collectOnboardingSnapshot, verifyOnboardingRequest } from '../runtime/onboarding/index.ts';
|
|
6
|
+
import { applyOnboardingRequest, collectOnboardingSnapshot, verifyOnboardingRequest, writeOnboardingCheckMarker } from '../runtime/onboarding/index.ts';
|
|
8
7
|
import type { OnboardingApplyRequest, OnboardingVerificationItem } from '../runtime/onboarding/index.ts';
|
|
9
8
|
import type { ModelPickerTarget } from './model-picker.ts';
|
|
10
9
|
import { captureOnboardingWizardSnapshot, restoreOnboardingWizardSnapshot } from './handler-ui-state.ts';
|
|
@@ -156,6 +155,17 @@ export function handleModelPickerCommitForHandler(handler: InputHandler): boolea
|
|
|
156
155
|
}
|
|
157
156
|
|
|
158
157
|
export async function handleOnboardingActionForHandler(handler: InputHandler, action: OnboardingWizardAction): Promise<void> {
|
|
158
|
+
if (action.startsWith('open-agent-workspace:')) {
|
|
159
|
+
const categoryId = action.slice('open-agent-workspace:'.length);
|
|
160
|
+
if (handler.commandContext) handler.openAgentWorkspace(handler.commandContext, categoryId);
|
|
161
|
+
else handler.onboardingWizard.setApplyFeedback({
|
|
162
|
+
severity: 'warning',
|
|
163
|
+
title: 'Workspace unavailable',
|
|
164
|
+
summary: 'The Agent workspace cannot open because the command context is not wired yet.',
|
|
165
|
+
messages: [`Requested workspace: ${categoryId}`],
|
|
166
|
+
});
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
159
169
|
if (action === 'start-openai-subscription') {
|
|
160
170
|
await handler.handleOpenAiSubscriptionStart();
|
|
161
171
|
return;
|
|
@@ -219,7 +229,7 @@ export async function handleOnboardingActionForHandler(handler: InputHandler, ac
|
|
|
219
229
|
showOnboardingApplyFeedbackForHandler(handler, {
|
|
220
230
|
severity: 'error',
|
|
221
231
|
title: 'Apply failed',
|
|
222
|
-
summary: 'The wizard could not persist these settings. No
|
|
232
|
+
summary: 'The wizard could not persist these settings. No connected-host restart was attempted.',
|
|
223
233
|
messages: [error instanceof Error ? error.message : String(error)],
|
|
224
234
|
});
|
|
225
235
|
return;
|
|
@@ -240,17 +250,34 @@ export async function handleOnboardingActionForHandler(handler: InputHandler, ac
|
|
|
240
250
|
|
|
241
251
|
handler.syncRuntimeFromOnboardingRequest(request);
|
|
242
252
|
handler.onboardingWizard.markApplied();
|
|
253
|
+
let markerWarning: string | null = null;
|
|
254
|
+
try {
|
|
255
|
+
writeOnboardingCheckMarker(handler.uiServices.environment.shellPaths, {
|
|
256
|
+
scope: 'user',
|
|
257
|
+
source: 'wizard',
|
|
258
|
+
mode: request.mode,
|
|
259
|
+
});
|
|
260
|
+
} catch (error) {
|
|
261
|
+
markerWarning = error instanceof Error ? error.message : String(error);
|
|
262
|
+
}
|
|
243
263
|
handler.onboardingWizard.close();
|
|
244
264
|
for (let index = handler.modalStack.length - 1; index >= 0; index -= 1) {
|
|
245
265
|
if (handler.modalStack[index] === 'onboarding') handler.modalStack.splice(index, 1);
|
|
246
266
|
}
|
|
247
267
|
if (handler.modalStack.length === 0) {
|
|
248
268
|
const returnFocus = handler.modalReturnFocus;
|
|
249
|
-
handler.panelFocused =
|
|
269
|
+
handler.panelFocused = false;
|
|
250
270
|
handler.indicatorFocused = returnFocus === 'indicator';
|
|
251
271
|
handler.modalReturnFocus = 'prompt';
|
|
252
272
|
}
|
|
253
|
-
|
|
273
|
+
const completionMessage = formatOnboardingApplyCompletionMessage(verificationItems);
|
|
274
|
+
handler.commandContext?.print?.(markerWarning
|
|
275
|
+
? `${completionMessage}\nSetup check marker could not be written: ${markerWarning}`
|
|
276
|
+
: completionMessage);
|
|
277
|
+
if (handler.commandContext) {
|
|
278
|
+
handler.openAgentWorkspace(handler.commandContext, 'setup');
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
254
281
|
handler.requestRender();
|
|
255
282
|
}
|
|
256
283
|
|
|
@@ -275,10 +302,12 @@ export async function refreshOnboardingHydrationForHandler(handler: InputHandler
|
|
|
275
302
|
},
|
|
276
303
|
providerAccounts: {
|
|
277
304
|
loadSnapshot: () => buildProviderAccountSnapshot({
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
305
|
+
providerModels: handler.uiServices.providers.providerRegistry,
|
|
306
|
+
services: handler.uiServices.platform.serviceRegistry,
|
|
307
|
+
subscriptions: handler.uiServices.platform.subscriptionManager,
|
|
308
|
+
environment: {
|
|
309
|
+
hasEnvironmentVariable: (name: string) => Boolean(process.env[name]),
|
|
310
|
+
},
|
|
282
311
|
}),
|
|
283
312
|
},
|
|
284
313
|
});
|
|
@@ -300,7 +329,6 @@ export async function refreshOnboardingHydrationForHandler(handler: InputHandler
|
|
|
300
329
|
export async function handleOpenAiSubscriptionStartForHandler(handler: InputHandler): Promise<void> {
|
|
301
330
|
if (handler.onboardingApplyPending) return;
|
|
302
331
|
handler.onboardingApplyPending = true;
|
|
303
|
-
let listener: Awaited<ReturnType<typeof createOAuthLocalListener>> | null = null;
|
|
304
332
|
try {
|
|
305
333
|
const started = await beginOpenAICodexLogin();
|
|
306
334
|
handler.uiServices.platform.subscriptionManager.savePending({
|
|
@@ -310,12 +338,6 @@ export async function handleOpenAiSubscriptionStartForHandler(handler: InputHand
|
|
|
310
338
|
redirectUri: started.redirectUri,
|
|
311
339
|
createdAt: Date.now(),
|
|
312
340
|
});
|
|
313
|
-
listener = await createOAuthLocalListener({
|
|
314
|
-
expectedState: started.state,
|
|
315
|
-
host: '127.0.0.1',
|
|
316
|
-
port: 1455,
|
|
317
|
-
path: '/auth/callback',
|
|
318
|
-
}).catch(() => null);
|
|
319
341
|
const browserOpened = await openExternalUrl(started.authorizationUrl);
|
|
320
342
|
await handler.refreshOnboardingHydration({ preserveValues: true, targetStepId: 'provider-access' });
|
|
321
343
|
handler.onboardingWizard.setFieldValue('providers.openai-authorization-url', started.authorizationUrl);
|
|
@@ -323,31 +345,14 @@ export async function handleOpenAiSubscriptionStartForHandler(handler: InputHand
|
|
|
323
345
|
if (providerIndex >= 0) handler.onboardingWizard.setStep(providerIndex);
|
|
324
346
|
handler.requestRender();
|
|
325
347
|
|
|
326
|
-
if (listener && browserOpened) {
|
|
327
|
-
const serial = ++handler.onboardingOpenAiListenerSerial;
|
|
328
|
-
handler.commandContext?.print?.([
|
|
329
|
-
'OpenAI subscription sign-in started from onboarding.',
|
|
330
|
-
' callback listener: waiting on 127.0.0.1:1455',
|
|
331
|
-
' authorizationUrl: shown in the wizard provider step',
|
|
332
|
-
'You can also paste the callback code or URL into the OpenAI callback field.',
|
|
333
|
-
].join('\n'));
|
|
334
|
-
void handler.completeOpenAiSubscriptionFromListener(listener, started.verifier, serial);
|
|
335
|
-
listener = null;
|
|
336
|
-
handler.requestRender();
|
|
337
|
-
return;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
listener?.close();
|
|
341
348
|
handler.commandContext?.print?.([
|
|
342
349
|
'OpenAI subscription sign-in started from onboarding.',
|
|
343
350
|
` browser: ${browserOpened ? 'opened' : 'open failed'}`,
|
|
344
|
-
|
|
351
|
+
' completion: paste callback code or URL into the OpenAI callback field',
|
|
345
352
|
' authorizationUrl: shown in the wizard provider step',
|
|
346
|
-
'Paste the callback code or URL into the OpenAI callback field after sign-in.',
|
|
347
353
|
].join('\n'));
|
|
348
354
|
handler.requestRender();
|
|
349
355
|
} catch (error) {
|
|
350
|
-
listener?.close();
|
|
351
356
|
handler.commandContext?.print?.([
|
|
352
357
|
'OpenAI subscription sign-in could not start.',
|
|
353
358
|
` ${error instanceof Error ? error.message : String(error)}`,
|
|
@@ -358,51 +363,6 @@ export async function handleOpenAiSubscriptionStartForHandler(handler: InputHand
|
|
|
358
363
|
}
|
|
359
364
|
}
|
|
360
365
|
|
|
361
|
-
export async function completeOpenAiSubscriptionFromListenerForHandler(
|
|
362
|
-
handler: InputHandler,
|
|
363
|
-
listener: Awaited<ReturnType<typeof createOAuthLocalListener>>,
|
|
364
|
-
verifier: string,
|
|
365
|
-
serial: number,
|
|
366
|
-
): Promise<void> {
|
|
367
|
-
try {
|
|
368
|
-
const callback = await listener.waitForCode();
|
|
369
|
-
const pending = handler.uiServices.platform.subscriptionManager.getPending('openai');
|
|
370
|
-
if (!pending || pending.verifier !== verifier || serial !== handler.onboardingOpenAiListenerSerial) return;
|
|
371
|
-
const token = await exchangeOpenAICodexCode(callback.code, verifier);
|
|
372
|
-
const now = Date.now();
|
|
373
|
-
const existing = handler.uiServices.platform.subscriptionManager.get('openai');
|
|
374
|
-
handler.uiServices.platform.subscriptionManager.saveSubscription({
|
|
375
|
-
provider: 'openai',
|
|
376
|
-
accessToken: token.accessToken,
|
|
377
|
-
refreshToken: token.refreshToken,
|
|
378
|
-
tokenType: token.tokenType,
|
|
379
|
-
expiresAt: token.expiresAt,
|
|
380
|
-
...(token.scopes ? { scopes: token.scopes } : {}),
|
|
381
|
-
authMode: 'oauth',
|
|
382
|
-
overrideAmbientApiKeys: false,
|
|
383
|
-
createdAt: existing?.createdAt ?? now,
|
|
384
|
-
updatedAt: now,
|
|
385
|
-
});
|
|
386
|
-
handler.uiServices.platform.subscriptionManager.clearPending('openai');
|
|
387
|
-
handler.onboardingOpenAiListenerSerial += 1;
|
|
388
|
-
handler.commandContext?.print?.([
|
|
389
|
-
'OpenAI subscription sign-in completed from onboarding.',
|
|
390
|
-
` tokenType: ${token.tokenType}`,
|
|
391
|
-
` expiresAt: ${token.expiresAt ? new Date(token.expiresAt).toISOString() : 'n/a'}`,
|
|
392
|
-
].join('\n'));
|
|
393
|
-
await handler.refreshOnboardingHydration({ preserveValues: true, targetStepId: 'provider-access' });
|
|
394
|
-
} catch (error) {
|
|
395
|
-
handler.commandContext?.print?.([
|
|
396
|
-
'OpenAI subscription listener could not complete automatically.',
|
|
397
|
-
` listener: ${error instanceof Error ? error.message : String(error)}`,
|
|
398
|
-
'Paste the callback code or URL into the OpenAI callback field to finish in onboarding.',
|
|
399
|
-
].join('\n'));
|
|
400
|
-
handler.requestRender();
|
|
401
|
-
} finally {
|
|
402
|
-
listener.close();
|
|
403
|
-
}
|
|
404
|
-
}
|
|
405
|
-
|
|
406
366
|
export async function handleOpenAiSubscriptionFinishForHandler(handler: InputHandler): Promise<void> {
|
|
407
367
|
if (handler.onboardingApplyPending) return;
|
|
408
368
|
const code = extractAuthorizationCode(handler.onboardingWizard.getTextFieldValue('providers.openai-callback-code'));
|
|
@@ -455,7 +415,7 @@ export async function handleOpenAiSubscriptionFinishForHandler(handler: InputHan
|
|
|
455
415
|
}
|
|
456
416
|
|
|
457
417
|
export function syncRuntimeFromOnboardingRequestForHandler(handler: InputHandler, request: ReturnType<OnboardingWizardController['buildApplyRequest']>): void {
|
|
458
|
-
const runtime = handler.commandContext?.session
|
|
418
|
+
const runtime = handler.commandContext?.session?.runtime;
|
|
459
419
|
if (!runtime) return;
|
|
460
420
|
|
|
461
421
|
for (const operation of request.operations) {
|
|
@@ -469,12 +429,13 @@ export function syncRuntimeFromOnboardingRequestForHandler(handler: InputHandler
|
|
|
469
429
|
}
|
|
470
430
|
|
|
471
431
|
export function getOnboardingConfigValueForHandler(handler: InputHandler, request: OnboardingApplyRequest, key: string): unknown {
|
|
472
|
-
const
|
|
432
|
+
const configManager: object = handler.uiServices.platform.configManager;
|
|
473
433
|
for (let index = request.operations.length - 1; index >= 0; index -= 1) {
|
|
474
434
|
const operation = request.operations[index];
|
|
475
435
|
if (operation?.kind === 'set-config' && operation.key === key) return operation.value;
|
|
476
436
|
}
|
|
477
|
-
|
|
437
|
+
const get = Reflect.get(configManager, 'get');
|
|
438
|
+
return typeof get === 'function' ? Reflect.apply(get, configManager, [key]) : undefined;
|
|
478
439
|
}
|
|
479
440
|
|
|
480
441
|
export function getOnboardingRuntimePostureForHandler(handler: InputHandler, request: OnboardingApplyRequest): OnboardingRuntimePosture {
|
|
@@ -487,12 +448,12 @@ export function getOnboardingRuntimePostureForHandler(handler: InputHandler, req
|
|
|
487
448
|
export async function restartOnboardingExternalServicesIfNeededForHandler(handler: InputHandler, request: OnboardingApplyRequest): Promise<OnboardingVerificationItem[]> {
|
|
488
449
|
const externalServices = handler.uiServices.platform.externalServices;
|
|
489
450
|
const state = externalServices?.inspect();
|
|
490
|
-
const
|
|
451
|
+
const hostStatus = state?.connectedHostStatus?.reason ?? (state?.connectedHostRunning ? 'connected GoodVibes host appears active' : 'connected GoodVibes host is not verified from this shell');
|
|
491
452
|
return [{
|
|
492
|
-
id: 'runtime:external-
|
|
453
|
+
id: 'runtime:external-host-owned',
|
|
493
454
|
status: 'pass',
|
|
494
|
-
message: `GoodVibes Agent did not start, stop, restart, or reconfigure connected
|
|
495
|
-
target: '
|
|
455
|
+
message: `GoodVibes Agent did not start, stop, restart, or reconfigure the connected host. ${hostStatus}`,
|
|
456
|
+
target: 'host',
|
|
496
457
|
}];
|
|
497
458
|
}
|
|
498
459
|
|
|
@@ -500,11 +461,11 @@ export function verifyOnboardingRuntimePostureForHandler(handler: InputHandler,
|
|
|
500
461
|
const externalServices = handler.uiServices.platform.externalServices;
|
|
501
462
|
const externalState = externalServices?.inspect();
|
|
502
463
|
return [{
|
|
503
|
-
id: 'runtime:external-
|
|
464
|
+
id: 'runtime:external-host-owned',
|
|
504
465
|
status: 'pass',
|
|
505
466
|
message: externalState
|
|
506
|
-
? '
|
|
507
|
-
: '
|
|
508
|
-
target: '
|
|
467
|
+
? 'The connected GoodVibes host is managed outside Agent; Agent onboarding did not request shutdown, startup, restart, bind, or surface changes.'
|
|
468
|
+
: 'The connected GoodVibes host is managed outside Agent; no local host controller is required for Agent onboarding.',
|
|
469
|
+
target: 'host',
|
|
509
470
|
}];
|
|
510
471
|
}
|
|
@@ -37,12 +37,12 @@ export type GlobalShortcutRouteState = {
|
|
|
37
37
|
handleBlockCopy: () => void;
|
|
38
38
|
handleBookmark: () => void;
|
|
39
39
|
handleBlockSave: () => void;
|
|
40
|
-
handleDiffApply: () => boolean;
|
|
41
40
|
handleUndo: () => void;
|
|
42
41
|
handleRedo: () => void;
|
|
43
42
|
handlePaste: () => void;
|
|
44
43
|
handleEscape: () => void;
|
|
45
|
-
|
|
44
|
+
cycleAgentWorkspaceCategory: (direction: 'next' | 'prev') => void;
|
|
45
|
+
dismissAgentWorkspace: () => boolean;
|
|
46
46
|
};
|
|
47
47
|
|
|
48
48
|
export function handleGlobalShortcutToken(
|
|
@@ -87,6 +87,10 @@ export function handleGlobalShortcutToken(
|
|
|
87
87
|
return true;
|
|
88
88
|
|
|
89
89
|
case 'panel-close-all': {
|
|
90
|
+
if (state.dismissAgentWorkspace()) {
|
|
91
|
+
state.panelFocused = false;
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
90
94
|
const pm = state.panelManager;
|
|
91
95
|
for (const p of pm.getAllOpen()) pm.close(p.id);
|
|
92
96
|
pm.hide();
|
|
@@ -96,6 +100,10 @@ export function handleGlobalShortcutToken(
|
|
|
96
100
|
}
|
|
97
101
|
|
|
98
102
|
case 'panel-close': {
|
|
103
|
+
if (state.dismissAgentWorkspace()) {
|
|
104
|
+
state.panelFocused = false;
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
99
107
|
const pm = state.panelManager;
|
|
100
108
|
const active = pm.getActivePanel();
|
|
101
109
|
if (active) {
|
|
@@ -108,16 +116,18 @@ export function handleGlobalShortcutToken(
|
|
|
108
116
|
|
|
109
117
|
case 'panel-picker':
|
|
110
118
|
state.commandContext?.openPanelPicker?.();
|
|
111
|
-
state.panelFocused =
|
|
119
|
+
state.panelFocused = false;
|
|
112
120
|
state.requestRender();
|
|
113
121
|
return true;
|
|
114
122
|
|
|
115
123
|
case 'panel-tab-next':
|
|
116
|
-
state.
|
|
124
|
+
state.cycleAgentWorkspaceCategory('next');
|
|
125
|
+
state.panelFocused = false;
|
|
117
126
|
return true;
|
|
118
127
|
|
|
119
128
|
case 'panel-tab-prev':
|
|
120
|
-
state.
|
|
129
|
+
state.cycleAgentWorkspaceCategory('prev');
|
|
130
|
+
state.panelFocused = false;
|
|
121
131
|
return true;
|
|
122
132
|
|
|
123
133
|
case 'history-search':
|
|
@@ -154,8 +164,7 @@ export function handleGlobalShortcutToken(
|
|
|
154
164
|
return true;
|
|
155
165
|
}
|
|
156
166
|
|
|
157
|
-
case '
|
|
158
|
-
if (!state.commandMode && state.handleDiffApply()) return true;
|
|
167
|
+
case 'line-start': {
|
|
159
168
|
const info = state.getWrappedPromptInfo(state.contentWidth);
|
|
160
169
|
state.cursorPos = info.wrappedLines.length > 1 ? info.segments[info.cursorWrappedLine].rawStart : 0;
|
|
161
170
|
state.ensureInputCursorVisible();
|
package/src/input/handler.ts
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
import { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { dirname } from 'node:path';
|
|
3
3
|
import { InputTokenizer } from '@pellux/goodvibes-sdk/platform/core';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
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';
|
|
4
|
+
import { clearModalStackForHandler, cleanupMarkerRegistryForHandler, executeBlockActionForHandler, expandPromptForHandler, findMarkerAtPosForHandler, getImageAttachmentsForHandler, handleBlockCopyForHandler, handleBlockRerunForHandler, handleBlockSaveForHandler, handleBlockToggleForHandler, handleBookmarkForHandler, handleCopyForHandler, handleCtrlCForHandler, handleEscapeForHandler, hydrateOnboardingWizardFromRuntimeForHandler, modalOpenedForHandler, openOnboardingWizardForHandler, registerPasteForHandler } from './handler-interactions.ts';
|
|
5
|
+
import { clearOnboardingModelPickerCancelStateForHandler, clearOnboardingPendingModelPickerTargetForHandler, getOnboardingConfigValueForHandler, getOnboardingRuntimePostureForHandler, handleModelPickerCommitForHandler, handleOnboardingActionForHandler, handleOpenAiSubscriptionFinishForHandler, handleOpenAiSubscriptionStartForHandler, openModelPickerWithTargetForHandler, openProviderModelPickerWithTargetForHandler, refreshOnboardingHydrationForHandler, restartOnboardingExternalServicesIfNeededForHandler, restoreOnboardingModelPickerCancelStateForHandler, syncRuntimeFromOnboardingRequestForHandler, verifyOnboardingRuntimePostureForHandler, type OnboardingRuntimePosture } from './handler-onboarding.ts';
|
|
10
6
|
import { SelectionManager } from './selection.ts';
|
|
11
7
|
import type { InfiniteBuffer } from '../core/history.ts';
|
|
12
8
|
import type { CommandRegistry, CommandContext } from './command-registry.ts';
|
|
@@ -56,7 +52,6 @@ import {
|
|
|
56
52
|
handleClipboardPaste,
|
|
57
53
|
handleCopy,
|
|
58
54
|
handleCtrlC,
|
|
59
|
-
handleDiffApply,
|
|
60
55
|
mediaTypeFromExt,
|
|
61
56
|
registerPaste,
|
|
62
57
|
} from './handler-content-actions.ts';
|
|
@@ -164,14 +159,13 @@ export class InputHandler {
|
|
|
164
159
|
public onboardingModelPickerCancelSnapshot: OnboardingWizardSnapshot | null = null;
|
|
165
160
|
public onboardingHydrationSerial = 0;
|
|
166
161
|
public onboardingApplyPending = false;
|
|
167
|
-
public onboardingOpenAiListenerSerial = 0;
|
|
168
162
|
|
|
169
163
|
/**
|
|
170
164
|
* Modal navigation stack. Each element is the name of an open modal.
|
|
171
165
|
* Used to support back-navigation via Escape.
|
|
172
166
|
*/
|
|
173
167
|
public modalStack: string[] = [];
|
|
174
|
-
public modalReturnFocus: 'prompt' | '
|
|
168
|
+
public modalReturnFocus: 'prompt' | 'indicator' = 'prompt';
|
|
175
169
|
public sessionPickerModal: SessionPickerModal;
|
|
176
170
|
public profilePickerModal: ProfilePickerModal;
|
|
177
171
|
/** True when the help overlay is visible. */
|
|
@@ -302,7 +296,6 @@ export class InputHandler {
|
|
|
302
296
|
handleBlockCopy: () => this.handleBlockCopy(),
|
|
303
297
|
handleBookmark: () => this.handleBookmark(),
|
|
304
298
|
handleBlockSave: () => this.handleBlockSave(),
|
|
305
|
-
handleDiffApply: () => this.handleDiffApply(),
|
|
306
299
|
handleUndo: () => { this.handleUndo(); this.syncFeedContextMutableFields(); },
|
|
307
300
|
handleRedo: () => { this.handleRedo(); this.syncFeedContextMutableFields(); },
|
|
308
301
|
handlePaste: () => { this.handlePaste(); this.syncFeedContextMutableFields(); },
|
|
@@ -310,7 +303,8 @@ export class InputHandler {
|
|
|
310
303
|
ensureInputCursorVisible: (contentWidth?: number) => this.ensureInputCursorVisible(contentWidth),
|
|
311
304
|
registerPaste: (content: string) => this.registerPaste(content),
|
|
312
305
|
executeBlockAction: (id: string) => this.executeBlockAction(id),
|
|
313
|
-
|
|
306
|
+
cycleAgentWorkspaceCategory: (direction: 'next' | 'prev') => this.cycleAgentWorkspaceCategory(direction),
|
|
307
|
+
dismissAgentWorkspace: () => this.dismissAgentWorkspace(),
|
|
314
308
|
onPanelInputConsumed: (activePanel: Panel | null, key: string) => this.handlePanelIntegrationAction(activePanel, key),
|
|
315
309
|
getWrappedPromptInfo: (contentWidth: number) => this.getWrappedPromptInfo(contentWidth),
|
|
316
310
|
moveCursorVertical: (direction: -1 | 1) => this.moveCursorVertical(direction),
|
|
@@ -351,7 +345,7 @@ export class InputHandler {
|
|
|
351
345
|
this.autocomplete = new AutocompleteEngine(registry);
|
|
352
346
|
}
|
|
353
347
|
|
|
354
|
-
/** Wire in the conversation manager for block copy/
|
|
348
|
+
/** Wire in the conversation manager for block copy/collapse. */
|
|
355
349
|
public setConversationManager(cm: ConversationManager): void { this.conversationManager = cm; }
|
|
356
350
|
|
|
357
351
|
/**
|
|
@@ -393,7 +387,6 @@ export class InputHandler {
|
|
|
393
387
|
public executeBlockAction(actionId: string): void { executeBlockActionForHandler(this, actionId); }
|
|
394
388
|
public handleBlockRerun(): void { handleBlockRerunForHandler(this); }
|
|
395
389
|
public handleBlockToggle(): void { handleBlockToggleForHandler(this); }
|
|
396
|
-
public handleDiffApply(): boolean { return handleDiffApplyForHandler(this); }
|
|
397
390
|
public handleCtrlC(): void { handleCtrlCForHandler(this); }
|
|
398
391
|
public modalOpened(name: string): void { modalOpenedForHandler(this, name); }
|
|
399
392
|
public clearModalStack(): void { clearModalStackForHandler(this); }
|
|
@@ -411,19 +404,37 @@ export class InputHandler {
|
|
|
411
404
|
this.mcpWorkspace.open(context);
|
|
412
405
|
this.requestRender();
|
|
413
406
|
}
|
|
414
|
-
public openAgentWorkspace(context: CommandContext): void {
|
|
407
|
+
public openAgentWorkspace(context: CommandContext, categoryId?: string): void {
|
|
415
408
|
this.panelFocused = false;
|
|
416
409
|
this.indicatorFocused = false;
|
|
417
410
|
this.modalOpened('agentWorkspace');
|
|
418
|
-
this.agentWorkspace.open(
|
|
411
|
+
this.agentWorkspace.open(
|
|
412
|
+
context,
|
|
413
|
+
(command) => this.dispatchAgentWorkspaceCommand(command, context),
|
|
414
|
+
categoryId,
|
|
415
|
+
(prompt) => this.dispatchAgentWorkspacePrompt(prompt, context),
|
|
416
|
+
);
|
|
419
417
|
this.requestRender();
|
|
420
418
|
}
|
|
421
419
|
|
|
422
|
-
private
|
|
420
|
+
private closeAgentWorkspaceModal(): void {
|
|
423
421
|
this.agentWorkspace.close();
|
|
424
422
|
for (let index = this.modalStack.length - 1; index >= 0; index -= 1) {
|
|
425
423
|
if (this.modalStack[index] === 'agentWorkspace') this.modalStack.splice(index, 1);
|
|
426
424
|
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
public dismissAgentWorkspace(): boolean {
|
|
428
|
+
if (!this.agentWorkspace.active) return false;
|
|
429
|
+
this.closeAgentWorkspaceModal();
|
|
430
|
+
this.panelFocused = false;
|
|
431
|
+
this.indicatorFocused = false;
|
|
432
|
+
this.requestRender();
|
|
433
|
+
return true;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
private dispatchAgentWorkspaceCommand(command: string, context: CommandContext): void {
|
|
437
|
+
this.closeAgentWorkspaceModal();
|
|
427
438
|
const { name, args } = parseSlashCommand(command);
|
|
428
439
|
if (!name) return;
|
|
429
440
|
void context.executeCommand?.(name, [...args]).catch((error: unknown) => {
|
|
@@ -432,11 +443,16 @@ export class InputHandler {
|
|
|
432
443
|
});
|
|
433
444
|
this.requestRender();
|
|
434
445
|
}
|
|
446
|
+
|
|
447
|
+
private dispatchAgentWorkspacePrompt(prompt: string, context: CommandContext): void {
|
|
448
|
+
this.closeAgentWorkspaceModal();
|
|
449
|
+
context.submitInput?.(prompt);
|
|
450
|
+
this.requestRender();
|
|
451
|
+
}
|
|
435
452
|
public handleModelPickerCommit(): boolean { return handleModelPickerCommitForHandler(this); }
|
|
436
453
|
public async handleOnboardingAction(action: OnboardingWizardAction): Promise<void> { await handleOnboardingActionForHandler(this, action); }
|
|
437
454
|
public async refreshOnboardingHydration(options: { readonly preserveValues?: boolean; readonly targetStepId?: string } = {}): Promise<void> { await refreshOnboardingHydrationForHandler(this, options); }
|
|
438
455
|
public async handleOpenAiSubscriptionStart(): Promise<void> { await handleOpenAiSubscriptionStartForHandler(this); }
|
|
439
|
-
public async completeOpenAiSubscriptionFromListener(listener: Awaited<ReturnType<typeof createOAuthLocalListener>>, verifier: string, serial: number): Promise<void> { await completeOpenAiSubscriptionFromListenerForHandler(this, listener, verifier, serial); }
|
|
440
456
|
public async handleOpenAiSubscriptionFinish(): Promise<void> { await handleOpenAiSubscriptionFinishForHandler(this); }
|
|
441
457
|
public syncRuntimeFromOnboardingRequest(request: ReturnType<OnboardingWizardController['buildApplyRequest']>): void { syncRuntimeFromOnboardingRequestForHandler(this, request); }
|
|
442
458
|
public getOnboardingConfigValue(request: OnboardingApplyRequest, key: string): unknown { return getOnboardingConfigValueForHandler(this, request, key); }
|
|
@@ -696,13 +712,24 @@ export class InputHandler {
|
|
|
696
712
|
* Word-wrap a single line to fit within maxW columns.
|
|
697
713
|
* Breaks at spaces; words wider than maxW are force-broken.
|
|
698
714
|
*/
|
|
699
|
-
public
|
|
700
|
-
const
|
|
701
|
-
if (
|
|
702
|
-
if (
|
|
703
|
-
|
|
704
|
-
this.
|
|
715
|
+
public cycleAgentWorkspaceCategory(direction: 'next' | 'prev'): void {
|
|
716
|
+
const context = this.commandContext;
|
|
717
|
+
if (!this.agentWorkspace.active) {
|
|
718
|
+
if (!context) return;
|
|
719
|
+
this.panelFocused = false;
|
|
720
|
+
this.indicatorFocused = false;
|
|
721
|
+
this.modalOpened('agentWorkspace');
|
|
722
|
+
this.agentWorkspace.open(
|
|
723
|
+
context,
|
|
724
|
+
(command) => this.dispatchAgentWorkspaceCommand(command, context),
|
|
725
|
+
undefined,
|
|
726
|
+
(prompt) => this.dispatchAgentWorkspacePrompt(prompt, context),
|
|
727
|
+
);
|
|
705
728
|
}
|
|
729
|
+
this.agentWorkspace.cycleCategory(direction);
|
|
730
|
+
this.panelFocused = false;
|
|
731
|
+
this.indicatorFocused = false;
|
|
732
|
+
this.requestRender();
|
|
706
733
|
}
|
|
707
734
|
|
|
708
735
|
public handlePanelIntegrationAction(activePanel: Panel | null, key: string): void {
|
|
@@ -284,13 +284,12 @@ export class InputHistory {
|
|
|
284
284
|
|
|
285
285
|
private normalizeStoredEntry(entry: unknown): StoredInputHistoryEntry | null {
|
|
286
286
|
if (typeof entry === 'string') return entry;
|
|
287
|
-
if (!entry || typeof entry !== 'object') return null;
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
const text = record.text.trim();
|
|
287
|
+
if (!entry || typeof entry !== 'object' || Array.isArray(entry)) return null;
|
|
288
|
+
if (!('text' in entry) || typeof entry.text !== 'string') return null;
|
|
289
|
+
const text = entry.text.trim();
|
|
291
290
|
if (!text) return null;
|
|
292
|
-
if (typeof
|
|
293
|
-
return { text, recallText:
|
|
291
|
+
if ('recallText' in entry && typeof entry.recallText === 'string' && entry.recallText.trim() && entry.recallText.trim() !== text) {
|
|
292
|
+
return { text, recallText: entry.recallText.trim() };
|
|
294
293
|
}
|
|
295
294
|
return text;
|
|
296
295
|
}
|
package/src/input/keybindings.ts
CHANGED
|
@@ -45,7 +45,7 @@ export type KeyAction =
|
|
|
45
45
|
| 'bookmark'
|
|
46
46
|
| 'block-save'
|
|
47
47
|
| 'delete-word'
|
|
48
|
-
| '
|
|
48
|
+
| 'line-start'
|
|
49
49
|
| 'next-error-line-end'
|
|
50
50
|
| 'kill-line'
|
|
51
51
|
| 'clear-prompt'
|
|
@@ -59,27 +59,40 @@ export const ACTION_DESCRIPTIONS: Record<KeyAction, string> = {
|
|
|
59
59
|
'copy-selection': 'Copy selected text to clipboard',
|
|
60
60
|
'clear-cancel': 'Clear input / cancel generation / exit (double)',
|
|
61
61
|
'screen-clear': 'Repaint the screen',
|
|
62
|
-
'panel-picker': 'Open
|
|
63
|
-
'panel-close': '
|
|
64
|
-
'panel-close-all': '
|
|
65
|
-
'panel-tab-next': '
|
|
66
|
-
'panel-tab-prev': '
|
|
62
|
+
'panel-picker': 'Open the Agent operator workspace',
|
|
63
|
+
'panel-close': 'Dismiss Agent workspace',
|
|
64
|
+
'panel-close-all': 'Dismiss Agent workspace focus',
|
|
65
|
+
'panel-tab-next': 'Cycle Agent workspace category forward',
|
|
66
|
+
'panel-tab-prev': 'Cycle Agent workspace category backward',
|
|
67
67
|
'history-search': 'Reverse input history search',
|
|
68
68
|
'search': 'Toggle conversation search',
|
|
69
69
|
'block-copy': 'Copy nearest block to clipboard',
|
|
70
70
|
'bookmark': 'Bookmark / unbookmark nearest block',
|
|
71
71
|
'block-save': 'Block file save disabled; copy block or export conversation',
|
|
72
72
|
'delete-word': 'Delete word backward',
|
|
73
|
-
'
|
|
73
|
+
'line-start': 'Move to start of line',
|
|
74
74
|
'next-error-line-end': 'Navigate to next error / move to line end',
|
|
75
75
|
'kill-line': 'Kill to end of line',
|
|
76
76
|
'clear-prompt': 'Clear the prompt',
|
|
77
77
|
'undo': 'Undo last prompt edit',
|
|
78
78
|
'redo': 'Redo last undone edit',
|
|
79
79
|
'paste': 'Paste from clipboard (image priority)',
|
|
80
|
-
'replay-panel': '
|
|
80
|
+
'replay-panel': 'Reserved replay workspace shortcut',
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
+
function isKeyAction(action: string): action is KeyAction {
|
|
84
|
+
return Object.hasOwn(ACTION_DESCRIPTIONS, action);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function isKeyCombo(value: unknown): value is KeyCombo {
|
|
88
|
+
if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
|
|
89
|
+
if (!('key' in value) || typeof value.key !== 'string' || value.key.length === 0) return false;
|
|
90
|
+
if ('ctrl' in value && value.ctrl !== undefined && typeof value.ctrl !== 'boolean') return false;
|
|
91
|
+
if ('shift' in value && value.shift !== undefined && typeof value.shift !== 'boolean') return false;
|
|
92
|
+
if ('alt' in value && value.alt !== undefined && typeof value.alt !== 'boolean') return false;
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
|
|
83
96
|
/** Default key bindings for all actions. */
|
|
84
97
|
export const DEFAULT_KEYBINDINGS: Record<KeyAction, KeyCombo[]> = {
|
|
85
98
|
'copy-selection': [{ key: 'c', ctrl: true, shift: true }],
|
|
@@ -96,7 +109,7 @@ export const DEFAULT_KEYBINDINGS: Record<KeyAction, KeyCombo[]> = {
|
|
|
96
109
|
'bookmark': [{ key: 'b', ctrl: true }],
|
|
97
110
|
'block-save': [{ key: 's', ctrl: true }],
|
|
98
111
|
'delete-word': [{ key: 'w', ctrl: true }],
|
|
99
|
-
'
|
|
112
|
+
'line-start': [{ key: 'a', ctrl: true }],
|
|
100
113
|
'next-error-line-end': [{ key: 'e', ctrl: true }],
|
|
101
114
|
'kill-line': [{ key: 'k', ctrl: true }],
|
|
102
115
|
'clear-prompt': [{ key: 'u', ctrl: true }],
|
|
@@ -218,11 +231,7 @@ export class KeybindingsManager {
|
|
|
218
231
|
}
|
|
219
232
|
|
|
220
233
|
private validateCombos(combos: unknown[]): combos is KeyCombo[] {
|
|
221
|
-
return combos.every(
|
|
222
|
-
if (typeof c !== 'object' || c === null) return false;
|
|
223
|
-
const combo = c as Record<string, unknown>;
|
|
224
|
-
return typeof combo['key'] === 'string' && combo['key'].length > 0;
|
|
225
|
-
});
|
|
234
|
+
return combos.every(isKeyCombo);
|
|
226
235
|
}
|
|
227
236
|
|
|
228
237
|
/**
|
|
@@ -233,9 +242,10 @@ export class KeybindingsManager {
|
|
|
233
242
|
* Expects: { logicalName: string; ctrl?: boolean; shift?: boolean; alt?: boolean }
|
|
234
243
|
*/
|
|
235
244
|
matches(
|
|
236
|
-
action:
|
|
245
|
+
action: string,
|
|
237
246
|
token: { logicalName?: string; ctrl?: boolean; shift?: boolean; alt?: boolean },
|
|
238
247
|
): boolean {
|
|
248
|
+
if (!isKeyAction(action)) return false;
|
|
239
249
|
const combos = this.bindings[action];
|
|
240
250
|
if (!combos) return false;
|
|
241
251
|
return combos.some((combo) => this.comboMatches(combo, token));
|
|
@@ -267,7 +277,8 @@ export class KeybindingsManager {
|
|
|
267
277
|
* getComboLabel — Return a human-readable label for the first combo of an action.
|
|
268
278
|
* Example: { key: 'f', ctrl: true } → "Ctrl+F"
|
|
269
279
|
*/
|
|
270
|
-
getComboLabel(action:
|
|
280
|
+
getComboLabel(action: string): string {
|
|
281
|
+
if (!isKeyAction(action)) return '(unbound)';
|
|
271
282
|
const combos = this.bindings[action];
|
|
272
283
|
if (!combos?.length) return '(unbound)';
|
|
273
284
|
return this.formatCombo(combos[0]);
|