@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
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,10 +1,9 @@
|
|
|
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';
|
|
5
|
-
import type { PermissionCategory } from '@pellux/goodvibes-sdk/platform/permissions';
|
|
6
6
|
import type { ContentPart } from '@pellux/goodvibes-sdk/platform/providers';
|
|
7
|
-
import type { CommandContext } from './command-registry.ts';
|
|
8
7
|
import type { BookmarkManager } from '@pellux/goodvibes-sdk/platform/bookmarks';
|
|
9
8
|
import { resolveAndValidatePath } from '@pellux/goodvibes-sdk/platform/utils';
|
|
10
9
|
import { logger } from '@pellux/goodvibes-sdk/platform/utils';
|
|
@@ -32,6 +31,11 @@ export const BINARY_IMAGE_MAGIC: {
|
|
|
32
31
|
];
|
|
33
32
|
|
|
34
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 = /[),.;:!?]+$/;
|
|
35
39
|
|
|
36
40
|
export function formatFileSize(bytes: number): string {
|
|
37
41
|
if (bytes < 1024) return `${bytes}B`;
|
|
@@ -48,6 +52,86 @@ export function mediaTypeFromExt(ext: string): string {
|
|
|
48
52
|
}
|
|
49
53
|
}
|
|
50
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
|
+
|
|
51
135
|
export type PasteRegistryState = {
|
|
52
136
|
pasteRegistry: Map<string, string>;
|
|
53
137
|
nextPasteId: number;
|
|
@@ -173,6 +257,8 @@ export function expandPrompt(
|
|
|
173
257
|
}
|
|
174
258
|
}
|
|
175
259
|
|
|
260
|
+
expanded = expandContextReferences(expanded, projectRoot);
|
|
261
|
+
|
|
176
262
|
const imageMarkerRegex = /\[IMAGE: (img\d+), [^\]]+\]/g;
|
|
177
263
|
const imageMarkers: { marker: string; index: number; id: string }[] = [];
|
|
178
264
|
let imgMatch;
|
|
@@ -337,29 +423,6 @@ export function handleBlockToggle(
|
|
|
337
423
|
}
|
|
338
424
|
}
|
|
339
425
|
|
|
340
|
-
export function handleDiffApply(
|
|
341
|
-
conversationManager: ConversationManager | null,
|
|
342
|
-
getScrollTop: () => number,
|
|
343
|
-
commandContext: CommandContext | undefined,
|
|
344
|
-
requestRender: () => void,
|
|
345
|
-
getCallId: () => string,
|
|
346
|
-
category: PermissionCategory,
|
|
347
|
-
): boolean {
|
|
348
|
-
void commandContext;
|
|
349
|
-
void getCallId;
|
|
350
|
-
void category;
|
|
351
|
-
if (!conversationManager) return false;
|
|
352
|
-
const lineIndex = getScrollTop();
|
|
353
|
-
const diff = conversationManager.getDiffAtLine(lineIndex);
|
|
354
|
-
if (!diff || !diff.filePath) return false;
|
|
355
|
-
conversationManager.log(
|
|
356
|
-
`[Diff apply blocked in GoodVibes Agent: ${diff.filePath}. Delegate build/fix work to GoodVibes TUI with /delegate <task>.]`,
|
|
357
|
-
{ fg: '#f59e0b' },
|
|
358
|
-
);
|
|
359
|
-
requestRender();
|
|
360
|
-
return true;
|
|
361
|
-
}
|
|
362
|
-
|
|
363
426
|
export function handleCtrlC(
|
|
364
427
|
prompt: string,
|
|
365
428
|
saveUndoState: () => void,
|
|
@@ -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) {
|
|
@@ -141,7 +141,6 @@ export interface InputFeedContext {
|
|
|
141
141
|
readonly handleBlockCopy: () => void;
|
|
142
142
|
readonly handleBookmark: () => void;
|
|
143
143
|
readonly handleBlockSave: () => void;
|
|
144
|
-
readonly handleDiffApply: () => boolean;
|
|
145
144
|
readonly handleUndo: () => void;
|
|
146
145
|
readonly handleRedo: () => void;
|
|
147
146
|
readonly handlePaste: () => void;
|
|
@@ -149,7 +148,8 @@ export interface InputFeedContext {
|
|
|
149
148
|
readonly ensureInputCursorVisible: (contentWidth?: number) => void;
|
|
150
149
|
readonly registerPaste: (content: string) => string;
|
|
151
150
|
readonly executeBlockAction: (id: string) => void;
|
|
152
|
-
readonly
|
|
151
|
+
readonly cycleAgentWorkspaceCategory: (direction: 'next' | 'prev') => void;
|
|
152
|
+
readonly dismissAgentWorkspace: () => boolean;
|
|
153
153
|
readonly onPanelInputConsumed: (activePanel: Panel | null, key: string) => void;
|
|
154
154
|
readonly getWrappedPromptInfo: (contentWidth: number) => WrappedPromptInfo;
|
|
155
155
|
readonly moveCursorVertical: (direction: -1 | 1) => boolean;
|
|
@@ -272,12 +272,12 @@ export function feedInputTokens(context: InputFeedContext, tokens: readonly Inpu
|
|
|
272
272
|
handleBlockCopy: context.handleBlockCopy,
|
|
273
273
|
handleBookmark: context.handleBookmark,
|
|
274
274
|
handleBlockSave: context.handleBlockSave,
|
|
275
|
-
handleDiffApply: context.handleDiffApply,
|
|
276
275
|
handleUndo: context.handleUndo,
|
|
277
276
|
handleRedo: context.handleRedo,
|
|
278
277
|
handlePaste: context.handlePaste,
|
|
279
278
|
handleEscape: context.handleEscape,
|
|
280
|
-
|
|
279
|
+
cycleAgentWorkspaceCategory: context.cycleAgentWorkspaceCategory,
|
|
280
|
+
dismissAgentWorkspace: context.dismissAgentWorkspace,
|
|
281
281
|
panelManager: context.panelManager,
|
|
282
282
|
keybindingsManager: context.keybindingsManager,
|
|
283
283
|
};
|
|
@@ -297,7 +297,8 @@ export function feedInputTokens(context: InputFeedContext, tokens: readonly Inpu
|
|
|
297
297
|
autocompleteActive: !!context.autocomplete?.isActive,
|
|
298
298
|
requestRender: context.requestRender,
|
|
299
299
|
handlePathCompletion: context.handlePathCompletion,
|
|
300
|
-
|
|
300
|
+
cycleAgentWorkspaceCategory: context.cycleAgentWorkspaceCategory,
|
|
301
|
+
dismissAgentWorkspace: context.dismissAgentWorkspace,
|
|
301
302
|
panelManager: context.panelManager,
|
|
302
303
|
keybindingsManager: context.keybindingsManager,
|
|
303
304
|
onPanelInputConsumed: context.onPanelInputConsumed,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { buildProviderAccountSnapshot } from '
|
|
1
|
+
import { buildProviderAccountSnapshot } from '../panels/provider-account-snapshot.ts';
|
|
2
2
|
import type { OnboardingWizardMode } from './onboarding/onboarding-wizard.ts';
|
|
3
|
-
import { collectOnboardingSnapshot
|
|
4
|
-
import { cleanupMarkerRegistry, expandPrompt, findMarkerAtPos, handleBlockCopy, handleBlockRerun, handleBlockSave, handleBlockToggle, handleBookmark, handleClipboardPaste, handleCopy, handleCtrlC,
|
|
3
|
+
import { collectOnboardingSnapshot } from '../runtime/onboarding/index.ts';
|
|
4
|
+
import { cleanupMarkerRegistry, expandPrompt, findMarkerAtPos, handleBlockCopy, handleBlockRerun, handleBlockSave, handleBlockToggle, handleBookmark, handleClipboardPaste, handleCopy, handleCtrlC, registerPaste } from './handler-content-actions.ts';
|
|
5
5
|
import { clearModalStack, handleEscape, modalOpened } from './handler-modal-stack.ts';
|
|
6
6
|
import { openOnboardingWizardState, type OpenOnboardingWizardOptions } from './handler-ui-state.ts';
|
|
7
7
|
import type { InputHandler } from './handler.ts';
|
|
@@ -11,19 +11,6 @@ export function openOnboardingWizardForHandler(
|
|
|
11
11
|
modeOrOptions: OnboardingWizardMode | OpenOnboardingWizardOptions = 'new',
|
|
12
12
|
): void {
|
|
13
13
|
const options = typeof modeOrOptions === 'string' ? { mode: modeOrOptions } : modeOrOptions;
|
|
14
|
-
const userMarker = readOnboardingCheckMarker(handler.uiServices.environment.shellPaths, 'user');
|
|
15
|
-
if (!userMarker.payload) {
|
|
16
|
-
try {
|
|
17
|
-
writeOnboardingCheckMarker(handler.uiServices.environment.shellPaths, {
|
|
18
|
-
scope: 'user',
|
|
19
|
-
source: 'wizard',
|
|
20
|
-
mode: options.mode ?? 'new',
|
|
21
|
-
});
|
|
22
|
-
} catch (error) {
|
|
23
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
24
|
-
handler.commandContext?.print?.(`Onboarding check marker could not be written: ${message}`);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
14
|
if (!handler.modalStack.includes('onboarding')) handler.modalOpened('onboarding');
|
|
28
15
|
handler.clearOnboardingModelPickerCancelState();
|
|
29
16
|
openOnboardingWizardState(handler.onboardingWizard, options);
|
|
@@ -50,10 +37,12 @@ export async function hydrateOnboardingWizardFromRuntimeForHandler(handler: Inpu
|
|
|
50
37
|
},
|
|
51
38
|
providerAccounts: {
|
|
52
39
|
loadSnapshot: () => buildProviderAccountSnapshot({
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
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
|
+
},
|
|
57
46
|
}),
|
|
58
47
|
},
|
|
59
48
|
});
|
|
@@ -152,7 +141,6 @@ export function executeBlockActionForHandler(handler: InputHandler, actionId: st
|
|
|
152
141
|
case 'copy': handler.handleBlockCopy(); break;
|
|
153
142
|
case 'bookmark': handler.handleBookmark(); break;
|
|
154
143
|
case 'toggle': handler.handleBlockToggle(); break;
|
|
155
|
-
case 'apply': handler.handleDiffApply(); break;
|
|
156
144
|
case 'rerun': handler.handleBlockRerun(); break;
|
|
157
145
|
}
|
|
158
146
|
}
|
|
@@ -172,21 +160,6 @@ export function handleBlockToggleForHandler(handler: InputHandler): void {
|
|
|
172
160
|
handleBlockToggle(handler.conversationManager, handler.getScrollTop, handler.requestRender);
|
|
173
161
|
}
|
|
174
162
|
|
|
175
|
-
/**
|
|
176
|
-
* handleDiffApply - Ctrl+A when a diff block is nearest: request approval and apply the diff.
|
|
177
|
-
* Returns true if a diff was found and applied (so caller can skip default Ctrl+A).
|
|
178
|
-
*/
|
|
179
|
-
export function handleDiffApplyForHandler(handler: InputHandler): boolean {
|
|
180
|
-
return handleDiffApply(
|
|
181
|
-
handler.conversationManager,
|
|
182
|
-
handler.getScrollTop,
|
|
183
|
-
handler.commandContext,
|
|
184
|
-
handler.requestRender,
|
|
185
|
-
() => `diff-apply-${Date.now()}`,
|
|
186
|
-
'write',
|
|
187
|
-
);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
163
|
/**
|
|
191
164
|
* Handle Ctrl+C:
|
|
192
165
|
* - If prompt has text: clear it
|
|
@@ -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';
|