@pellux/goodvibes-agent 0.1.117 → 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 +13 -4
- package/README.md +35 -14
- package/bin/goodvibes-agent.ts +16 -2
- package/dist/package/main.js +176073 -170980
- package/docs/README.md +11 -5
- package/docs/channels-remote-and-api.md +50 -0
- package/docs/connected-host.md +3 -3
- package/docs/getting-started.md +29 -15
- 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 +44 -9
- package/docs/tools-and-commands.md +123 -0
- package/docs/voice-and-live-tts.md +51 -0
- package/package.json +2 -5
- 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-registry.ts +15 -14
- package/src/agent/record-labels.ts +107 -0
- package/src/agent/reminder-schedule-format.ts +33 -24
- package/src/agent/reminder-schedule.ts +26 -25
- package/src/agent/routine-registry.ts +13 -12
- 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 +34 -32
- package/src/agent/routine-schedule-receipts.ts +28 -26
- package/src/agent/runtime-profile-starters.ts +2 -2
- package/src/agent/runtime-profile.ts +18 -17
- package/src/agent/skill-registry.ts +25 -24
- package/src/cli/agent-knowledge-args.ts +5 -1
- package/src/cli/agent-knowledge-command.ts +39 -33
- 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 +13 -8
- package/src/cli/config-overrides.ts +37 -36
- package/src/cli/external-runtime.ts +10 -4
- package/src/cli/help.ts +29 -11
- package/src/cli/local-library-command.ts +134 -68
- package/src/cli/management-commands.ts +98 -62
- package/src/cli/management.ts +52 -26
- package/src/cli/memory-command.ts +66 -32
- package/src/cli/parser.ts +37 -24
- package/src/cli/profiles-command.ts +52 -35
- package/src/cli/provider-auth-routes.ts +2 -1
- package/src/cli/routines-command.ts +44 -36
- package/src/cli/service-posture.ts +6 -6
- package/src/cli/status.ts +46 -121
- package/src/core/conversation-message-snapshot.ts +131 -0
- package/src/input/agent-workspace-activation.ts +33 -7
- package/src/input/agent-workspace-basic-command-editor-submission.ts +7 -3
- package/src/input/agent-workspace-basic-command-editors.ts +30 -10
- package/src/input/agent-workspace-categories.ts +276 -64
- package/src/input/agent-workspace-channel-command-editor-submission.ts +34 -0
- package/src/input/agent-workspace-channel-command-editors.ts +23 -5
- package/src/input/agent-workspace-channels.ts +35 -2
- package/src/input/agent-workspace-command-editor.ts +18 -2
- package/src/input/agent-workspace-config-reader.ts +16 -0
- package/src/input/agent-workspace-delegation-editor-submission.ts +1 -1
- package/src/input/agent-workspace-editors.ts +140 -2
- package/src/input/agent-workspace-knowledge-query-editor.ts +1 -1
- package/src/input/agent-workspace-learned-behavior.ts +2 -2
- package/src/input/agent-workspace-library-command-editor-submission.ts +1 -1
- package/src/input/agent-workspace-library-command-editors.ts +2 -2
- 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-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-editors.ts +1 -1
- package/src/input/agent-workspace-memory-editor.ts +2 -2
- package/src/input/agent-workspace-navigation.ts +38 -2
- package/src/input/agent-workspace-notify-editor-submission.ts +16 -2
- package/src/input/agent-workspace-operations-command-editor-submission.ts +63 -1
- package/src/input/agent-workspace-operations-command-editors.ts +80 -3
- package/src/input/agent-workspace-panel-route.ts +43 -0
- package/src/input/agent-workspace-reminder-schedule-editor.ts +1 -1
- 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-setup.ts +22 -11
- package/src/input/agent-workspace-skill-bundle-command-editor-submission.ts +6 -6
- package/src/input/agent-workspace-skill-bundle-command-editors.ts +10 -10
- package/src/input/agent-workspace-snapshot.ts +112 -13
- package/src/input/agent-workspace-task-command-editors.ts +4 -4
- package/src/input/agent-workspace-token.ts +18 -2
- package/src/input/agent-workspace-types.ts +92 -4
- package/src/input/agent-workspace-voice-media.ts +3 -6
- package/src/input/agent-workspace-web-research-editor.ts +104 -0
- package/src/input/agent-workspace.ts +136 -208
- package/src/input/command-registry.ts +4 -1
- package/src/input/commands/agent-runtime-profile-runtime.ts +45 -41
- package/src/input/commands/agent-skills-runtime.ts +83 -70
- package/src/input/commands/agent-workspace-runtime.ts +23 -7
- package/src/input/commands/brief-runtime.ts +25 -24
- package/src/input/commands/channels-runtime.ts +145 -31
- 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 +140 -115
- package/src/input/commands/knowledge.ts +57 -56
- package/src/input/commands/local-provider-runtime.ts +36 -18
- package/src/input/commands/local-runtime.ts +138 -16
- package/src/input/commands/local-setup-review.ts +7 -7
- package/src/input/commands/mcp-runtime.ts +56 -35
- 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 -17
- package/src/input/commands/personas-runtime.ts +45 -30
- package/src/input/commands/planning-runtime.ts +1 -1
- package/src/input/commands/platform-access-runtime.ts +29 -29
- package/src/input/commands/provider-accounts-runtime.ts +60 -39
- package/src/input/commands/qrcode-runtime.ts +45 -6
- 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 +59 -43
- package/src/input/commands/schedule-runtime.ts +33 -20
- package/src/input/commands/security-runtime.ts +4 -4
- package/src/input/commands/session-content.ts +80 -78
- package/src/input/commands/session-workflow.ts +132 -93
- package/src/input/commands/session.ts +3 -174
- package/src/input/commands/shell-core.ts +32 -17
- package/src/input/commands/subscription-runtime.ts +53 -179
- package/src/input/commands/tasks-runtime.ts +20 -20
- package/src/input/commands/work-plan-runtime.ts +33 -8
- package/src/input/commands.ts +2 -2
- package/src/input/feed-context-factory.ts +2 -1
- 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 -1
- package/src/input/handler-feed-routes.ts +19 -12
- package/src/input/handler-feed.ts +6 -3
- package/src/input/handler-interactions.ts +7 -5
- package/src/input/handler-modal-stack.ts +3 -3
- package/src/input/handler-onboarding.ts +24 -80
- package/src/input/handler-shortcuts.ts +15 -4
- package/src/input/handler.ts +47 -17
- package/src/input/input-history.ts +5 -6
- package/src/input/keybindings.ts +22 -11
- package/src/input/onboarding/onboarding-wizard-apply.ts +13 -0
- package/src/input/onboarding/onboarding-wizard-constants.ts +1 -0
- package/src/input/onboarding/onboarding-wizard-operator-steps.ts +147 -57
- package/src/input/onboarding/onboarding-wizard-steps.ts +46 -29
- package/src/input/onboarding/onboarding-wizard-types.ts +3 -1
- package/src/input/onboarding/onboarding-wizard.ts +68 -0
- package/src/input/profile-picker-modal.ts +31 -12
- package/src/input/session-picker-modal.ts +21 -4
- 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 +6 -52
- package/src/input/submission-intent.ts +0 -1
- package/src/input/submission-router.ts +3 -3
- package/src/main.ts +18 -8
- package/src/panels/approval-panel.ts +8 -8
- package/src/panels/automation-control-panel.ts +2 -2
- package/src/panels/base-panel.ts +1 -1
- package/src/panels/builtin/agent.ts +1 -1
- package/src/panels/builtin/operations.ts +1 -10
- package/src/panels/builtin/session.ts +9 -9
- package/src/panels/builtin/shared.ts +2 -2
- 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 +18 -11
- 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 +45 -4
- package/src/panels/provider-health-panel.ts +5 -4
- package/src/panels/qr-panel.ts +1 -1
- 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 +3 -3
- package/src/panels/system-messages-panel.ts +1 -1
- package/src/panels/tasks-panel.ts +20 -13
- 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 +1 -1
- package/src/provider-auth-route-display.ts +9 -0
- package/src/renderer/agent-workspace-style.ts +34 -0
- package/src/renderer/agent-workspace.ts +228 -52
- package/src/renderer/autocomplete-overlay.ts +25 -6
- 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 +106 -33
- package/src/renderer/history-search-overlay.ts +19 -4
- package/src/renderer/live-tail-modal.ts +27 -5
- package/src/renderer/mcp-workspace.ts +164 -50
- package/src/renderer/model-picker-overlay.ts +58 -2
- package/src/renderer/model-workspace.ts +104 -20
- package/src/renderer/process-modal.ts +27 -6
- package/src/renderer/profile-picker-modal.ts +20 -4
- 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 +83 -50
- package/src/renderer/tool-call.ts +20 -11
- package/src/runtime/agent-runtime-events.ts +6 -6
- package/src/runtime/bootstrap-command-context.ts +7 -1
- package/src/runtime/bootstrap-command-parts.ts +9 -7
- package/src/runtime/bootstrap-core.ts +19 -1
- package/src/runtime/bootstrap-hook-bridge.ts +7 -18
- package/src/runtime/bootstrap-shell.ts +4 -4
- package/src/runtime/bootstrap.ts +31 -22
- package/src/runtime/connected-host-auth.ts +7 -2
- package/src/runtime/diagnostics/panels/index.ts +2 -2
- package/src/runtime/diagnostics/panels/policy.ts +7 -7
- package/src/runtime/index.ts +2 -1
- package/src/runtime/onboarding/apply-file-helpers.ts +66 -0
- package/src/runtime/onboarding/apply.ts +80 -79
- package/src/runtime/onboarding/derivation.ts +5 -8
- package/src/runtime/onboarding/snapshot.ts +0 -15
- package/src/runtime/onboarding/types.ts +8 -19
- package/src/runtime/onboarding/verify.ts +32 -10
- package/src/runtime/operator-token-cleanup.ts +1 -1
- package/src/runtime/services.ts +91 -22
- 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/ui-openers.ts +3 -13
- 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 +269 -69
- 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 +8 -8
- package/src/tools/agent-work-plan-tool.ts +256 -0
- package/src/version.ts +1 -1
- package/src/input/commands/policy-dispatch.ts +0 -339
- package/src/input/commands/policy.ts +0 -13
- 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
package/src/input/commands.ts
CHANGED
|
@@ -38,6 +38,7 @@ import { registerChannelsRuntimeCommands } from './commands/channels-runtime.ts'
|
|
|
38
38
|
import { registerBriefRuntimeCommands } from './commands/brief-runtime.ts';
|
|
39
39
|
import { registerSupportBundleRuntimeCommands } from './commands/support-bundle-runtime.ts';
|
|
40
40
|
import { registerCompatRuntimeCommands } from './commands/compat-runtime.ts';
|
|
41
|
+
import { registerOperatorActionRuntimeCommands } from './commands/operator-actions-runtime.ts';
|
|
41
42
|
|
|
42
43
|
function registerAgentMemoryCommand(registry: CommandRegistry): void {
|
|
43
44
|
registry.register({
|
|
@@ -62,6 +63,7 @@ export function registerBuiltinCommands(registry: CommandRegistry): void {
|
|
|
62
63
|
registerBriefRuntimeCommands(registry);
|
|
63
64
|
registerSupportBundleRuntimeCommands(registry);
|
|
64
65
|
registerCompatRuntimeCommands(registry);
|
|
66
|
+
registerOperatorActionRuntimeCommands(registry);
|
|
65
67
|
registerAgentRuntimeProfileRuntimeCommands(registry);
|
|
66
68
|
registerPersonasRuntimeCommands(registry);
|
|
67
69
|
registerAgentSkillsRuntimeCommands(registry);
|
|
@@ -70,7 +72,6 @@ export function registerBuiltinCommands(registry: CommandRegistry): void {
|
|
|
70
72
|
registerDelegationRuntimeCommands(registry);
|
|
71
73
|
registerConfigCommand(registry);
|
|
72
74
|
registerOperatorRuntimeCommands(registry);
|
|
73
|
-
registry.unregister('profiles');
|
|
74
75
|
registerNotifyRuntimeCommands(registry);
|
|
75
76
|
registerProductRuntimeCommands(registry);
|
|
76
77
|
registerPlatformAccessRuntimeCommands(registry);
|
|
@@ -93,7 +94,6 @@ export function registerBuiltinCommands(registry: CommandRegistry): void {
|
|
|
93
94
|
registerPlanningRuntimeCommands(registry);
|
|
94
95
|
registerScheduleRuntimeCommands(registry);
|
|
95
96
|
registerSessionContentCommands(registry);
|
|
96
|
-
registry.unregister('session-memory');
|
|
97
97
|
registerAgentMemoryCommand(registry);
|
|
98
98
|
|
|
99
99
|
// ── /session ─────────────────────────────────────────────────────────────
|
|
@@ -147,7 +147,8 @@ export interface FeedContextClosures {
|
|
|
147
147
|
ensureInputCursorVisible: (contentWidth?: number) => void;
|
|
148
148
|
registerPaste: (content: string) => string;
|
|
149
149
|
executeBlockAction: (id: string) => void;
|
|
150
|
-
|
|
150
|
+
cycleAgentWorkspaceCategory: (direction: 'next' | 'prev') => void;
|
|
151
|
+
dismissAgentWorkspace: () => boolean;
|
|
151
152
|
onPanelInputConsumed: (activePanel: Panel | null, key: string) => void;
|
|
152
153
|
getWrappedPromptInfo: (contentWidth: number) => WrappedPromptInfo;
|
|
153
154
|
moveCursorVertical: (direction: -1 | 1) => boolean;
|
package/src/input/file-picker.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Dirent } from 'node:fs';
|
|
1
2
|
import { readdir } from 'node:fs/promises';
|
|
2
3
|
import { join, relative } from 'node:path';
|
|
3
4
|
import type { ShellPathService } from '@/runtime/index.ts';
|
|
@@ -160,9 +161,9 @@ export class FilePickerModal {
|
|
|
160
161
|
if (depth > 8) return; // Limit depth
|
|
161
162
|
if (files.length > 5000) return; // Limit total files
|
|
162
163
|
|
|
163
|
-
let entries:
|
|
164
|
+
let entries: Dirent[];
|
|
164
165
|
try {
|
|
165
|
-
entries =
|
|
166
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
166
167
|
} catch {
|
|
167
168
|
return;
|
|
168
169
|
}
|
|
@@ -106,7 +106,7 @@ export function handleCommandModeToken(state: CommandModeRouteState, token: Inpu
|
|
|
106
106
|
if (skillContent) {
|
|
107
107
|
state.commandContext?.submitInput?.(skillContent);
|
|
108
108
|
} else {
|
|
109
|
-
state.conversationManager?.log(`Unknown command
|
|
109
|
+
state.conversationManager?.log(`Unknown command /${name}. Type /help for available commands.`, { fg: '#ef4444' });
|
|
110
110
|
state.requestRender();
|
|
111
111
|
}
|
|
112
112
|
}
|
|
@@ -121,27 +121,24 @@ export function handleCommandModeToken(state: CommandModeRouteState, token: Inpu
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
function withPanelFocusSync(context: CommandContext, state: CommandModeRouteState): CommandContext {
|
|
124
|
-
const panelIsFocusable = (): boolean =>
|
|
125
|
-
state.panelManager.isVisible() && state.panelManager.getAllOpen().length > 0;
|
|
126
|
-
|
|
127
124
|
return {
|
|
128
125
|
...context,
|
|
129
126
|
openPanelPicker: context.openPanelPicker
|
|
130
127
|
? () => {
|
|
131
128
|
context.openPanelPicker?.();
|
|
132
|
-
state.panelFocused =
|
|
129
|
+
state.panelFocused = false;
|
|
133
130
|
}
|
|
134
131
|
: undefined,
|
|
135
132
|
showPanel: context.showPanel
|
|
136
133
|
? (panelId, pane) => {
|
|
137
134
|
context.showPanel?.(panelId, pane);
|
|
138
|
-
state.panelFocused =
|
|
135
|
+
state.panelFocused = false;
|
|
139
136
|
}
|
|
140
137
|
: undefined,
|
|
141
138
|
focusPanels: context.focusPanels
|
|
142
139
|
? () => {
|
|
143
140
|
context.focusPanels?.();
|
|
144
|
-
state.panelFocused =
|
|
141
|
+
state.panelFocused = false;
|
|
145
142
|
}
|
|
146
143
|
: undefined,
|
|
147
144
|
focusPrompt: context.focusPrompt
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { readFileSync,
|
|
1
|
+
import { existsSync, lstatSync, readFileSync, readdirSync } from 'node:fs';
|
|
2
|
+
import { basename, relative } from 'node:path';
|
|
2
3
|
import { copyToClipboard, pasteFromClipboard, pasteImageFromClipboard } from '../utils/clipboard.ts';
|
|
3
4
|
import type { InfiniteBuffer } from '../core/history.ts';
|
|
4
5
|
import type { ConversationManager } from '../core/conversation';
|
|
@@ -30,6 +31,11 @@ export const BINARY_IMAGE_MAGIC: {
|
|
|
30
31
|
];
|
|
31
32
|
|
|
32
33
|
export const IMAGE_EXTENSIONS = ['.png', '.jpg', '.jpeg', '.webp', '.gif'];
|
|
34
|
+
const MAX_CONTEXT_FILE_BYTES = 64 * 1024;
|
|
35
|
+
const MAX_CONTEXT_DIRECTORY_ENTRIES = 200;
|
|
36
|
+
const URL_REFERENCE_REGEX = /^https?:\/\/[^\s]+$/i;
|
|
37
|
+
const CONTEXT_REFERENCE_REGEX = /(^|\s)@([^\s]+)/g;
|
|
38
|
+
const CONTEXT_REFERENCE_TRAILING_PUNCTUATION = /[),.;:!?]+$/;
|
|
33
39
|
|
|
34
40
|
export function formatFileSize(bytes: number): string {
|
|
35
41
|
if (bytes < 1024) return `${bytes}B`;
|
|
@@ -46,6 +52,86 @@ export function mediaTypeFromExt(ext: string): string {
|
|
|
46
52
|
}
|
|
47
53
|
}
|
|
48
54
|
|
|
55
|
+
function stripTrailingReferencePunctuation(value: string): { readonly core: string; readonly suffix: string } {
|
|
56
|
+
const match = CONTEXT_REFERENCE_TRAILING_PUNCTUATION.exec(value);
|
|
57
|
+
if (!match) return { core: value, suffix: '' };
|
|
58
|
+
return {
|
|
59
|
+
core: value.slice(0, -match[0].length),
|
|
60
|
+
suffix: match[0],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function escapeContextAttribute(value: string): string {
|
|
65
|
+
return value
|
|
66
|
+
.replace(/&/g, '&')
|
|
67
|
+
.replace(/"/g, '"')
|
|
68
|
+
.replace(/</g, '<')
|
|
69
|
+
.replace(/>/g, '>');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function readContextFileBlock(reference: string, projectRoot: string): string | null {
|
|
73
|
+
let resolvedPath: string;
|
|
74
|
+
try {
|
|
75
|
+
resolvedPath = resolveAndValidatePath(reference, projectRoot);
|
|
76
|
+
} catch (error) {
|
|
77
|
+
logger.debug('expandPrompt: context reference rejected', { reference, error: summarizeError(error) });
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
if (!existsSync(resolvedPath)) return null;
|
|
81
|
+
|
|
82
|
+
const stat = lstatSync(resolvedPath);
|
|
83
|
+
const label = escapeContextAttribute(relative(projectRoot, resolvedPath) || basename(resolvedPath));
|
|
84
|
+
if (stat.isDirectory()) {
|
|
85
|
+
const entries = readdirSync(resolvedPath, { withFileTypes: true })
|
|
86
|
+
.slice(0, MAX_CONTEXT_DIRECTORY_ENTRIES)
|
|
87
|
+
.map((entry) => `${entry.isDirectory() ? 'dir ' : 'file'} ${entry.name}`)
|
|
88
|
+
.join('\n');
|
|
89
|
+
return [
|
|
90
|
+
`<context-folder path="${label}">`,
|
|
91
|
+
entries || '(empty directory)',
|
|
92
|
+
stat.isDirectory() ? `</context-folder>` : '',
|
|
93
|
+
].filter(Boolean).join('\n');
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (!stat.isFile()) return null;
|
|
97
|
+
if (stat.size > MAX_CONTEXT_FILE_BYTES) {
|
|
98
|
+
return [
|
|
99
|
+
`<context-file path="${label}" truncated="true" bytes="${stat.size}">`,
|
|
100
|
+
readFileSync(resolvedPath, 'utf-8').slice(0, MAX_CONTEXT_FILE_BYTES),
|
|
101
|
+
'</context-file>',
|
|
102
|
+
].join('\n');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return [
|
|
106
|
+
`<context-file path="${label}" bytes="${stat.size}">`,
|
|
107
|
+
readFileSync(resolvedPath, 'utf-8'),
|
|
108
|
+
'</context-file>',
|
|
109
|
+
].join('\n');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function buildContextUrlBlock(reference: string): string {
|
|
113
|
+
const href = escapeContextAttribute(reference);
|
|
114
|
+
return [
|
|
115
|
+
`<context-url href="${href}">`,
|
|
116
|
+
'The user referenced this URL in the prompt. Use connected tools only if content retrieval is needed; do not ingest it into Agent Knowledge unless the user explicitly asks.',
|
|
117
|
+
'</context-url>',
|
|
118
|
+
].join('\n');
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function expandContextReferences(text: string, projectRoot: string): string {
|
|
122
|
+
return text.replace(CONTEXT_REFERENCE_REGEX, (full: string, prefix: string, rawReference: string): string => {
|
|
123
|
+
if (rawReference.startsWith('model:')) return full;
|
|
124
|
+
const { core, suffix } = stripTrailingReferencePunctuation(rawReference);
|
|
125
|
+
if (!core || core.startsWith('@')) return full;
|
|
126
|
+
if (URL_REFERENCE_REGEX.test(core)) {
|
|
127
|
+
return `${prefix}${buildContextUrlBlock(core)}${suffix}`;
|
|
128
|
+
}
|
|
129
|
+
const fileBlock = readContextFileBlock(core, projectRoot);
|
|
130
|
+
if (!fileBlock) return full;
|
|
131
|
+
return `${prefix}${fileBlock}${suffix}`;
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
49
135
|
export type PasteRegistryState = {
|
|
50
136
|
pasteRegistry: Map<string, string>;
|
|
51
137
|
nextPasteId: number;
|
|
@@ -171,6 +257,8 @@ export function expandPrompt(
|
|
|
171
257
|
}
|
|
172
258
|
}
|
|
173
259
|
|
|
260
|
+
expanded = expandContextReferences(expanded, projectRoot);
|
|
261
|
+
|
|
174
262
|
const imageMarkerRegex = /\[IMAGE: (img\d+), [^\]]+\]/g;
|
|
175
263
|
const imageMarkers: { marker: string; index: number; id: string }[] = [];
|
|
176
264
|
let imgMatch;
|
|
@@ -25,7 +25,8 @@ export type PanelFocusRouteState = {
|
|
|
25
25
|
autocompleteActive: boolean;
|
|
26
26
|
requestRender: () => void;
|
|
27
27
|
handlePathCompletion: () => boolean;
|
|
28
|
-
|
|
28
|
+
cycleAgentWorkspaceCategory: (direction: 'next' | 'prev') => void;
|
|
29
|
+
dismissAgentWorkspace: () => boolean;
|
|
29
30
|
onPanelInputConsumed?: (activePanel: import('../panels/types.ts').Panel | null, key: string) => void;
|
|
30
31
|
};
|
|
31
32
|
|
|
@@ -42,16 +43,16 @@ export function handlePanelFocusToken(state: PanelFocusRouteState, token: InputT
|
|
|
42
43
|
!state.searchActive &&
|
|
43
44
|
!state.autocompleteActive
|
|
44
45
|
) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
46
|
+
if (panelFocused) {
|
|
47
|
+
panelFocused = false;
|
|
48
|
+
state.requestRender();
|
|
49
|
+
return { handled: true, panelFocused };
|
|
50
|
+
}
|
|
51
|
+
if (state.handlePathCompletion()) {
|
|
52
52
|
state.requestRender();
|
|
53
53
|
return { handled: true, panelFocused };
|
|
54
54
|
}
|
|
55
|
+
return { handled: false, panelFocused };
|
|
55
56
|
}
|
|
56
57
|
|
|
57
58
|
if (!panelFocused) {
|
|
@@ -76,14 +77,17 @@ export function handlePanelFocusToken(state: PanelFocusRouteState, token: InputT
|
|
|
76
77
|
}
|
|
77
78
|
const kb = state.keybindingsManager;
|
|
78
79
|
if (kb.matches('panel-tab-next', token)) {
|
|
79
|
-
state.
|
|
80
|
-
return { handled: true, panelFocused };
|
|
80
|
+
state.cycleAgentWorkspaceCategory('next');
|
|
81
|
+
return { handled: true, panelFocused: false };
|
|
81
82
|
}
|
|
82
83
|
if (kb.matches('panel-tab-prev', token)) {
|
|
83
|
-
state.
|
|
84
|
-
return { handled: true, panelFocused };
|
|
84
|
+
state.cycleAgentWorkspaceCategory('prev');
|
|
85
|
+
return { handled: true, panelFocused: false };
|
|
85
86
|
}
|
|
86
87
|
if (kb.matches('panel-close-all', token)) {
|
|
88
|
+
if (state.dismissAgentWorkspace()) {
|
|
89
|
+
return { handled: true, panelFocused: false };
|
|
90
|
+
}
|
|
87
91
|
const pm = state.panelManager;
|
|
88
92
|
for (const p of pm.getAllOpen()) pm.close(p.id);
|
|
89
93
|
panelFocused = false;
|
|
@@ -91,6 +95,9 @@ export function handlePanelFocusToken(state: PanelFocusRouteState, token: InputT
|
|
|
91
95
|
return { handled: true, panelFocused };
|
|
92
96
|
}
|
|
93
97
|
if (kb.matches('panel-close', token)) {
|
|
98
|
+
if (state.dismissAgentWorkspace()) {
|
|
99
|
+
return { handled: true, panelFocused: false };
|
|
100
|
+
}
|
|
94
101
|
const pm = state.panelManager;
|
|
95
102
|
const active = pm.getActivePanel();
|
|
96
103
|
if (active) {
|
|
@@ -148,7 +148,8 @@ export interface InputFeedContext {
|
|
|
148
148
|
readonly ensureInputCursorVisible: (contentWidth?: number) => void;
|
|
149
149
|
readonly registerPaste: (content: string) => string;
|
|
150
150
|
readonly executeBlockAction: (id: string) => void;
|
|
151
|
-
readonly
|
|
151
|
+
readonly cycleAgentWorkspaceCategory: (direction: 'next' | 'prev') => void;
|
|
152
|
+
readonly dismissAgentWorkspace: () => boolean;
|
|
152
153
|
readonly onPanelInputConsumed: (activePanel: Panel | null, key: string) => void;
|
|
153
154
|
readonly getWrappedPromptInfo: (contentWidth: number) => WrappedPromptInfo;
|
|
154
155
|
readonly moveCursorVertical: (direction: -1 | 1) => boolean;
|
|
@@ -275,7 +276,8 @@ export function feedInputTokens(context: InputFeedContext, tokens: readonly Inpu
|
|
|
275
276
|
handleRedo: context.handleRedo,
|
|
276
277
|
handlePaste: context.handlePaste,
|
|
277
278
|
handleEscape: context.handleEscape,
|
|
278
|
-
|
|
279
|
+
cycleAgentWorkspaceCategory: context.cycleAgentWorkspaceCategory,
|
|
280
|
+
dismissAgentWorkspace: context.dismissAgentWorkspace,
|
|
279
281
|
panelManager: context.panelManager,
|
|
280
282
|
keybindingsManager: context.keybindingsManager,
|
|
281
283
|
};
|
|
@@ -295,7 +297,8 @@ export function feedInputTokens(context: InputFeedContext, tokens: readonly Inpu
|
|
|
295
297
|
autocompleteActive: !!context.autocomplete?.isActive,
|
|
296
298
|
requestRender: context.requestRender,
|
|
297
299
|
handlePathCompletion: context.handlePathCompletion,
|
|
298
|
-
|
|
300
|
+
cycleAgentWorkspaceCategory: context.cycleAgentWorkspaceCategory,
|
|
301
|
+
dismissAgentWorkspace: context.dismissAgentWorkspace,
|
|
299
302
|
panelManager: context.panelManager,
|
|
300
303
|
keybindingsManager: context.keybindingsManager,
|
|
301
304
|
onPanelInputConsumed: context.onPanelInputConsumed,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { buildProviderAccountSnapshot } from '
|
|
1
|
+
import { buildProviderAccountSnapshot } from '../panels/provider-account-snapshot.ts';
|
|
2
2
|
import type { OnboardingWizardMode } from './onboarding/onboarding-wizard.ts';
|
|
3
3
|
import { collectOnboardingSnapshot } from '../runtime/onboarding/index.ts';
|
|
4
4
|
import { cleanupMarkerRegistry, expandPrompt, findMarkerAtPos, handleBlockCopy, handleBlockRerun, handleBlockSave, handleBlockToggle, handleBookmark, handleClipboardPaste, handleCopy, handleCtrlC, registerPaste } from './handler-content-actions.ts';
|
|
@@ -37,10 +37,12 @@ export async function hydrateOnboardingWizardFromRuntimeForHandler(handler: Inpu
|
|
|
37
37
|
},
|
|
38
38
|
providerAccounts: {
|
|
39
39
|
loadSnapshot: () => buildProviderAccountSnapshot({
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
providerModels: handler.uiServices.providers.providerRegistry,
|
|
41
|
+
services: handler.uiServices.platform.serviceRegistry,
|
|
42
|
+
subscriptions: handler.uiServices.platform.subscriptionManager,
|
|
43
|
+
environment: {
|
|
44
|
+
hasEnvironmentVariable: (name: string) => Boolean(process.env[name]),
|
|
45
|
+
},
|
|
44
46
|
}),
|
|
45
47
|
},
|
|
46
48
|
});
|
|
@@ -8,7 +8,7 @@ import type { SelectionResult } from './selection-modal.ts';
|
|
|
8
8
|
|
|
9
9
|
export type ModalStackState = ActiveModalState & {
|
|
10
10
|
modalStack: string[];
|
|
11
|
-
modalReturnFocus?: 'prompt' | '
|
|
11
|
+
modalReturnFocus?: 'prompt' | 'indicator';
|
|
12
12
|
panelFocused: boolean;
|
|
13
13
|
indicatorFocused: boolean;
|
|
14
14
|
};
|
|
@@ -20,7 +20,7 @@ export function modalOpened(state: ModalStackState, name: string): void {
|
|
|
20
20
|
if (state.modalStack[state.modalStack.length - 1] === name) return;
|
|
21
21
|
if (state.modalStack.includes(name)) return;
|
|
22
22
|
if (state.modalStack.length === 0) {
|
|
23
|
-
state.modalReturnFocus = state.indicatorFocused ? 'indicator' :
|
|
23
|
+
state.modalReturnFocus = state.indicatorFocused ? 'indicator' : 'prompt';
|
|
24
24
|
}
|
|
25
25
|
state.modalStack.push(name);
|
|
26
26
|
}
|
|
@@ -86,7 +86,7 @@ export function handleEscape(state: EscapeState): {
|
|
|
86
86
|
shortcutsOverlayActive,
|
|
87
87
|
commandMode,
|
|
88
88
|
}) !== null) return;
|
|
89
|
-
panelFocused =
|
|
89
|
+
panelFocused = false;
|
|
90
90
|
indicatorFocused = modalReturnFocus === 'indicator';
|
|
91
91
|
modalReturnFocus = 'prompt';
|
|
92
92
|
state.modalReturnFocus = 'prompt';
|
|
@@ -1,8 +1,7 @@
|
|
|
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
6
|
import { applyOnboardingRequest, collectOnboardingSnapshot, verifyOnboardingRequest, writeOnboardingCheckMarker } from '../runtime/onboarding/index.ts';
|
|
8
7
|
import type { OnboardingApplyRequest, OnboardingVerificationItem } from '../runtime/onboarding/index.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;
|
|
@@ -256,7 +266,7 @@ export async function handleOnboardingActionForHandler(handler: InputHandler, ac
|
|
|
256
266
|
}
|
|
257
267
|
if (handler.modalStack.length === 0) {
|
|
258
268
|
const returnFocus = handler.modalReturnFocus;
|
|
259
|
-
handler.panelFocused =
|
|
269
|
+
handler.panelFocused = false;
|
|
260
270
|
handler.indicatorFocused = returnFocus === 'indicator';
|
|
261
271
|
handler.modalReturnFocus = 'prompt';
|
|
262
272
|
}
|
|
@@ -292,10 +302,12 @@ export async function refreshOnboardingHydrationForHandler(handler: InputHandler
|
|
|
292
302
|
},
|
|
293
303
|
providerAccounts: {
|
|
294
304
|
loadSnapshot: () => buildProviderAccountSnapshot({
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
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
|
+
},
|
|
299
311
|
}),
|
|
300
312
|
},
|
|
301
313
|
});
|
|
@@ -317,7 +329,6 @@ export async function refreshOnboardingHydrationForHandler(handler: InputHandler
|
|
|
317
329
|
export async function handleOpenAiSubscriptionStartForHandler(handler: InputHandler): Promise<void> {
|
|
318
330
|
if (handler.onboardingApplyPending) return;
|
|
319
331
|
handler.onboardingApplyPending = true;
|
|
320
|
-
let listener: Awaited<ReturnType<typeof createOAuthLocalListener>> | null = null;
|
|
321
332
|
try {
|
|
322
333
|
const started = await beginOpenAICodexLogin();
|
|
323
334
|
handler.uiServices.platform.subscriptionManager.savePending({
|
|
@@ -327,12 +338,6 @@ export async function handleOpenAiSubscriptionStartForHandler(handler: InputHand
|
|
|
327
338
|
redirectUri: started.redirectUri,
|
|
328
339
|
createdAt: Date.now(),
|
|
329
340
|
});
|
|
330
|
-
listener = await createOAuthLocalListener({
|
|
331
|
-
expectedState: started.state,
|
|
332
|
-
host: '127.0.0.1',
|
|
333
|
-
port: 1455,
|
|
334
|
-
path: '/auth/callback',
|
|
335
|
-
}).catch(() => null);
|
|
336
341
|
const browserOpened = await openExternalUrl(started.authorizationUrl);
|
|
337
342
|
await handler.refreshOnboardingHydration({ preserveValues: true, targetStepId: 'provider-access' });
|
|
338
343
|
handler.onboardingWizard.setFieldValue('providers.openai-authorization-url', started.authorizationUrl);
|
|
@@ -340,31 +345,14 @@ export async function handleOpenAiSubscriptionStartForHandler(handler: InputHand
|
|
|
340
345
|
if (providerIndex >= 0) handler.onboardingWizard.setStep(providerIndex);
|
|
341
346
|
handler.requestRender();
|
|
342
347
|
|
|
343
|
-
if (listener && browserOpened) {
|
|
344
|
-
const serial = ++handler.onboardingOpenAiListenerSerial;
|
|
345
|
-
handler.commandContext?.print?.([
|
|
346
|
-
'OpenAI subscription sign-in started from onboarding.',
|
|
347
|
-
' callback listener: waiting on 127.0.0.1:1455',
|
|
348
|
-
' authorizationUrl: shown in the wizard provider step',
|
|
349
|
-
'You can also paste the callback code or URL into the OpenAI callback field.',
|
|
350
|
-
].join('\n'));
|
|
351
|
-
void handler.completeOpenAiSubscriptionFromListener(listener, started.verifier, serial);
|
|
352
|
-
listener = null;
|
|
353
|
-
handler.requestRender();
|
|
354
|
-
return;
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
listener?.close();
|
|
358
348
|
handler.commandContext?.print?.([
|
|
359
349
|
'OpenAI subscription sign-in started from onboarding.',
|
|
360
350
|
` browser: ${browserOpened ? 'opened' : 'open failed'}`,
|
|
361
|
-
|
|
351
|
+
' completion: paste callback code or URL into the OpenAI callback field',
|
|
362
352
|
' authorizationUrl: shown in the wizard provider step',
|
|
363
|
-
'Paste the callback code or URL into the OpenAI callback field after sign-in.',
|
|
364
353
|
].join('\n'));
|
|
365
354
|
handler.requestRender();
|
|
366
355
|
} catch (error) {
|
|
367
|
-
listener?.close();
|
|
368
356
|
handler.commandContext?.print?.([
|
|
369
357
|
'OpenAI subscription sign-in could not start.',
|
|
370
358
|
` ${error instanceof Error ? error.message : String(error)}`,
|
|
@@ -375,51 +363,6 @@ export async function handleOpenAiSubscriptionStartForHandler(handler: InputHand
|
|
|
375
363
|
}
|
|
376
364
|
}
|
|
377
365
|
|
|
378
|
-
export async function completeOpenAiSubscriptionFromListenerForHandler(
|
|
379
|
-
handler: InputHandler,
|
|
380
|
-
listener: Awaited<ReturnType<typeof createOAuthLocalListener>>,
|
|
381
|
-
verifier: string,
|
|
382
|
-
serial: number,
|
|
383
|
-
): Promise<void> {
|
|
384
|
-
try {
|
|
385
|
-
const callback = await listener.waitForCode();
|
|
386
|
-
const pending = handler.uiServices.platform.subscriptionManager.getPending('openai');
|
|
387
|
-
if (!pending || pending.verifier !== verifier || serial !== handler.onboardingOpenAiListenerSerial) return;
|
|
388
|
-
const token = await exchangeOpenAICodexCode(callback.code, verifier);
|
|
389
|
-
const now = Date.now();
|
|
390
|
-
const existing = handler.uiServices.platform.subscriptionManager.get('openai');
|
|
391
|
-
handler.uiServices.platform.subscriptionManager.saveSubscription({
|
|
392
|
-
provider: 'openai',
|
|
393
|
-
accessToken: token.accessToken,
|
|
394
|
-
refreshToken: token.refreshToken,
|
|
395
|
-
tokenType: token.tokenType,
|
|
396
|
-
expiresAt: token.expiresAt,
|
|
397
|
-
...(token.scopes ? { scopes: token.scopes } : {}),
|
|
398
|
-
authMode: 'oauth',
|
|
399
|
-
overrideAmbientApiKeys: false,
|
|
400
|
-
createdAt: existing?.createdAt ?? now,
|
|
401
|
-
updatedAt: now,
|
|
402
|
-
});
|
|
403
|
-
handler.uiServices.platform.subscriptionManager.clearPending('openai');
|
|
404
|
-
handler.onboardingOpenAiListenerSerial += 1;
|
|
405
|
-
handler.commandContext?.print?.([
|
|
406
|
-
'OpenAI subscription sign-in completed from onboarding.',
|
|
407
|
-
` tokenType: ${token.tokenType}`,
|
|
408
|
-
` expiresAt: ${token.expiresAt ? new Date(token.expiresAt).toISOString() : 'n/a'}`,
|
|
409
|
-
].join('\n'));
|
|
410
|
-
await handler.refreshOnboardingHydration({ preserveValues: true, targetStepId: 'provider-access' });
|
|
411
|
-
} catch (error) {
|
|
412
|
-
handler.commandContext?.print?.([
|
|
413
|
-
'OpenAI subscription listener could not complete automatically.',
|
|
414
|
-
` listener: ${error instanceof Error ? error.message : String(error)}`,
|
|
415
|
-
'Paste the callback code or URL into the OpenAI callback field to finish in onboarding.',
|
|
416
|
-
].join('\n'));
|
|
417
|
-
handler.requestRender();
|
|
418
|
-
} finally {
|
|
419
|
-
listener.close();
|
|
420
|
-
}
|
|
421
|
-
}
|
|
422
|
-
|
|
423
366
|
export async function handleOpenAiSubscriptionFinishForHandler(handler: InputHandler): Promise<void> {
|
|
424
367
|
if (handler.onboardingApplyPending) return;
|
|
425
368
|
const code = extractAuthorizationCode(handler.onboardingWizard.getTextFieldValue('providers.openai-callback-code'));
|
|
@@ -486,12 +429,13 @@ export function syncRuntimeFromOnboardingRequestForHandler(handler: InputHandler
|
|
|
486
429
|
}
|
|
487
430
|
|
|
488
431
|
export function getOnboardingConfigValueForHandler(handler: InputHandler, request: OnboardingApplyRequest, key: string): unknown {
|
|
489
|
-
const
|
|
432
|
+
const configManager: object = handler.uiServices.platform.configManager;
|
|
490
433
|
for (let index = request.operations.length - 1; index >= 0; index -= 1) {
|
|
491
434
|
const operation = request.operations[index];
|
|
492
435
|
if (operation?.kind === 'set-config' && operation.key === key) return operation.value;
|
|
493
436
|
}
|
|
494
|
-
|
|
437
|
+
const get = Reflect.get(configManager, 'get');
|
|
438
|
+
return typeof get === 'function' ? Reflect.apply(get, configManager, [key]) : undefined;
|
|
495
439
|
}
|
|
496
440
|
|
|
497
441
|
export function getOnboardingRuntimePostureForHandler(handler: InputHandler, request: OnboardingApplyRequest): OnboardingRuntimePosture {
|
|
@@ -504,7 +448,7 @@ export function getOnboardingRuntimePostureForHandler(handler: InputHandler, req
|
|
|
504
448
|
export async function restartOnboardingExternalServicesIfNeededForHandler(handler: InputHandler, request: OnboardingApplyRequest): Promise<OnboardingVerificationItem[]> {
|
|
505
449
|
const externalServices = handler.uiServices.platform.externalServices;
|
|
506
450
|
const state = externalServices?.inspect();
|
|
507
|
-
const hostStatus = state?.
|
|
451
|
+
const hostStatus = state?.connectedHostStatus?.reason ?? (state?.connectedHostRunning ? 'connected GoodVibes host appears active' : 'connected GoodVibes host is not verified from this shell');
|
|
508
452
|
return [{
|
|
509
453
|
id: 'runtime:external-host-owned',
|
|
510
454
|
status: 'pass',
|
|
@@ -41,7 +41,8 @@ export type GlobalShortcutRouteState = {
|
|
|
41
41
|
handleRedo: () => void;
|
|
42
42
|
handlePaste: () => void;
|
|
43
43
|
handleEscape: () => void;
|
|
44
|
-
|
|
44
|
+
cycleAgentWorkspaceCategory: (direction: 'next' | 'prev') => void;
|
|
45
|
+
dismissAgentWorkspace: () => boolean;
|
|
45
46
|
};
|
|
46
47
|
|
|
47
48
|
export function handleGlobalShortcutToken(
|
|
@@ -86,6 +87,10 @@ export function handleGlobalShortcutToken(
|
|
|
86
87
|
return true;
|
|
87
88
|
|
|
88
89
|
case 'panel-close-all': {
|
|
90
|
+
if (state.dismissAgentWorkspace()) {
|
|
91
|
+
state.panelFocused = false;
|
|
92
|
+
return true;
|
|
93
|
+
}
|
|
89
94
|
const pm = state.panelManager;
|
|
90
95
|
for (const p of pm.getAllOpen()) pm.close(p.id);
|
|
91
96
|
pm.hide();
|
|
@@ -95,6 +100,10 @@ export function handleGlobalShortcutToken(
|
|
|
95
100
|
}
|
|
96
101
|
|
|
97
102
|
case 'panel-close': {
|
|
103
|
+
if (state.dismissAgentWorkspace()) {
|
|
104
|
+
state.panelFocused = false;
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
98
107
|
const pm = state.panelManager;
|
|
99
108
|
const active = pm.getActivePanel();
|
|
100
109
|
if (active) {
|
|
@@ -107,16 +116,18 @@ export function handleGlobalShortcutToken(
|
|
|
107
116
|
|
|
108
117
|
case 'panel-picker':
|
|
109
118
|
state.commandContext?.openPanelPicker?.();
|
|
110
|
-
state.panelFocused =
|
|
119
|
+
state.panelFocused = false;
|
|
111
120
|
state.requestRender();
|
|
112
121
|
return true;
|
|
113
122
|
|
|
114
123
|
case 'panel-tab-next':
|
|
115
|
-
state.
|
|
124
|
+
state.cycleAgentWorkspaceCategory('next');
|
|
125
|
+
state.panelFocused = false;
|
|
116
126
|
return true;
|
|
117
127
|
|
|
118
128
|
case 'panel-tab-prev':
|
|
119
|
-
state.
|
|
129
|
+
state.cycleAgentWorkspaceCategory('prev');
|
|
130
|
+
state.panelFocused = false;
|
|
120
131
|
return true;
|
|
121
132
|
|
|
122
133
|
case 'history-search':
|