@pellux/goodvibes-agent 1.4.3 → 1.5.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 +24 -0
- package/README.md +7 -7
- package/dist/package/main.js +7450 -12285
- package/docs/README.md +2 -2
- package/docs/channels-remote-and-api.md +1 -1
- package/docs/getting-started.md +2 -2
- package/docs/release-and-publishing.md +1 -1
- package/docs/tools-and-commands.md +5 -5
- package/package.json +4 -2
- package/release/performance-snapshot.json +2 -2
- package/release/release-notes.md +11 -7
- package/release/release-readiness.json +6 -6
- package/src/agent/behavior-discovery-summary.ts +4 -18
- package/src/agent/calendar-registry.ts +322 -0
- package/src/agent/competitive-feature-inventory.ts +268 -130
- package/src/agent/document-registry.ts +5 -1
- package/src/agent/email/email-service.ts +350 -0
- package/src/agent/email/imap-client.ts +596 -0
- package/src/agent/email/smtp-client.ts +453 -0
- package/src/agent/ics-calendar.ts +662 -0
- package/src/agent/ics-timezone.ts +172 -0
- package/src/agent/markdown-frontmatter.ts +31 -0
- package/src/agent/memory-safety.ts +1 -1
- package/src/agent/note-registry.ts +3 -9
- package/src/agent/persona-discovery.ts +3 -15
- package/src/agent/persona-registry.ts +1 -10
- package/src/agent/research-source-registry.ts +5 -1
- package/src/agent/routine-discovery.ts +3 -15
- package/src/agent/runtime-profile.ts +3 -0
- package/src/agent/skill-discovery.ts +3 -15
- package/src/agent/skill-draft-proposer.ts +203 -0
- package/src/agent/skill-draft-runner.ts +201 -0
- package/src/agent/skill-registry.ts +36 -1
- package/src/agent/skill-standard.ts +99 -0
- package/src/agent/vibe-file.ts +7 -22
- package/src/cli/completion.ts +1 -1
- package/src/cli/config-overrides.ts +10 -1
- package/src/cli/redaction.ts +17 -5
- package/src/config/provider-model.ts +2 -1
- package/src/config/secret-config.ts +13 -6
- package/src/core/activity-feed.ts +97 -0
- package/src/core/away-digest.ts +161 -0
- package/src/core/conversation-rendering.ts +7 -3
- package/src/core/conversation.ts +22 -15
- package/src/core/hardware-profile.ts +362 -0
- package/src/core/last-seen-store.ts +78 -0
- package/src/core/plain-language.ts +52 -0
- package/src/core/setup-incomplete-hint.ts +90 -0
- package/src/core/system-message-router.ts +38 -87
- package/src/input/agent-workspace-basic-command-editor-submission.ts +60 -220
- package/src/input/agent-workspace-basic-command-editors.ts +39 -141
- package/src/input/agent-workspace-categories.ts +63 -158
- package/src/input/agent-workspace-command-editor.ts +4 -0
- package/src/input/agent-workspace-host-category.ts +0 -5
- package/src/input/agent-workspace-local-editor-submission.ts +3 -1
- package/src/input/agent-workspace-navigation.ts +10 -3
- package/src/input/agent-workspace-onboarding-actions.ts +132 -0
- package/src/input/agent-workspace-onboarding-categories.ts +29 -26
- package/src/input/agent-workspace-onboarding-finish.ts +11 -4
- package/src/input/agent-workspace-onboarding-state.ts +111 -0
- package/src/input/agent-workspace-profile-editor-submission.ts +260 -0
- package/src/input/agent-workspace-profile-editors.ts +155 -0
- package/src/input/agent-workspace-subscription-editor.ts +7 -0
- package/src/input/agent-workspace-types.ts +5 -1
- package/src/input/agent-workspace.ts +65 -39
- package/src/input/command-registry.ts +18 -5
- package/src/input/commands/agent-runtime-profile-runtime.ts +2 -1
- package/src/input/commands/agent-skills-runtime.ts +60 -3
- package/src/input/commands/calendar-runtime.ts +209 -0
- package/src/input/commands/channels-runtime.ts +1 -0
- package/src/input/commands/command-error.ts +9 -0
- package/src/input/commands/compat-runtime.ts +1 -0
- package/src/input/commands/config.ts +1 -0
- package/src/input/commands/conversation-runtime.ts +1 -1
- package/src/input/commands/delegation-runtime.ts +5 -6
- package/src/input/commands/email-runtime.ts +387 -0
- package/src/input/commands/experience-runtime.ts +17 -4
- package/src/input/commands/guidance-runtime.ts +1 -1
- package/src/input/commands/health-runtime.ts +6 -1
- package/src/input/commands/knowledge-format.ts +73 -0
- package/src/input/commands/knowledge.ts +9 -74
- package/src/input/commands/local-provider-runtime.ts +2 -1
- package/src/input/commands/local-runtime.ts +10 -4
- package/src/input/commands/mcp-runtime.ts +7 -0
- package/src/input/commands/notify-runtime.ts +17 -1
- package/src/input/commands/onboarding-runtime.ts +1 -0
- package/src/input/commands/operator-actions-runtime.ts +1 -0
- package/src/input/commands/operator-runtime.ts +3 -0
- package/src/input/commands/personas-runtime.ts +1 -0
- package/src/input/commands/platform-access-runtime.ts +40 -17
- package/src/input/commands/product-runtime.ts +6 -1
- package/src/input/commands/provider-accounts-runtime.ts +3 -2
- package/src/input/commands/qrcode-runtime.ts +1 -0
- package/src/input/commands/routines-runtime.ts +1 -0
- package/src/input/commands/runtime-services.ts +0 -13
- package/src/input/commands/security-runtime.ts +1 -0
- package/src/input/commands/session-content.ts +1 -0
- package/src/input/commands/shell-core.ts +5 -2
- package/src/input/commands/subscription-runtime.ts +33 -9
- package/src/input/commands/support-bundle-runtime.ts +8 -1
- package/src/input/commands/tasks-runtime.ts +1 -0
- package/src/input/commands/tts-runtime.ts +1 -0
- package/src/input/commands/vibe-runtime.ts +1 -0
- package/src/input/commands.ts +4 -0
- package/src/input/feed-context-factory.ts +3 -12
- package/src/input/handler-command-route.ts +7 -60
- package/src/input/handler-feed-routes.ts +0 -194
- package/src/input/handler-feed.ts +2 -54
- package/src/input/handler-interactions.ts +0 -2
- package/src/input/handler-modal-stack.ts +0 -9
- package/src/input/handler-picker-routes.ts +24 -1
- package/src/input/handler-shortcuts.ts +11 -40
- package/src/input/handler-ui-state.ts +13 -0
- package/src/input/handler.ts +8 -35
- package/src/input/keybindings.ts +40 -17
- package/src/input/model-picker-local-fit.ts +130 -0
- package/src/input/submission-router.ts +0 -5
- package/src/main.ts +111 -89
- package/src/renderer/activity-sidebar.ts +186 -0
- package/src/renderer/agent-workspace-context-lines.ts +5 -48
- package/src/renderer/agent-workspace-style.ts +1 -1
- package/src/renderer/agent-workspace.ts +14 -2
- package/src/renderer/compositor.ts +37 -125
- package/src/renderer/conversation-overlays.ts +3 -3
- package/src/renderer/help-overlay.ts +7 -5
- package/src/renderer/model-workspace.ts +101 -86
- package/src/{panels → renderer}/polish.ts +3 -3
- package/src/renderer/shell-surface.ts +4 -5
- package/src/renderer/status-token.ts +31 -11
- package/src/renderer/tab-strip.ts +1 -1
- package/src/renderer/tool-call.ts +7 -8
- package/src/renderer/tool-labels.ts +92 -0
- package/src/renderer/ui-factory.ts +48 -96
- package/src/runtime/bootstrap-command-context.ts +0 -5
- package/src/runtime/bootstrap-command-parts.ts +6 -15
- package/src/runtime/bootstrap-core.ts +34 -13
- package/src/runtime/bootstrap-hook-bridge.ts +3 -1
- package/src/runtime/bootstrap-shell.ts +3 -50
- package/src/runtime/bootstrap.ts +3 -4
- package/src/runtime/context.ts +1 -1
- package/src/runtime/diagnostics/panels/index.ts +0 -1
- package/src/runtime/diagnostics/panels/policy.ts +1 -1
- package/src/runtime/execution-ledger.ts +16 -1
- package/src/runtime/index.ts +6 -1
- package/src/runtime/onboarding/index.ts +1 -0
- package/src/runtime/onboarding/onboarding-state.ts +200 -0
- package/src/{panels → runtime}/provider-account-snapshot.ts +5 -2
- package/src/runtime/services.ts +16 -4
- package/src/runtime/terminal-output-guard.ts +7 -0
- package/src/runtime/tool-permission-safety.ts +1 -1
- package/src/runtime/ui/model-picker/data-provider.ts +1 -1
- package/src/runtime/ui/model-picker/health-enrichment.ts +2 -2
- package/src/runtime/ui/model-picker/types.ts +2 -2
- package/src/runtime/ui/provider-health/data-provider.ts +3 -3
- package/src/runtime/ui/provider-health/types.ts +2 -2
- package/src/runtime/ui-services.ts +0 -2
- package/src/shell/agent-workspace-fullscreen.ts +0 -1
- package/src/shell/autonomy-surfacing.ts +272 -0
- package/src/shell/session-continuity-hints.ts +0 -6
- package/src/shell/startup-wiring.ts +221 -0
- package/src/shell/ui-openers.ts +18 -29
- package/src/tools/agent-context-policy.ts +1 -1
- package/src/tools/agent-harness-background-processes.ts +4 -4
- package/src/tools/agent-harness-browser-cockpit-route.ts +3 -3
- package/src/tools/agent-harness-command-runner.ts +6 -1
- package/src/tools/agent-harness-document-ops.ts +26 -53
- package/src/tools/agent-harness-execution-history.ts +1 -13
- package/src/tools/agent-harness-execution-posture.ts +0 -15
- package/src/tools/agent-harness-keybinding-metadata.ts +28 -29
- package/src/tools/agent-harness-local-model-cookbook.ts +24 -1
- package/src/tools/agent-harness-metadata.ts +16 -0
- package/src/tools/agent-harness-mode-catalog.ts +2 -9
- package/src/tools/agent-harness-provider-account-metadata.ts +2 -2
- package/src/tools/agent-harness-setup-posture-utils.ts +1 -1
- package/src/tools/agent-harness-tool-schema.ts +13 -14
- package/src/tools/agent-harness-tool.ts +27 -23
- package/src/tools/agent-harness-ui-surface-metadata.ts +10 -20
- package/src/tools/agent-harness-workspace-action-runner.ts +3 -4
- package/src/tools/agent-workspace-tool.ts +2 -33
- package/src/utils/terminal-width.ts +9 -3
- package/src/version.ts +1 -1
- package/src/input/agent-workspace-panel-route.ts +0 -44
- package/src/input/panel-integration-actions.ts +0 -26
- package/src/panels/approval-panel.ts +0 -149
- package/src/panels/automation-control-panel.ts +0 -212
- package/src/panels/base-panel.ts +0 -254
- package/src/panels/builtin/agent.ts +0 -58
- package/src/panels/builtin/knowledge.ts +0 -26
- package/src/panels/builtin/operations.ts +0 -121
- package/src/panels/builtin/session.ts +0 -138
- package/src/panels/builtin/shared.ts +0 -275
- package/src/panels/builtin/usage.ts +0 -21
- package/src/panels/builtin-panels.ts +0 -23
- package/src/panels/confirm-state.ts +0 -61
- package/src/panels/context-visualizer-panel.ts +0 -204
- package/src/panels/cost-tracker-panel.ts +0 -444
- package/src/panels/docs-panel.ts +0 -285
- package/src/panels/index.ts +0 -25
- package/src/panels/knowledge-panel.ts +0 -417
- package/src/panels/memory-panel.ts +0 -226
- package/src/panels/panel-list-panel.ts +0 -464
- package/src/panels/panel-manager.ts +0 -570
- package/src/panels/provider-accounts-panel.ts +0 -233
- package/src/panels/provider-health-domains.ts +0 -208
- package/src/panels/provider-health-panel.ts +0 -720
- package/src/panels/provider-health-tracker.ts +0 -115
- package/src/panels/provider-stats-panel.ts +0 -366
- package/src/panels/qr-panel.ts +0 -207
- package/src/panels/schedule-panel.ts +0 -321
- package/src/panels/scrollable-list-panel.ts +0 -491
- package/src/panels/search-focus.ts +0 -32
- package/src/panels/security-panel.ts +0 -295
- package/src/panels/session-browser-panel.ts +0 -395
- package/src/panels/session-maintenance.ts +0 -125
- package/src/panels/subscription-panel.ts +0 -263
- package/src/panels/system-messages-panel.ts +0 -230
- package/src/panels/tasks-panel.ts +0 -344
- package/src/panels/thinking-panel.ts +0 -304
- package/src/panels/token-budget-panel.ts +0 -475
- package/src/panels/tool-inspector-panel.ts +0 -436
- package/src/panels/types.ts +0 -54
- package/src/renderer/panel-composite.ts +0 -158
- package/src/renderer/panel-tab-bar.ts +0 -69
- package/src/renderer/panel-workspace-bar.ts +0 -42
- package/src/runtime/diagnostics/panels/panel-resources.ts +0 -118
- package/src/tools/agent-harness-panel-metadata.ts +0 -211
- /package/src/runtime/perf/{panel-health-monitor.ts → component-health.ts} +0 -0
|
@@ -204,10 +204,6 @@ function describeCandidate(route: ExecutionRoute, context: CommandContext, toolR
|
|
|
204
204
|
};
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
-
function toolInspectorAvailable(context: CommandContext): boolean {
|
|
208
|
-
return Boolean(context.workspace.panelManager?.getRegisteredTypes().some((panel) => panel.id === 'tools'));
|
|
209
|
-
}
|
|
210
|
-
|
|
211
207
|
function executionSupervisionRoutes(context: CommandContext, route: ExecutionRoute): readonly ExecutionSupervisionRoute[] {
|
|
212
208
|
const routes: ExecutionSupervisionRoute[] = [];
|
|
213
209
|
if (route.id === 'local-shell-command') {
|
|
@@ -228,15 +224,6 @@ function executionSupervisionRoutes(context: CommandContext, route: ExecutionRou
|
|
|
228
224
|
},
|
|
229
225
|
);
|
|
230
226
|
}
|
|
231
|
-
if (route.id === 'local-shell-command' || route.id === 'local-edit-write') {
|
|
232
|
-
routes.push({
|
|
233
|
-
id: 'tool-inspector',
|
|
234
|
-
label: 'Tool Call Inspector',
|
|
235
|
-
available: toolInspectorAvailable(context),
|
|
236
|
-
modelRoute: 'workspace action:"open_panel" panelId:"tools"',
|
|
237
|
-
requiresConfirmation: true,
|
|
238
|
-
});
|
|
239
|
-
}
|
|
240
227
|
return routes;
|
|
241
228
|
}
|
|
242
229
|
|
|
@@ -244,11 +231,9 @@ function executionSupervisionSummary(context: CommandContext): Record<string, un
|
|
|
244
231
|
return {
|
|
245
232
|
processMonitorAvailable: typeof context.openProcessModal === 'function',
|
|
246
233
|
liveTailAvailable: typeof context.openLiveTail === 'function',
|
|
247
|
-
toolInspectorAvailable: toolInspectorAvailable(context),
|
|
248
234
|
routes: [
|
|
249
235
|
'workspace action:"open" surfaceId:"process-monitor"',
|
|
250
236
|
'workspace action:"open" surfaceId:"live-tail"',
|
|
251
|
-
'workspace action:"open_panel" panelId:"tools"',
|
|
252
237
|
],
|
|
253
238
|
};
|
|
254
239
|
}
|
|
@@ -310,30 +310,37 @@ function keybindingOperationRoute(action: KeyAction): KeybindingOperationRoute {
|
|
|
310
310
|
confirmation: 'agent_harness mode:"run_keybinding" requires confirm:true and explicitUserRequest.',
|
|
311
311
|
note: 'Runs the available clear-screen route.',
|
|
312
312
|
};
|
|
313
|
-
case '
|
|
313
|
+
case 'sidebar-toggle':
|
|
314
|
+
return {
|
|
315
|
+
supported: false,
|
|
316
|
+
effect: 'visible-ui-navigation',
|
|
317
|
+
confirmation: 'Direct user interaction only.',
|
|
318
|
+
note: 'Shows or hides the activity sidebar. Layout preferences stay under user control.',
|
|
319
|
+
};
|
|
320
|
+
case 'workspace-picker':
|
|
314
321
|
return {
|
|
315
322
|
supported: true,
|
|
316
323
|
effect: 'visible-ui-navigation',
|
|
317
324
|
preferredMode: 'run_keybinding',
|
|
318
325
|
surfaceId: 'agent-workspace',
|
|
319
326
|
confirmation: 'agent_harness mode:"run_keybinding" requires confirm:true and explicitUserRequest.',
|
|
320
|
-
note: 'Opens the
|
|
327
|
+
note: 'Opens the Agent workspace home.',
|
|
321
328
|
};
|
|
322
|
-
case '
|
|
329
|
+
case 'workspace-close':
|
|
323
330
|
return {
|
|
324
331
|
supported: true,
|
|
325
332
|
effect: 'visible-ui-navigation',
|
|
326
333
|
preferredMode: 'run_keybinding',
|
|
327
334
|
confirmation: 'agent_harness mode:"run_keybinding" requires confirm:true and explicitUserRequest.',
|
|
328
|
-
note: 'Dismisses Agent workspace
|
|
335
|
+
note: 'Dismisses the Agent workspace.',
|
|
329
336
|
};
|
|
330
|
-
case '
|
|
337
|
+
case 'workspace-close-all':
|
|
331
338
|
return {
|
|
332
339
|
supported: true,
|
|
333
340
|
effect: 'visible-ui-navigation',
|
|
334
341
|
preferredMode: 'run_keybinding',
|
|
335
342
|
confirmation: 'agent_harness mode:"run_keybinding" requires confirm:true and explicitUserRequest.',
|
|
336
|
-
note: 'Dismisses Agent workspace
|
|
343
|
+
note: 'Dismisses the Agent workspace (alias chord: Ctrl+Shift+X has the same effect as Ctrl+X).',
|
|
337
344
|
};
|
|
338
345
|
case 'history-search':
|
|
339
346
|
return {
|
|
@@ -373,8 +380,8 @@ function keybindingOperationRoute(action: KeyAction): KeybindingOperationRoute {
|
|
|
373
380
|
confirmation: 'agent_harness mode:"run_keybinding" requires confirm:true and explicitUserRequest.',
|
|
374
381
|
note: 'Opens the visible nearest-block actions surface. The exact block action remains an interactive visible-shell selection because it depends on cursor/scroll position.',
|
|
375
382
|
};
|
|
376
|
-
case '
|
|
377
|
-
case '
|
|
383
|
+
case 'workspace-tab-next':
|
|
384
|
+
case 'workspace-tab-prev':
|
|
378
385
|
return {
|
|
379
386
|
supported: false,
|
|
380
387
|
effect: 'visible-ui-navigation',
|
|
@@ -558,17 +565,17 @@ export function runHarnessKeybinding(context: CommandContext, args: HarnessKeybi
|
|
|
558
565
|
if (!context.clearScreen) return runUnavailable(resolved.action, route, 'Clear-screen route is unavailable.');
|
|
559
566
|
context.clearScreen();
|
|
560
567
|
return { status: 'executed', action: resolved.action, effect: 'screen-clear', keybinding: descriptor };
|
|
561
|
-
case '
|
|
562
|
-
if (context.
|
|
563
|
-
context.
|
|
564
|
-
return { status: 'executed', action: resolved.action, effect: 'agent-workspace-opened', route: '
|
|
568
|
+
case 'workspace-picker':
|
|
569
|
+
if (context.openWorkspacePicker) {
|
|
570
|
+
context.openWorkspacePicker();
|
|
571
|
+
return { status: 'executed', action: resolved.action, effect: 'agent-workspace-opened', route: 'openWorkspacePicker', keybinding: descriptor };
|
|
565
572
|
}
|
|
566
573
|
if (context.openAgentWorkspace) {
|
|
567
574
|
context.openAgentWorkspace('home');
|
|
568
575
|
return { status: 'executed', action: resolved.action, effect: 'agent-workspace-opened', route: 'openAgentWorkspace', categoryId: 'home', keybinding: descriptor };
|
|
569
576
|
}
|
|
570
|
-
return runUnavailable(resolved.action, route, 'No
|
|
571
|
-
case '
|
|
577
|
+
return runUnavailable(resolved.action, route, 'No workspace picker or Agent workspace route is available.');
|
|
578
|
+
case 'workspace-close': {
|
|
572
579
|
const dismissedAgentWorkspace = context.dismissAgentWorkspace?.() ?? false;
|
|
573
580
|
if (dismissedAgentWorkspace) {
|
|
574
581
|
return {
|
|
@@ -579,20 +586,17 @@ export function runHarnessKeybinding(context: CommandContext, args: HarnessKeybi
|
|
|
579
586
|
keybinding: descriptor,
|
|
580
587
|
};
|
|
581
588
|
}
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
if (!active && !context.focusPrompt) return runUnavailable(resolved.action, route, 'No active Agent workspace, active panel, or prompt focus route is available.');
|
|
585
|
-
if (context.focusPrompt) context.focusPrompt();
|
|
589
|
+
if (!context.focusPrompt) return runUnavailable(resolved.action, route, 'No active Agent workspace or prompt focus route is available.');
|
|
590
|
+
context.focusPrompt();
|
|
586
591
|
context.renderRequest();
|
|
587
592
|
return {
|
|
588
593
|
status: 'executed',
|
|
589
594
|
action: resolved.action,
|
|
590
|
-
effect:
|
|
591
|
-
...(active ? { panelId: active.id } : {}),
|
|
595
|
+
effect: 'prompt-focused',
|
|
592
596
|
keybinding: descriptor,
|
|
593
597
|
};
|
|
594
598
|
}
|
|
595
|
-
case '
|
|
599
|
+
case 'workspace-close-all': {
|
|
596
600
|
const dismissedAgentWorkspace = context.dismissAgentWorkspace?.() ?? false;
|
|
597
601
|
if (dismissedAgentWorkspace) {
|
|
598
602
|
return {
|
|
@@ -603,18 +607,13 @@ export function runHarnessKeybinding(context: CommandContext, args: HarnessKeybi
|
|
|
603
607
|
keybinding: descriptor,
|
|
604
608
|
};
|
|
605
609
|
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
for (const panel of openPanels) managerPanel?.close(panel.id);
|
|
609
|
-
managerPanel?.hide();
|
|
610
|
-
if (openPanels.length === 0 && !context.focusPrompt) return runUnavailable(resolved.action, route, 'No active Agent workspace, open panels, or prompt focus route is available.');
|
|
611
|
-
if (context.focusPrompt) context.focusPrompt();
|
|
610
|
+
if (!context.focusPrompt) return runUnavailable(resolved.action, route, 'No active Agent workspace or prompt focus route is available.');
|
|
611
|
+
context.focusPrompt();
|
|
612
612
|
context.renderRequest();
|
|
613
613
|
return {
|
|
614
614
|
status: 'executed',
|
|
615
615
|
action: resolved.action,
|
|
616
|
-
effect: '
|
|
617
|
-
closedPanels: openPanels.map((panel) => panel.id),
|
|
616
|
+
effect: 'prompt-focused',
|
|
618
617
|
keybinding: descriptor,
|
|
619
618
|
};
|
|
620
619
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CommandContext } from '../input/command-registry.ts';
|
|
2
|
+
import { estimateModelBytes, fitAssessment, fitVerdictLabel, readHardwareProfileSync, REPRESENTATIVE_7B_PARAMS } from '../core/hardware-profile.ts';
|
|
2
3
|
import { previewHarnessText } from './agent-harness-text.ts';
|
|
3
4
|
import { localModelDetection, localModelServerHealthMap } from './agent-harness-local-model-endpoints.ts';
|
|
4
5
|
import { localHardwareProfile, localRecipeReadinessScore, localRecipeStackId, scoreLocalModelRecipe } from './agent-harness-model-readiness.ts';
|
|
@@ -83,6 +84,21 @@ export function localModelSetupPlan(
|
|
|
83
84
|
};
|
|
84
85
|
}
|
|
85
86
|
|
|
87
|
+
/**
|
|
88
|
+
* Representative Q4 parameter count for a recipe's default/starter model.
|
|
89
|
+
* Used to estimate memory footprint for hardware fit annotation.
|
|
90
|
+
* Returns null for stacks where size is too variable to estimate safely.
|
|
91
|
+
*/
|
|
92
|
+
function recipeRepresentativeParamCount(recipe: LocalModelRecipe): number | null {
|
|
93
|
+
// Uses the shared REPRESENTATIVE_7B_PARAMS constant so the renderer and cookbook
|
|
94
|
+
// always reference the same basis.
|
|
95
|
+
// The generic openai-compatible stack is too varied to estimate.
|
|
96
|
+
if (recipe.id === 'ollama' || recipe.id === 'llama-cpp' || recipe.id === 'vllm') {
|
|
97
|
+
return REPRESENTATIVE_7B_PARAMS;
|
|
98
|
+
}
|
|
99
|
+
return null;
|
|
100
|
+
}
|
|
101
|
+
|
|
86
102
|
export function localModelRecipes(): readonly LocalModelRecipe[] {
|
|
87
103
|
return [
|
|
88
104
|
{
|
|
@@ -175,7 +191,14 @@ export function describeLocalModelRecipe(
|
|
|
175
191
|
hardware: previewHarnessText(recipe.hardware, includeParameters ? 180 : 96),
|
|
176
192
|
hardwareMatched: fit.reasons.slice(0, includeParameters ? 6 : 3),
|
|
177
193
|
detected,
|
|
178
|
-
|
|
194
|
+
modelRoute: 'models action:"status" or agent_harness mode:"open_ui_surface"',
|
|
195
|
+
...(() => {
|
|
196
|
+
const paramCount = recipeRepresentativeParamCount(recipe);
|
|
197
|
+
if (paramCount === null) return {};
|
|
198
|
+
const sizeBytes = estimateModelBytes(paramCount);
|
|
199
|
+
const label = fitVerdictLabel(fitAssessment(sizeBytes, readHardwareProfileSync()));
|
|
200
|
+
return label ? { hardwareFit: label } : {};
|
|
201
|
+
})(),
|
|
179
202
|
...(includeParameters ? {
|
|
180
203
|
setup: recipe.setup,
|
|
181
204
|
modelExamples: recipe.modelExamples,
|
|
@@ -204,6 +204,22 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
204
204
|
boundary: 'Connected schedules require an explicit user request and do not create hidden Agent jobs or local schedulers.',
|
|
205
205
|
};
|
|
206
206
|
}
|
|
207
|
+
if (root === 'email') {
|
|
208
|
+
return {
|
|
209
|
+
effect: 'external-network',
|
|
210
|
+
confirmation,
|
|
211
|
+
preferredModelTool: `${agentHarnessModes('run_command')} (use /email set to configure, /email config to view settings)`,
|
|
212
|
+
boundary: 'Email IMAP reads are read-only (EXAMINE); sends require explicit --yes confirmation and route only to the configured account. Use /email set email.<key> <value> to configure email settings; use /email config to view current settings. The generic settings action cannot set email.* keys — /email set is the only supported path.',
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
if (root === 'calendar' || root === 'cal') {
|
|
216
|
+
return {
|
|
217
|
+
effect: 'local-state',
|
|
218
|
+
confirmation,
|
|
219
|
+
preferredModelTool: agentHarnessModes('run_command'),
|
|
220
|
+
boundary: 'Calendar commands manage local ICS events only; import/export and mutations require explicit --yes confirmation. Calendar configuration is set via /calendar subcommands, not the generic settings action.',
|
|
221
|
+
};
|
|
222
|
+
}
|
|
207
223
|
if (root === 'channels' || root === 'channel' || root === 'notify') {
|
|
208
224
|
return {
|
|
209
225
|
effect: 'external-network',
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AGENT_HARNESS_MODES } from './agent-harness-tool-schema.ts';
|
|
2
|
+
import { readLimit } from './agent-harness-tool-utils.ts';
|
|
2
3
|
|
|
3
4
|
export type AgentHarnessMode = typeof AGENT_HARNESS_MODES[number];
|
|
4
5
|
|
|
@@ -35,9 +36,6 @@ export const HARNESS_MODE_DESCRIPTORS: readonly HarnessModeDescriptor[] = [
|
|
|
35
36
|
{ id: 'route_decision', kind: 'inspect', family: 'start', summary: 'Choose the best visible Agent route for a plain user task.', next: 'Prefer route action:"plan" for first-class access.', keywords: ['where should this go', 'which tool', 'route user task', 'one assistant', 'user-first route'], parameters: ['query', 'target', 'limit', 'includeParameters'] },
|
|
36
37
|
{ id: 'cli_commands', kind: 'discover', family: 'cli', summary: 'List top-level package CLI mirrors for discovery only.', next: 'Prefer workspace action:"cli_commands|cli_command".', parameters: ['query', 'limit', 'includeParameters'] },
|
|
37
38
|
{ id: 'cli_command', kind: 'inspect', family: 'cli', summary: 'Inspect one CLI command parser result, policy, aliases, and model route.', parameters: ['cliCommand', 'command', 'commandName', 'target', 'query'] },
|
|
38
|
-
{ id: 'panels', kind: 'discover', family: 'ui', summary: 'List built-in panel catalog state and workspace routes.', next: 'Prefer workspace action:"panels|panel|open_panel".', parameters: ['query', 'category', 'limit', 'includeParameters'] },
|
|
39
|
-
{ id: 'panel', kind: 'inspect', family: 'ui', summary: 'Inspect one built-in panel, open state, workspace route, and policy.', parameters: ['panelId', 'target', 'query'] },
|
|
40
|
-
{ id: 'open_panel', kind: 'effect', family: 'ui', summary: 'Route the visible shell to one built-in panel.', requiresConfirmation: true, parameters: ['panelId', 'target', 'query', 'pane', 'confirm', 'explicitUserRequest'] },
|
|
41
39
|
{ id: 'ui_surfaces', kind: 'discover', family: 'ui', summary: 'List modal, picker, and visible UI surfaces the model can request.', next: 'Prefer workspace action:"surfaces|surface|open".', keywords: ['web dashboard', 'pwa', 'browser cockpit', 'connected browser', 'mobile web'], parameters: ['query', 'limit', 'includeParameters'] },
|
|
42
40
|
{ id: 'ui_surface', kind: 'inspect', family: 'ui', summary: 'Inspect one visible modal or picker surface and route contract.', keywords: ['web dashboard', 'pwa', 'browser cockpit', 'connected browser', 'mobile web'], parameters: ['surfaceId', 'target', 'query'] },
|
|
43
41
|
{ id: 'open_ui_surface', kind: 'effect', family: 'ui', summary: 'Open one visible modal, picker, or operator workspace route.', requiresConfirmation: true, keywords: ['web dashboard', 'pwa', 'browser cockpit', 'connected browser', 'mobile web'], parameters: ['surfaceId', 'target', 'query', 'confirm', 'explicitUserRequest'] },
|
|
@@ -147,18 +145,13 @@ export const HARNESS_MODE_DESCRIPTORS: readonly HarnessModeDescriptor[] = [
|
|
|
147
145
|
{ id: 'connected_host_capability', kind: 'inspect', family: 'connected-host', summary: 'Inspect one connected-host capability and blocked surfaces.', next: 'Prefer host action:"capability".', parameters: ['capabilityId', 'target', 'query'] },
|
|
148
146
|
{ id: 'daemon', kind: 'alias', family: 'connected-host', summary: 'GoodVibes daemon -> connected_host; mutations use confirmed methods.', next: 'Prefer host action:"capabilities".', aliases: ['connected_host'], parameters: ['includeParameters'] },
|
|
149
147
|
{ id: 'daemon_status', kind: 'alias', family: 'connected-host', summary: 'GoodVibes daemon status -> connected_host_status.', next: 'Prefer host action:"status".', aliases: ['connected_host_status'], parameters: ['includeParameters'] },
|
|
148
|
+
{ id: 'propose_skill_drafts', kind: 'effect', family: 'personal-ops', summary: 'Draft up to 3 skills from recent learning candidates for review.', requiresConfirmation: true, keywords: ['skill draft', 'propose skill', 'auto-propose', 'draft skills', 'learning draft'], parameters: ['confirm', 'explicitUserRequest'] },
|
|
150
149
|
] as const;
|
|
151
150
|
|
|
152
151
|
function readString(value: unknown): string {
|
|
153
152
|
return typeof value === 'string' ? value.trim() : '';
|
|
154
153
|
}
|
|
155
154
|
|
|
156
|
-
function readLimit(value: unknown, fallback: number): number {
|
|
157
|
-
const parsed = typeof value === 'string' && value.trim() ? Number(value) : value;
|
|
158
|
-
if (typeof parsed !== 'number' || !Number.isFinite(parsed)) return fallback;
|
|
159
|
-
return Math.max(1, Math.min(500, Math.trunc(parsed)));
|
|
160
|
-
}
|
|
161
|
-
|
|
162
155
|
function describeHarnessModeDescriptor(
|
|
163
156
|
descriptor: HarnessModeDescriptor,
|
|
164
157
|
options: { readonly includeParameters?: boolean; readonly lookup?: Record<string, unknown> } = {},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { CommandContext } from '../input/command-registry.ts';
|
|
2
|
-
import type { ProviderAccountRecord, ProviderAccountSnapshot } from '../
|
|
3
|
-
import { buildProviderAccountSnapshot } from '../
|
|
2
|
+
import type { ProviderAccountRecord, ProviderAccountSnapshot } from '../runtime/provider-account-snapshot.ts';
|
|
3
|
+
import { buildProviderAccountSnapshot } from '../runtime/provider-account-snapshot.ts';
|
|
4
4
|
import { requireProvider, requireServiceRegistry, requireSubscriptionManager } from '../input/commands/runtime-services.ts';
|
|
5
5
|
import { previewHarnessText } from './agent-harness-text.ts';
|
|
6
6
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { statSync } from 'node:fs';
|
|
2
|
-
import { buildProviderAccountSnapshot } from '../
|
|
2
|
+
import { buildProviderAccountSnapshot } from '../runtime/provider-account-snapshot.ts';
|
|
3
3
|
import { requireLocalUserAuthManager, requirePlatform, requireProvider, requireSecretsManager, requireServiceRegistry, requireShellPaths, requireSubscriptionManager } from '../input/commands/runtime-services.ts';
|
|
4
4
|
import { collectOnboardingSnapshot } from '../runtime/onboarding/index.ts';
|
|
5
5
|
import type { CommandContext } from '../input/command-registry.ts';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export const AGENT_HARNESS_MODES = [
|
|
2
|
-
'summary', 'modes', 'mode', 'route_decision', 'cli_commands', 'cli_command',
|
|
2
|
+
'summary', 'modes', 'mode', 'route_decision', 'cli_commands', 'cli_command',
|
|
3
3
|
'ui_surfaces', 'ui_surface', 'open_ui_surface',
|
|
4
4
|
'shortcuts', 'keybindings', 'keybinding', 'run_keybinding', 'set_keybinding', 'reset_keybinding',
|
|
5
5
|
'commands', 'command', 'run_command', 'channels', 'channel', 'channel_setup_guide', 'channel_triage', 'channel_deliveries', 'notifications', 'notification_target',
|
|
@@ -32,6 +32,12 @@ export const AGENT_HARNESS_MODES = [
|
|
|
32
32
|
'service_posture', 'service_endpoint',
|
|
33
33
|
'connected_host', 'connected_host_status', 'connected_host_capability',
|
|
34
34
|
'daemon', 'daemon_status',
|
|
35
|
+
'propose_skill_drafts',
|
|
36
|
+
] as const;
|
|
37
|
+
|
|
38
|
+
const BACKGROUND_PROCESS_ACTION_VALUES = [
|
|
39
|
+
'start', 'spawn', 'run', 'stop', 'kill', 'cancel', 'wait', 'list',
|
|
40
|
+
'status', 'poll', 'log', 'output', 'write', 'capabilities', 'doctor', 'parity',
|
|
35
41
|
] as const;
|
|
36
42
|
|
|
37
43
|
const KEY_COMBO_PARAMETER_SCHEMA = {
|
|
@@ -42,10 +48,12 @@ const KEY_COMBO_PARAMETER_SCHEMA = {
|
|
|
42
48
|
} as const;
|
|
43
49
|
|
|
44
50
|
export const AGENT_HARNESS_PARAMETER_PROPERTIES = {
|
|
51
|
+
// The full mode catalog is intentionally NOT inlined as an enum:
|
|
52
|
+
// it would bloat every model prompt. Dispatch still validates against
|
|
53
|
+
// AGENT_HARNESS_MODES and unknown modes return suggestions.
|
|
45
54
|
mode: {
|
|
46
55
|
type: 'string',
|
|
47
|
-
|
|
48
|
-
description: 'Harness operation. Start with summary or a plural catalog mode.',
|
|
56
|
+
description: 'Operation. Start with "summary"; mode:"modes" lists the catalog.',
|
|
49
57
|
},
|
|
50
58
|
query: {
|
|
51
59
|
type: 'string',
|
|
@@ -131,12 +139,12 @@ export const AGENT_HARNESS_PARAMETER_PROPERTIES = {
|
|
|
131
139
|
},
|
|
132
140
|
processAction: {
|
|
133
141
|
type: 'string',
|
|
134
|
-
enum:
|
|
142
|
+
enum: BACKGROUND_PROCESS_ACTION_VALUES,
|
|
135
143
|
description: 'Background process lifecycle action or process-style alias.',
|
|
136
144
|
},
|
|
137
145
|
action: {
|
|
138
146
|
type: 'string',
|
|
139
|
-
enum:
|
|
147
|
+
enum: BACKGROUND_PROCESS_ACTION_VALUES,
|
|
140
148
|
description: 'Process-style action alias for run_background_process.',
|
|
141
149
|
},
|
|
142
150
|
cwd: {
|
|
@@ -216,10 +224,6 @@ export const AGENT_HARNESS_PARAMETER_PROPERTIES = {
|
|
|
216
224
|
type: 'string',
|
|
217
225
|
description: 'UI surface id for ui_surface or open_ui_surface modes.',
|
|
218
226
|
},
|
|
219
|
-
panelId: {
|
|
220
|
-
type: 'string',
|
|
221
|
-
description: 'Built-in panel id for panel or open_panel modes.',
|
|
222
|
-
},
|
|
223
227
|
actionId: {
|
|
224
228
|
type: 'string',
|
|
225
229
|
description: 'Workspace action id or keybinding action id.',
|
|
@@ -332,11 +336,6 @@ export const AGENT_HARNESS_PARAMETER_PROPERTIES = {
|
|
|
332
336
|
type: 'number',
|
|
333
337
|
description: 'Maximum catalog entries to return.',
|
|
334
338
|
},
|
|
335
|
-
pane: {
|
|
336
|
-
type: 'string',
|
|
337
|
-
enum: ['top', 'bottom'],
|
|
338
|
-
description: 'Preferred pane for open_panel.',
|
|
339
|
-
},
|
|
340
339
|
confirm: {
|
|
341
340
|
type: 'boolean',
|
|
342
341
|
description: 'Required true for confirmed harness effects.',
|
|
@@ -8,11 +8,12 @@ import { channelReadinessCatalogStatus, describeHarnessChannel, describeHarnessC
|
|
|
8
8
|
import { blockedHarnessCliCommandTokens, describeHarnessCliCommand, listHarnessCliCommands, totalHarnessCliCommands } from './agent-harness-cli-metadata.ts';
|
|
9
9
|
import { describeHarnessCommand, listHarnessCommands } from './agent-harness-command-catalog.ts';
|
|
10
10
|
import { describeLearningCandidate, learningCuratorCatalogStatus, learningCuratorSummary } from './agent-harness-learning-curator.ts';
|
|
11
|
+
import { runSkillDraftProposer } from '../agent/skill-draft-runner.ts';
|
|
12
|
+
import { AgentSkillRegistry } from '../agent/skill-registry.ts';
|
|
11
13
|
import { delegationPostureCatalogStatus, delegationPostureSummary, describeHarnessDelegationRoute } from './agent-harness-delegation-posture.ts';
|
|
12
14
|
import { describeHarnessKeybinding, listHarnessKeybindings, listHarnessShortcuts, resetHarnessKeybinding, runHarnessKeybinding, setHarnessKeybinding, totalHarnessKeybindings, totalHarnessShortcuts } from './agent-harness-keybinding-metadata.ts';
|
|
13
15
|
import { describeHarnessMediaProvider, mediaPostureCatalogStatus, mediaPostureSummary } from './agent-harness-media-posture.ts';
|
|
14
16
|
import { describeHarnessNotificationTarget, listHarnessNotificationTargets, notificationTargetCatalogStatus } from './agent-harness-notification-metadata.ts';
|
|
15
|
-
import { describeHarnessPanel, listHarnessPanels, openHarnessPanel, totalHarnessPanels } from './agent-harness-panel-metadata.ts';
|
|
16
17
|
import { connectedHostStatusSummary } from './agent-harness-connected-host-status.ts';
|
|
17
18
|
import { backgroundProcessCatalogStatus, backgroundProcessSummary, describeBackgroundProcess, runBackgroundProcessAction } from './agent-harness-background-processes.ts';
|
|
18
19
|
import { describeDocumentOpsLane, documentOpsCatalogStatus, documentOpsSummary } from './agent-harness-document-ops.ts';
|
|
@@ -81,7 +82,6 @@ function compactHarnessModeGuide(): Record<string, unknown> {
|
|
|
81
82
|
function detailedHarnessModelAccessGuide(): Record<string, string> {
|
|
82
83
|
return {
|
|
83
84
|
cliCommands: 'Prefer workspace action:"cli_commands|cli_command" for CLI discovery. Lower-level cli command modes remain available.',
|
|
84
|
-
panels: 'Prefer workspace action:"panels|panel|open_panel"; visible navigation needs confirm:true and explicitUserRequest.',
|
|
85
85
|
uiSurfaces: 'Prefer workspace action:"surfaces|surface|open" for visible UI and computer action:"browser|open_browser" for browser/PWA. Lower-level UI modes remain available.',
|
|
86
86
|
shortcuts: 'Prefer workspace action:"shortcuts|keybindings|keybinding|run_keybinding|set_keybinding|reset_keybinding"; effects need confirmation.',
|
|
87
87
|
slashCommands: 'Prefer workspace action:"commands|command|run_command"; slash-command execution needs confirmation.',
|
|
@@ -131,7 +131,7 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
131
131
|
return {
|
|
132
132
|
definition: {
|
|
133
133
|
name: 'agent_harness',
|
|
134
|
-
description: 'Inspect or operate
|
|
134
|
+
description: 'Inspect or operate Agent harness surfaces; mode:"modes" lists all.',
|
|
135
135
|
parameters: {
|
|
136
136
|
type: 'object',
|
|
137
137
|
properties: AGENT_HARNESS_PARAMETER_PROPERTIES,
|
|
@@ -143,7 +143,13 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
143
143
|
},
|
|
144
144
|
execute: async (rawArgs) => {
|
|
145
145
|
const args = rawArgs as AgentHarnessToolArgs;
|
|
146
|
-
if (!isMode(args.mode))
|
|
146
|
+
if (!isMode(args.mode)) {
|
|
147
|
+
const requested = String(args.mode).toLowerCase();
|
|
148
|
+
const suggestions = AGENT_HARNESS_MODES
|
|
149
|
+
.filter((mode) => mode.includes(requested) || requested.includes(mode))
|
|
150
|
+
.slice(0, 5);
|
|
151
|
+
return error(`Unknown agent_harness mode: ${String(args.mode)}. ${suggestions.length > 0 ? `Closest modes: ${suggestions.join(', ')}. ` : ''}Use mode:"modes" to list the full catalog.`);
|
|
152
|
+
}
|
|
147
153
|
try {
|
|
148
154
|
if (args.mode === 'summary') {
|
|
149
155
|
const channelReadiness = channelReadinessCatalogStatus(deps.commandContext);
|
|
@@ -214,7 +220,6 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
214
220
|
harnessModes: HARNESS_MODE_DESCRIPTORS.length,
|
|
215
221
|
cliCommands: totalHarnessCliCommands(),
|
|
216
222
|
blockedCliCommandTokens: blockedHarnessCliCommandTokens(),
|
|
217
|
-
panels: totalHarnessPanels(deps.commandContext),
|
|
218
223
|
uiSurfaces: totalHarnessUiSurfaces(),
|
|
219
224
|
shortcuts: totalHarnessShortcuts(deps.commandContext),
|
|
220
225
|
keybindings: totalHarnessKeybindings(deps.commandContext),
|
|
@@ -282,24 +287,6 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
282
287
|
if (args.mode === 'cli_command') {
|
|
283
288
|
return output(describeHarnessCliCommand(args));
|
|
284
289
|
}
|
|
285
|
-
if (args.mode === 'panels') {
|
|
286
|
-
const panels = listHarnessPanels(deps.commandContext, args);
|
|
287
|
-
return output({
|
|
288
|
-
panels,
|
|
289
|
-
returned: panels.length,
|
|
290
|
-
total: totalHarnessPanels(deps.commandContext),
|
|
291
|
-
policy: 'Panel modes expose Agent/TUI operator view catalog and open state. open_panel is confirmation-gated and routes through the current Agent operator surface.',
|
|
292
|
-
});
|
|
293
|
-
}
|
|
294
|
-
if (args.mode === 'panel') {
|
|
295
|
-
const panel = describeHarnessPanel(deps.commandContext, args);
|
|
296
|
-
return panel ? output(panel) : error(`Unknown panel ${readString(args.panelId || args.target || args.query) || '<missing>'}.`);
|
|
297
|
-
}
|
|
298
|
-
if (args.mode === 'open_panel') {
|
|
299
|
-
const confirmationError = requireConfirmedAction(args, 'Panel routing');
|
|
300
|
-
if (confirmationError) return error(confirmationError);
|
|
301
|
-
return output(openHarnessPanel(deps.commandContext, args));
|
|
302
|
-
}
|
|
303
290
|
if (args.mode === 'ui_surfaces') {
|
|
304
291
|
const surfaces = listHarnessUiSurfaces(deps.commandContext, args);
|
|
305
292
|
return output({ surfaces, returned: surfaces.length, total: totalHarnessUiSurfaces() });
|
|
@@ -717,6 +704,23 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
717
704
|
includeParameters: args.includeParameters === true,
|
|
718
705
|
}));
|
|
719
706
|
}
|
|
707
|
+
if (args.mode === 'propose_skill_drafts') {
|
|
708
|
+
const confirmationError = requireConfirmedAction(args, 'Skill draft proposal');
|
|
709
|
+
if (confirmationError) return error(confirmationError);
|
|
710
|
+
const shellPaths = deps.commandContext.workspace?.shellPaths;
|
|
711
|
+
if (!shellPaths) return error('Skill draft proposal requires an active workspace.');
|
|
712
|
+
const registry = AgentSkillRegistry.fromShellPaths(shellPaths);
|
|
713
|
+
const result = runSkillDraftProposer(deps.commandContext, registry);
|
|
714
|
+
return output({
|
|
715
|
+
proposed: result.proposed,
|
|
716
|
+
skipped: result.skipped,
|
|
717
|
+
skillIds: result.skillIds,
|
|
718
|
+
message: result.proposed > 0
|
|
719
|
+
? `Drafted ${result.proposed} skill${result.proposed !== 1 ? 's' : ''} for review. Find them under Memory > Skills with enabled:false.`
|
|
720
|
+
: 'No new skill drafts this pass.',
|
|
721
|
+
policy: 'Drafted skills are disabled and require review before use. Enable them under Memory > Skills.',
|
|
722
|
+
});
|
|
723
|
+
}
|
|
720
724
|
return error(`Unhandled agent_harness mode: ${args.mode}`);
|
|
721
725
|
} catch (err) {
|
|
722
726
|
return error(formatHarnessError(err));
|
|
@@ -101,16 +101,6 @@ function openPanelWorkspaceSurface(
|
|
|
101
101
|
options.opener();
|
|
102
102
|
return opened(surface, { categoryId: options.categoryId, panelId: options.panelId, route: 'named-opener' });
|
|
103
103
|
}
|
|
104
|
-
if (context.showPanel) {
|
|
105
|
-
const pane = optionalPane(args);
|
|
106
|
-
context.showPanel(options.panelId, pane);
|
|
107
|
-
return opened(surface, {
|
|
108
|
-
categoryId: options.categoryId,
|
|
109
|
-
panelId: options.panelId,
|
|
110
|
-
pane: pane ?? 'default',
|
|
111
|
-
route: 'panel-route',
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
104
|
return routeUnavailable(surface);
|
|
115
105
|
}
|
|
116
106
|
|
|
@@ -183,17 +173,17 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
183
173
|
},
|
|
184
174
|
{
|
|
185
175
|
id: 'panel-picker',
|
|
186
|
-
label: '
|
|
176
|
+
label: 'Workspace Picker',
|
|
187
177
|
kind: 'picker',
|
|
188
|
-
summary: 'Operator
|
|
178
|
+
summary: 'Operator route into the Agent Workspace home.',
|
|
189
179
|
command: 'Ctrl+P',
|
|
190
|
-
preferredModelRoute:
|
|
191
|
-
available: (context) => typeof context.
|
|
180
|
+
preferredModelRoute: 'Use mode:"workspace_actions" for concrete model operation, or mode:"open_ui_surface" for visible routing.',
|
|
181
|
+
available: (context) => typeof context.openWorkspacePicker === 'function' || typeof context.openAgentWorkspace === 'function',
|
|
192
182
|
open: (context) => {
|
|
193
183
|
const surface = findSurfaceById('panel-picker')!;
|
|
194
|
-
if (context.
|
|
195
|
-
context.
|
|
196
|
-
return opened(surface, { categoryId: 'home', route: '
|
|
184
|
+
if (context.openWorkspacePicker) {
|
|
185
|
+
context.openWorkspacePicker();
|
|
186
|
+
return opened(surface, { categoryId: 'home', route: 'workspace-picker' });
|
|
197
187
|
}
|
|
198
188
|
return openAgentWorkspaceCategory(context, surface, 'home');
|
|
199
189
|
},
|
|
@@ -206,7 +196,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
206
196
|
command: '/security',
|
|
207
197
|
preferredModelRoute: `Use mode:"workspace_actions" for security review actions or ${agentHarnessModes('run_command')} for confirmed /security review output.`,
|
|
208
198
|
parameters: ['pane'],
|
|
209
|
-
available: (context) => typeof context.openAgentWorkspace === 'function' || typeof context.openSecurityPanel === 'function'
|
|
199
|
+
available: (context) => typeof context.openAgentWorkspace === 'function' || typeof context.openSecurityPanel === 'function',
|
|
210
200
|
open: (context, args) => {
|
|
211
201
|
const surface = findSurfaceById('security-panel')!;
|
|
212
202
|
return openPanelWorkspaceSurface(context, args, surface, {
|
|
@@ -224,7 +214,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
224
214
|
command: '/knowledge',
|
|
225
215
|
preferredModelRoute: `Use agent_knowledge, agent_knowledge_ingest, mode:"workspace_actions", or ${agentHarnessModes('run_command')} for confirmed /knowledge operation.`,
|
|
226
216
|
parameters: ['pane'],
|
|
227
|
-
available: (context) => typeof context.openAgentWorkspace === 'function' || typeof context.openKnowledgePanel === 'function'
|
|
217
|
+
available: (context) => typeof context.openAgentWorkspace === 'function' || typeof context.openKnowledgePanel === 'function',
|
|
228
218
|
open: (context, args) => {
|
|
229
219
|
const surface = findSurfaceById('knowledge-panel')!;
|
|
230
220
|
return openPanelWorkspaceSurface(context, args, surface, {
|
|
@@ -242,7 +232,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
242
232
|
command: '/subscription',
|
|
243
233
|
preferredModelRoute: `Use mode:"workspace_actions" or ${agentHarnessModes('run_command')} for confirmed /subscription mirrors.`,
|
|
244
234
|
parameters: ['pane'],
|
|
245
|
-
available: (context) => typeof context.openAgentWorkspace === 'function' || typeof context.openSubscriptionPanel === 'function'
|
|
235
|
+
available: (context) => typeof context.openAgentWorkspace === 'function' || typeof context.openSubscriptionPanel === 'function',
|
|
246
236
|
open: (context, args) => {
|
|
247
237
|
const surface = findSurfaceById('subscription-panel')!;
|
|
248
238
|
return openPanelWorkspaceSurface(context, args, surface, {
|
|
@@ -49,7 +49,7 @@ export async function runWorkspaceAction(
|
|
|
49
49
|
if (action.kind === 'settings-import') {
|
|
50
50
|
const preview = previewAgentWorkspaceTuiSettingsImport(deps.commandContext);
|
|
51
51
|
if (!preview) return error('GoodVibes settings import is unavailable in this runtime.');
|
|
52
|
-
if (args.confirm !== true) {
|
|
52
|
+
if (args.confirm !== true && !readString(args.explicitUserRequest)) {
|
|
53
53
|
return output({
|
|
54
54
|
status: 'confirmation_required',
|
|
55
55
|
action: describeWorkspaceAction(category, action, { lookup }),
|
|
@@ -57,10 +57,9 @@ export async function runWorkspaceAction(
|
|
|
57
57
|
next: 'Run with confirm:true and explicitUserRequest after the user asks to import these settings.',
|
|
58
58
|
});
|
|
59
59
|
}
|
|
60
|
+
const confirmationError = requireConfirmedAction(args, 'GoodVibes settings import');
|
|
61
|
+
if (confirmationError) return error(confirmationError);
|
|
60
62
|
const explicitUserRequest = readString(args.explicitUserRequest);
|
|
61
|
-
if (!explicitUserRequest) {
|
|
62
|
-
return error('GoodVibes settings import requires explicitUserRequest when confirm is true.');
|
|
63
|
-
}
|
|
64
63
|
const outcome = await importAgentWorkspaceTuiSettings(deps.commandContext);
|
|
65
64
|
return output({
|
|
66
65
|
status: outcome.status,
|