@pellux/goodvibes-agent 1.0.34 → 1.0.36
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 +28 -13
- package/README.md +11 -8
- package/dist/package/main.js +1592 -921
- package/docs/README.md +6 -5
- package/docs/channels-remote-and-api.md +3 -3
- package/docs/connected-host.md +3 -3
- package/docs/getting-started.md +20 -12
- package/docs/knowledge-artifacts-and-multimodal.md +9 -4
- package/docs/project-planning.md +3 -3
- package/docs/providers-and-routing.md +2 -2
- package/docs/release-and-publishing.md +8 -8
- package/docs/tools-and-commands.md +34 -17
- package/docs/voice-and-live-tts.md +1 -1
- package/package.json +1 -1
- package/release/live-verification/live-verification.json +15 -15
- package/release/live-verification/live-verification.md +19 -21
- package/release/release-notes.md +6 -6
- package/release/release-readiness.json +64 -64
- package/src/agent/harness-control.ts +35 -9
- package/src/agent/reminder-schedule-format.ts +2 -5
- package/src/agent/reminder-schedule.ts +4 -11
- package/src/agent/routine-schedule-format.ts +3 -6
- package/src/agent/routine-schedule-promotion.ts +5 -14
- package/src/agent/routine-schedule-receipts.ts +4 -9
- package/src/cli/agent-knowledge-command.ts +6 -11
- package/src/cli/agent-knowledge-format.ts +4 -9
- package/src/cli/agent-knowledge-runtime.ts +7 -14
- package/src/cli/external-runtime.ts +3 -46
- package/src/cli/help.ts +2 -2
- package/src/cli/status.ts +6 -7
- package/src/input/agent-workspace-categories.ts +23 -23
- package/src/input/agent-workspace-channels.ts +3 -3
- package/src/input/agent-workspace-operations-command-editors.ts +1 -1
- package/src/input/command-registry.ts +1 -1
- package/src/input/commands/compat-runtime.ts +1 -1
- package/src/input/commands/planning-runtime.ts +1 -1
- package/src/input/commands/runtime-services.ts +1 -1
- package/src/input/mcp-workspace.ts +1 -1
- package/src/input/submission-router.ts +1 -1
- package/src/panels/builtin/shared.ts +1 -1
- package/src/panels/project-planning-panel.ts +4 -4
- package/src/panels/qr-panel.ts +2 -2
- package/src/renderer/conversation-overlays.ts +1 -0
- package/src/runtime/bootstrap-command-parts.ts +1 -1
- package/src/runtime/bootstrap-core.ts +3 -1
- package/src/runtime/bootstrap-hook-bridge.ts +1 -1
- package/src/runtime/bootstrap-shell.ts +1 -1
- package/src/runtime/bootstrap.ts +7 -4
- package/src/runtime/context.ts +2 -2
- package/src/runtime/index.ts +88 -5
- package/src/runtime/store/state.ts +1 -1
- package/src/tools/agent-channel-send-tool.ts +1 -1
- package/src/tools/agent-harness-channel-metadata.ts +36 -25
- package/src/tools/agent-harness-cli-metadata.ts +19 -1
- package/src/tools/agent-harness-command-catalog.ts +15 -4
- package/src/tools/agent-harness-connected-host-status.ts +7 -6
- package/src/tools/agent-harness-delegation-posture.ts +15 -4
- package/src/tools/agent-harness-keybinding-metadata.ts +67 -16
- package/src/tools/agent-harness-mcp-metadata.ts +11 -3
- package/src/tools/agent-harness-media-posture.ts +25 -14
- package/src/tools/agent-harness-metadata.ts +140 -37
- package/src/tools/agent-harness-mode-catalog.ts +258 -0
- package/src/tools/agent-harness-model-routing.ts +18 -3
- package/src/tools/agent-harness-model-tool-catalog.ts +85 -7
- package/src/tools/agent-harness-notification-metadata.ts +30 -19
- package/src/tools/agent-harness-operator-methods.ts +15 -10
- package/src/tools/agent-harness-pairing-posture.ts +17 -5
- package/src/tools/agent-harness-panel-metadata.ts +10 -4
- package/src/tools/agent-harness-provider-account-metadata.ts +46 -35
- package/src/tools/agent-harness-release-evidence.ts +31 -3
- package/src/tools/agent-harness-release-readiness.ts +30 -0
- package/src/tools/agent-harness-security-posture.ts +18 -4
- package/src/tools/agent-harness-service-posture.ts +9 -2
- package/src/tools/agent-harness-session-metadata.ts +24 -8
- package/src/tools/agent-harness-setup-posture.ts +32 -21
- package/src/tools/agent-harness-text.ts +6 -0
- package/src/tools/agent-harness-tool-schema.ts +1 -1
- package/src/tools/agent-harness-tool.ts +38 -36
- package/src/tools/agent-harness-ui-surface-metadata.ts +105 -101
- package/src/tools/agent-harness-workspace-actions.ts +64 -3
- package/src/tools/agent-knowledge-ingest-tool.ts +1 -1
- package/src/tools/agent-knowledge-tool.ts +1 -1
- package/src/tools/agent-media-generate-tool.ts +2 -2
- package/src/tools/agent-notify-tool.ts +1 -1
- package/src/tools/agent-reminder-schedule-tool.ts +1 -1
- package/src/tools/tool-definition-compaction.ts +76 -0
- package/src/version.ts +2 -8
|
@@ -28,13 +28,12 @@ import { describeHarnessSession, sessionCatalogStatus, sessionSummary } from './
|
|
|
28
28
|
import { describeHarnessServiceEndpoint, servicePostureCatalogStatus, servicePostureSummary } from './agent-harness-service-posture.ts';
|
|
29
29
|
import { describeHarnessSetupItem, setupPostureCatalogStatus, setupPostureSummary } from './agent-harness-setup-posture.ts';
|
|
30
30
|
import { AGENT_HARNESS_MODES, AGENT_HARNESS_PARAMETER_PROPERTIES } from './agent-harness-tool-schema.ts';
|
|
31
|
+
import { describeHarnessMode, HARNESS_MODE_DESCRIPTORS, listHarnessModes, type AgentHarnessMode } from './agent-harness-mode-catalog.ts';
|
|
31
32
|
import { describeHarnessUiSurface, listHarnessUiSurfaces, openHarnessUiSurface, totalHarnessUiSurfaces } from './agent-harness-ui-surface-metadata.ts';
|
|
32
33
|
import { AGENT_WORKSPACE_CATEGORIES, allWorkspaceActions, buildWorkspaceEditorContext, createWorkspaceEditor, describeWorkspaceAction, describeWorkspaceCategory, describeWorkspaceEditor, listWorkspaceActions, resolveWorkspaceActionDetail } from './agent-harness-workspace-actions.ts';
|
|
33
34
|
import { describeWorkspaceEditorModelExecution } from './agent-harness-workspace-editor-execution.ts';
|
|
34
35
|
import { connectedHostSummary, describeConnectedHostCapability, settingsPolicySummary } from './agent-harness-metadata.ts';
|
|
35
|
-
import { formatHarnessError, listHarnessSettings, resetHarnessSetting, resolveHarnessSetting, setHarnessSetting } from '../agent/harness-control.ts';
|
|
36
|
-
|
|
37
|
-
type AgentHarnessMode = typeof AGENT_HARNESS_MODES[number];
|
|
36
|
+
import { countHarnessSettings, formatHarnessError, listHarnessSettings, resetHarnessSetting, resolveHarnessSetting, setHarnessSetting } from '../agent/harness-control.ts';
|
|
38
37
|
|
|
39
38
|
interface AgentHarnessToolArgs {
|
|
40
39
|
readonly mode?: unknown;
|
|
@@ -127,31 +126,21 @@ function output(value: unknown): { readonly success: true; readonly output: stri
|
|
|
127
126
|
|
|
128
127
|
function error(message: string): { readonly success: false; readonly error: string } { return { success: false, error: message }; }
|
|
129
128
|
|
|
129
|
+
function harnessModeIdsByKind(kind: AgentHarnessModeGuideKind): readonly AgentHarnessMode[] {
|
|
130
|
+
return HARNESS_MODE_DESCRIPTORS
|
|
131
|
+
.filter((descriptor) => descriptor.kind === kind)
|
|
132
|
+
.map((descriptor) => descriptor.id);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
type AgentHarnessModeGuideKind = typeof HARNESS_MODE_DESCRIPTORS[number]['kind'];
|
|
136
|
+
|
|
130
137
|
function compactHarnessModeGuide(): Record<string, unknown> {
|
|
131
138
|
return {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
'settings', 'workspace', 'workspace_categories', 'workspace_actions',
|
|
138
|
-
'tools', 'release_evidence', 'release_readiness', 'operator_methods',
|
|
139
|
-
'service_posture', 'connected_host', 'daemon',
|
|
140
|
-
],
|
|
141
|
-
inspect: [
|
|
142
|
-
'cli_command', 'panel', 'ui_surface', 'keybinding', 'command', 'channel',
|
|
143
|
-
'notification_target', 'provider_account', 'mcp_server', 'setup_item',
|
|
144
|
-
'model_route', 'pairing_route', 'delegation_route', 'security_finding',
|
|
145
|
-
'support_bundle', 'media_provider', 'session', 'get_setting',
|
|
146
|
-
'workspace_action', 'tool', 'release_evidence_artifact',
|
|
147
|
-
'release_readiness_item', 'operator_method', 'service_endpoint',
|
|
148
|
-
'connected_host_capability', 'connected_host_status', 'daemon_status',
|
|
149
|
-
],
|
|
150
|
-
effects: [
|
|
151
|
-
'open_panel', 'open_ui_surface', 'run_keybinding', 'set_keybinding',
|
|
152
|
-
'reset_keybinding', 'run_command', 'set_setting', 'reset_setting',
|
|
153
|
-
'run_workspace_action',
|
|
154
|
-
],
|
|
139
|
+
start: ['summary', 'modes', 'mode'],
|
|
140
|
+
discover: harnessModeIdsByKind('discover'),
|
|
141
|
+
inspect: harnessModeIdsByKind('inspect'),
|
|
142
|
+
effects: harnessModeIdsByKind('effect'),
|
|
143
|
+
aliases: harnessModeIdsByKind('alias'),
|
|
155
144
|
pattern: 'Use query|target for search, exact ids for inspect modes, and confirm:true plus explicitUserRequest for effects.',
|
|
156
145
|
};
|
|
157
146
|
}
|
|
@@ -175,15 +164,16 @@ function detailedHarnessModelAccessGuide(): Record<string, string> {
|
|
|
175
164
|
supportBundles: 'List mode:"support_bundles"; inspect mode:"support_bundle"; export/import stays confirmation-gated.',
|
|
176
165
|
mediaPosture: 'List mode:"media_posture"; inspect mode:"media_provider"; generate with agent_media_generate and confirmation.',
|
|
177
166
|
sessions: 'List mode:"sessions"; inspect mode:"session"; save/resume/export/delete stays visible confirmed flow.',
|
|
178
|
-
workspace: 'List mode:"workspace" or mode:"workspace_categories"; actions via workspace_actions
|
|
179
|
-
settings: 'List mode:"settings" with category|prefix|query|includeHidden:true; get_setting
|
|
167
|
+
workspace: 'List mode:"workspace" or mode:"workspace_categories"; actions via mode:"workspace_actions", mode:"workspace_action", and mode:"run_workspace_action"; includeParameters:true inlines editor schemas.',
|
|
168
|
+
settings: 'List mode:"settings" with category|prefix|query|includeHidden:true; mode:"get_setting", mode:"set_setting", and mode:"reset_setting" use key|target|query; writes require confirmation.',
|
|
180
169
|
tools: 'List mode:"tools" with query|limit|includeParameters:true; inspect mode:"tool" with toolName|target|query.',
|
|
181
|
-
|
|
182
|
-
|
|
170
|
+
modeCatalog: 'Search mode:"modes" with query|target; inspect one contract with mode:"mode" target:"...".',
|
|
171
|
+
releaseEvidence: 'Operator/audit: list mode:"release_evidence"; inspect mode:"release_evidence_artifact"; includeParameters:true inlines artifact detail.',
|
|
172
|
+
releaseReadiness: 'Operator/audit: list mode:"release_readiness"; inspect mode:"release_readiness_item"; includeParameters:true inlines item detail.',
|
|
183
173
|
operatorMethods: 'List mode:"operator_methods"; inspect mode:"operator_method"; execute only through the returned first-class tool.',
|
|
184
174
|
servicePosture: 'List mode:"service_posture"; inspect mode:"service_endpoint"; includeParameters:true adds probes and redacted log tail.',
|
|
185
175
|
connectedHost: 'Map mode:"connected_host"; inspect mode:"connected_host_capability"; no lifecycle control.',
|
|
186
|
-
connectedHostStatus: 'Live read-only mode:"connected_host_status" for host reachability,
|
|
176
|
+
connectedHostStatus: 'Live read-only mode:"connected_host_status" for host reachability, token posture, and Knowledge readiness.',
|
|
187
177
|
daemon: 'Daemon aliases route to mode:"connected_host" and mode:"connected_host_status"; lifecycle control is not exposed.',
|
|
188
178
|
};
|
|
189
179
|
}
|
|
@@ -392,7 +382,7 @@ async function runWorkspaceAction(
|
|
|
392
382
|
}
|
|
393
383
|
if (action.kind === 'editor' && action.editorKind) {
|
|
394
384
|
const editor = createWorkspaceEditor(action.editorKind, buildWorkspaceEditorContext(deps.commandContext, args));
|
|
395
|
-
if (!editor) return error(`No workspace editor
|
|
385
|
+
if (!editor) return error(`No workspace editor route exists for ${action.editorKind}.`);
|
|
396
386
|
return runWorkspaceEditorAction(deps, action, editor, args);
|
|
397
387
|
}
|
|
398
388
|
if (action.kind === 'local-selection' || action.kind === 'local-operation') {
|
|
@@ -425,6 +415,7 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
425
415
|
try {
|
|
426
416
|
if (args.mode === 'summary') {
|
|
427
417
|
return output({
|
|
418
|
+
harnessModes: HARNESS_MODE_DESCRIPTORS.length,
|
|
428
419
|
cliCommands: totalHarnessCliCommands(),
|
|
429
420
|
blockedCliCommandTokens: blockedHarnessCliCommandTokens(),
|
|
430
421
|
panels: totalHarnessPanels(deps.commandContext),
|
|
@@ -472,6 +463,13 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
472
463
|
}),
|
|
473
464
|
});
|
|
474
465
|
}
|
|
466
|
+
if (args.mode === 'modes') return output(listHarnessModes(args));
|
|
467
|
+
if (args.mode === 'mode') {
|
|
468
|
+
const mode = describeHarnessMode(args);
|
|
469
|
+
if (mode.status === 'ambiguous') return error(`Ambiguous harness mode ${String(mode.input)}. Candidates: ${JSON.stringify(mode.candidates)}`);
|
|
470
|
+
if (mode.status === 'missing_lookup') return error(String(mode.usage));
|
|
471
|
+
return output(mode.mode);
|
|
472
|
+
}
|
|
475
473
|
if (args.mode === 'cli_commands') {
|
|
476
474
|
const commands = listHarnessCliCommands(args);
|
|
477
475
|
return output({
|
|
@@ -491,7 +489,7 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
491
489
|
panels,
|
|
492
490
|
returned: panels.length,
|
|
493
491
|
total: totalHarnessPanels(deps.commandContext),
|
|
494
|
-
policy: 'Panel modes expose Agent/TUI operator view catalog and open state. open_panel is confirmation-gated and routes through the current Agent
|
|
492
|
+
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.',
|
|
495
493
|
});
|
|
496
494
|
}
|
|
497
495
|
if (args.mode === 'panel') {
|
|
@@ -630,16 +628,20 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
630
628
|
return error(resolved.usage);
|
|
631
629
|
}
|
|
632
630
|
if (args.mode === 'settings') {
|
|
633
|
-
const
|
|
631
|
+
const filters = {
|
|
634
632
|
category: readString(args.category) || undefined,
|
|
635
633
|
prefix: readString(args.prefix) || undefined,
|
|
636
634
|
query: readString(args.query) || undefined,
|
|
637
635
|
includeHidden: args.includeHidden === true,
|
|
638
|
-
limit: readLimit(args.limit,
|
|
636
|
+
limit: readLimit(args.limit, 500),
|
|
637
|
+
};
|
|
638
|
+
const settings = listHarnessSettings(deps.commandContext.platform.configManager, {
|
|
639
|
+
...filters,
|
|
639
640
|
}, {
|
|
640
641
|
includeParameters: args.includeParameters === true,
|
|
641
642
|
});
|
|
642
|
-
|
|
643
|
+
const total = countHarnessSettings(deps.commandContext.platform.configManager, filters);
|
|
644
|
+
return output({ settings, returned: settings.length, total, policy: settingsPolicySummary() });
|
|
643
645
|
}
|
|
644
646
|
if (args.mode === 'get_setting') {
|
|
645
647
|
const setting = resolveHarnessSetting(deps.commandContext.platform.configManager, settingLookupArgs(args));
|
|
@@ -3,6 +3,10 @@ import { openTtsProviderPicker, openTtsVoicePicker } from '../input/tts-settings
|
|
|
3
3
|
|
|
4
4
|
type UiSurfaceKind = 'overlay' | 'modal' | 'workspace' | 'picker';
|
|
5
5
|
|
|
6
|
+
function agentHarnessModes(...modes: readonly string[]): string {
|
|
7
|
+
return `agent_harness ${modes.map((mode) => `mode:"${mode}"`).join(', ')}`;
|
|
8
|
+
}
|
|
9
|
+
|
|
6
10
|
export interface AgentHarnessUiSurfaceArgs {
|
|
7
11
|
readonly query?: unknown;
|
|
8
12
|
readonly surfaceId?: unknown;
|
|
@@ -70,7 +74,7 @@ function opened(surface: UiSurfaceDefinition, extra: Record<string, unknown> = {
|
|
|
70
74
|
surface: surface.id,
|
|
71
75
|
kind: surface.kind,
|
|
72
76
|
...extra,
|
|
73
|
-
note: 'UI routing was handed to the current Agent
|
|
77
|
+
note: 'UI routing was handed to the current Agent operator surface.',
|
|
74
78
|
};
|
|
75
79
|
}
|
|
76
80
|
|
|
@@ -150,20 +154,28 @@ function openPanelWorkspaceSurface(
|
|
|
150
154
|
categoryId: options.categoryId,
|
|
151
155
|
panelId: options.panelId,
|
|
152
156
|
pane: pane ?? 'default',
|
|
153
|
-
route: 'panel-
|
|
157
|
+
route: 'panel-route',
|
|
154
158
|
});
|
|
155
159
|
}
|
|
156
160
|
return routeUnavailable(surface);
|
|
157
161
|
}
|
|
158
162
|
|
|
163
|
+
function openSimpleContextSurface(context: CommandContext, surfaceId: string, openerKey: keyof CommandContext): Record<string, unknown> {
|
|
164
|
+
const surface = findSurfaceById(surfaceId)!;
|
|
165
|
+
const opener = context[openerKey] as unknown;
|
|
166
|
+
if (typeof opener !== 'function') return routeUnavailable(surface);
|
|
167
|
+
(opener as () => void)();
|
|
168
|
+
return opened(surface);
|
|
169
|
+
}
|
|
170
|
+
|
|
159
171
|
const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
160
172
|
{
|
|
161
173
|
id: 'agent-workspace',
|
|
162
174
|
label: 'Agent Workspace',
|
|
163
175
|
kind: 'workspace',
|
|
164
|
-
summary: '
|
|
176
|
+
summary: 'Operator workspace for setup, knowledge, channels, and automation.',
|
|
165
177
|
command: '/agent',
|
|
166
|
-
preferredModelRoute:
|
|
178
|
+
preferredModelRoute: `Use ${agentHarnessModes('workspace_actions', 'workspace_action', 'run_workspace_action')} for model operation; use mode:"open_ui_surface" only to visibly navigate.`,
|
|
167
179
|
parameters: ['categoryId'],
|
|
168
180
|
available: (context) => typeof context.openAgentWorkspace === 'function',
|
|
169
181
|
open: (context, args) => {
|
|
@@ -178,9 +190,9 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
178
190
|
id: 'panel-picker',
|
|
179
191
|
label: 'Panel Picker',
|
|
180
192
|
kind: 'picker',
|
|
181
|
-
summary: '
|
|
193
|
+
summary: 'Operator panel route into Agent Workspace home.',
|
|
182
194
|
command: 'Ctrl+P',
|
|
183
|
-
preferredModelRoute:
|
|
195
|
+
preferredModelRoute: `Use ${agentHarnessModes('panels', 'panel', 'open_panel')} for panel catalog and routing, or mode:"workspace_actions" for concrete model operation.`,
|
|
184
196
|
available: (context) => typeof context.openPanelPicker === 'function' || typeof context.openAgentWorkspace === 'function',
|
|
185
197
|
open: (context) => {
|
|
186
198
|
const surface = findSurfaceById('panel-picker')!;
|
|
@@ -195,15 +207,11 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
195
207
|
id: 'security-panel',
|
|
196
208
|
label: 'Security Panel',
|
|
197
209
|
kind: 'workspace',
|
|
198
|
-
summary: '
|
|
210
|
+
summary: 'Operator security review for tokens, MCP, policy, and plugin risk.',
|
|
199
211
|
command: '/security',
|
|
200
|
-
preferredModelRoute:
|
|
212
|
+
preferredModelRoute: `Use mode:"workspace_actions" for security review actions or ${agentHarnessModes('run_command')} for confirmed /security review output.`,
|
|
201
213
|
parameters: ['pane'],
|
|
202
|
-
available: (context) =>
|
|
203
|
-
typeof context.openAgentWorkspace === 'function'
|
|
204
|
-
|| typeof context.openSecurityPanel === 'function'
|
|
205
|
-
|| typeof context.showPanel === 'function'
|
|
206
|
-
),
|
|
214
|
+
available: (context) => typeof context.openAgentWorkspace === 'function' || typeof context.openSecurityPanel === 'function' || typeof context.showPanel === 'function',
|
|
207
215
|
open: (context, args) => {
|
|
208
216
|
const surface = findSurfaceById('security-panel')!;
|
|
209
217
|
return openPanelWorkspaceSurface(context, args, surface, {
|
|
@@ -217,15 +225,11 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
217
225
|
id: 'knowledge-panel',
|
|
218
226
|
label: 'Knowledge Panel',
|
|
219
227
|
kind: 'workspace',
|
|
220
|
-
summary: '
|
|
228
|
+
summary: 'Operator Knowledge surface for isolated status, search, and ingest.',
|
|
221
229
|
command: '/knowledge',
|
|
222
|
-
preferredModelRoute:
|
|
230
|
+
preferredModelRoute: `Use agent_knowledge, agent_knowledge_ingest, mode:"workspace_actions", or ${agentHarnessModes('run_command')} for confirmed /knowledge operation.`,
|
|
223
231
|
parameters: ['pane'],
|
|
224
|
-
available: (context) =>
|
|
225
|
-
typeof context.openAgentWorkspace === 'function'
|
|
226
|
-
|| typeof context.openKnowledgePanel === 'function'
|
|
227
|
-
|| typeof context.showPanel === 'function'
|
|
228
|
-
),
|
|
232
|
+
available: (context) => typeof context.openAgentWorkspace === 'function' || typeof context.openKnowledgePanel === 'function' || typeof context.showPanel === 'function',
|
|
229
233
|
open: (context, args) => {
|
|
230
234
|
const surface = findSurfaceById('knowledge-panel')!;
|
|
231
235
|
return openPanelWorkspaceSurface(context, args, surface, {
|
|
@@ -239,15 +243,11 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
239
243
|
id: 'subscription-panel',
|
|
240
244
|
label: 'Subscription Panel',
|
|
241
245
|
kind: 'workspace',
|
|
242
|
-
summary: '
|
|
246
|
+
summary: 'Operator subscription surface for provider review, auth, and bundles.',
|
|
243
247
|
command: '/subscription',
|
|
244
|
-
preferredModelRoute:
|
|
248
|
+
preferredModelRoute: `Use mode:"workspace_actions" or ${agentHarnessModes('run_command')} for confirmed /subscription mirrors.`,
|
|
245
249
|
parameters: ['pane'],
|
|
246
|
-
available: (context) =>
|
|
247
|
-
typeof context.openAgentWorkspace === 'function'
|
|
248
|
-
|| typeof context.openSubscriptionPanel === 'function'
|
|
249
|
-
|| typeof context.showPanel === 'function'
|
|
250
|
-
),
|
|
250
|
+
available: (context) => typeof context.openAgentWorkspace === 'function' || typeof context.openSubscriptionPanel === 'function' || typeof context.showPanel === 'function',
|
|
251
251
|
open: (context, args) => {
|
|
252
252
|
const surface = findSurfaceById('subscription-panel')!;
|
|
253
253
|
return openPanelWorkspaceSurface(context, args, surface, {
|
|
@@ -261,9 +261,9 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
261
261
|
id: 'settings',
|
|
262
262
|
label: 'Settings',
|
|
263
263
|
kind: 'modal',
|
|
264
|
-
summary: 'Fullscreen settings workspace for Agent
|
|
264
|
+
summary: 'Fullscreen settings workspace for Agent config, secrets, MCP, and tools.',
|
|
265
265
|
command: '/settings',
|
|
266
|
-
preferredModelRoute:
|
|
266
|
+
preferredModelRoute: `Use ${agentHarnessModes('settings', 'get_setting', 'set_setting', 'reset_setting')} for model operation; use mode:"open_ui_surface" only to visibly navigate.`,
|
|
267
267
|
parameters: ['target', 'key', 'prefix'],
|
|
268
268
|
available: (context) => typeof context.openSettingsModal === 'function',
|
|
269
269
|
open: (context, args) => {
|
|
@@ -280,14 +280,9 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
280
280
|
kind: 'workspace',
|
|
281
281
|
summary: 'MCP server setup, trust posture, and tool inventory workspace.',
|
|
282
282
|
command: '/mcp',
|
|
283
|
-
preferredModelRoute:
|
|
283
|
+
preferredModelRoute: `Use ${agentHarnessModes('workspace_actions', 'tools', 'settings')} for model operation.`,
|
|
284
284
|
available: (context) => typeof context.openMcpWorkspace === 'function',
|
|
285
|
-
open: (context) =>
|
|
286
|
-
const surface = findSurfaceById('mcp-workspace')!;
|
|
287
|
-
if (!context.openMcpWorkspace) return routeUnavailable(surface);
|
|
288
|
-
context.openMcpWorkspace();
|
|
289
|
-
return opened(surface);
|
|
290
|
-
},
|
|
285
|
+
open: (context) => openSimpleContextSurface(context, 'mcp-workspace', 'openMcpWorkspace'),
|
|
291
286
|
},
|
|
292
287
|
{
|
|
293
288
|
id: 'model-picker',
|
|
@@ -295,7 +290,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
295
290
|
kind: 'picker',
|
|
296
291
|
summary: 'Interactive model picker for main, helper, tool, and TTS model routes.',
|
|
297
292
|
command: '/model',
|
|
298
|
-
preferredModelRoute:
|
|
293
|
+
preferredModelRoute: `Use ${agentHarnessModes('settings', 'get_setting', 'set_setting')} for direct provider.model changes, or mode:"run_command" with confirmation when a concrete model id is known.`,
|
|
299
294
|
parameters: ['target'],
|
|
300
295
|
available: (context) => typeof context.openModelPicker === 'function' || typeof context.openModelPickerWithTarget === 'function',
|
|
301
296
|
open: (context, args) => {
|
|
@@ -316,7 +311,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
316
311
|
kind: 'picker',
|
|
317
312
|
summary: 'Interactive provider picker for model route setup.',
|
|
318
313
|
command: '/provider',
|
|
319
|
-
preferredModelRoute:
|
|
314
|
+
preferredModelRoute: `Use ${agentHarnessModes('settings', 'get_setting', 'set_setting')} for direct provider routing changes, or confirmed mode:"run_command" mirrors for concrete provider changes.`,
|
|
320
315
|
parameters: ['target'],
|
|
321
316
|
available: (context) => typeof context.openProviderPicker === 'function' || typeof context.openProviderModelPickerWithTarget === 'function',
|
|
322
317
|
open: (context, args) => {
|
|
@@ -335,9 +330,9 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
335
330
|
id: 'reasoning-effort-picker',
|
|
336
331
|
label: 'Reasoning Effort Picker',
|
|
337
332
|
kind: 'picker',
|
|
338
|
-
summary: '
|
|
333
|
+
summary: 'Reasoning-effort selector for models that expose effort levels.',
|
|
339
334
|
command: '/effort',
|
|
340
|
-
preferredModelRoute:
|
|
335
|
+
preferredModelRoute: `Use ${agentHarnessModes('settings', 'get_setting', 'set_setting')} for provider.reasoningEffort when a concrete level is known, or mode:"run_workspace_action" setup-effort with confirmation.`,
|
|
341
336
|
available: (context) => typeof context.openReasoningEffortPicker === 'function',
|
|
342
337
|
open: (context) => {
|
|
343
338
|
const surface = findSurfaceById('reasoning-effort-picker')!;
|
|
@@ -363,9 +358,9 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
363
358
|
id: 'tts-provider-picker',
|
|
364
359
|
label: 'TTS Provider Picker',
|
|
365
360
|
kind: 'picker',
|
|
366
|
-
summary: '
|
|
361
|
+
summary: 'Streaming TTS provider picker from Agent settings.',
|
|
367
362
|
command: '/config tts.provider',
|
|
368
|
-
preferredModelRoute:
|
|
363
|
+
preferredModelRoute: `Use ${agentHarnessModes('settings', 'get_setting', 'set_setting')} for tts.provider when a concrete provider id is known; use mode:"open_ui_surface" only to visibly navigate.`,
|
|
369
364
|
available: (context) => typeof context.openSelection === 'function' && Boolean(context.platform.voiceProviderRegistry),
|
|
370
365
|
open: (context) => {
|
|
371
366
|
const surface = findSurfaceById('tts-provider-picker')!;
|
|
@@ -378,9 +373,9 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
378
373
|
id: 'tts-voice-picker',
|
|
379
374
|
label: 'TTS Voice Picker',
|
|
380
375
|
kind: 'picker',
|
|
381
|
-
summary: '
|
|
376
|
+
summary: 'TTS voice picker for the selected or supplied provider.',
|
|
382
377
|
command: '/config tts.voice',
|
|
383
|
-
preferredModelRoute:
|
|
378
|
+
preferredModelRoute: `Use ${agentHarnessModes('settings', 'get_setting', 'set_setting', 'reset_setting')} for tts.voice when a concrete voice id is known; use mode:"open_ui_surface" only to visibly navigate.`,
|
|
384
379
|
parameters: ['target'],
|
|
385
380
|
available: (context) => typeof context.openSelection === 'function' && Boolean(context.platform.voiceService),
|
|
386
381
|
open: async (context, args) => {
|
|
@@ -401,12 +396,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
401
396
|
command: '/sessions',
|
|
402
397
|
preferredModelRoute: 'Use session slash-command mirrors with confirmation for concrete save/load/export actions.',
|
|
403
398
|
available: (context) => typeof context.openSessionPicker === 'function',
|
|
404
|
-
open: (context) =>
|
|
405
|
-
const surface = findSurfaceById('session-picker')!;
|
|
406
|
-
if (!context.openSessionPicker) return routeUnavailable(surface);
|
|
407
|
-
context.openSessionPicker();
|
|
408
|
-
return opened(surface);
|
|
409
|
-
},
|
|
399
|
+
open: (context) => openSimpleContextSurface(context, 'session-picker', 'openSessionPicker'),
|
|
410
400
|
},
|
|
411
401
|
{
|
|
412
402
|
id: 'profile-picker',
|
|
@@ -416,12 +406,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
416
406
|
command: '/agent-profile',
|
|
417
407
|
preferredModelRoute: 'Use workspace profile actions or profile slash-command mirrors for concrete model operation.',
|
|
418
408
|
available: (context) => typeof context.openProfilePicker === 'function',
|
|
419
|
-
open: (context) =>
|
|
420
|
-
const surface = findSurfaceById('profile-picker')!;
|
|
421
|
-
if (!context.openProfilePicker) return routeUnavailable(surface);
|
|
422
|
-
context.openProfilePicker();
|
|
423
|
-
return opened(surface);
|
|
424
|
-
},
|
|
409
|
+
open: (context) => openSimpleContextSurface(context, 'profile-picker', 'openProfilePicker'),
|
|
425
410
|
},
|
|
426
411
|
{
|
|
427
412
|
id: 'bookmark-modal',
|
|
@@ -431,12 +416,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
431
416
|
command: '/bookmarks',
|
|
432
417
|
preferredModelRoute: 'Use slash-command mirrors for concrete bookmark inspection; opening is visible navigation only.',
|
|
433
418
|
available: (context) => typeof context.openBookmarkModal === 'function',
|
|
434
|
-
open: (context) =>
|
|
435
|
-
const surface = findSurfaceById('bookmark-modal')!;
|
|
436
|
-
if (!context.openBookmarkModal) return routeUnavailable(surface);
|
|
437
|
-
context.openBookmarkModal();
|
|
438
|
-
return opened(surface);
|
|
439
|
-
},
|
|
419
|
+
open: (context) => openSimpleContextSurface(context, 'bookmark-modal', 'openBookmarkModal'),
|
|
440
420
|
},
|
|
441
421
|
{
|
|
442
422
|
id: 'context-inspector',
|
|
@@ -446,33 +426,23 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
446
426
|
command: '/context',
|
|
447
427
|
preferredModelRoute: 'Use slash-command mirrors for text output; opening is visible navigation only.',
|
|
448
428
|
available: (context) => typeof context.openContextInspector === 'function',
|
|
449
|
-
open: (context) =>
|
|
450
|
-
const surface = findSurfaceById('context-inspector')!;
|
|
451
|
-
if (!context.openContextInspector) return routeUnavailable(surface);
|
|
452
|
-
context.openContextInspector();
|
|
453
|
-
return opened(surface);
|
|
454
|
-
},
|
|
429
|
+
open: (context) => openSimpleContextSurface(context, 'context-inspector', 'openContextInspector'),
|
|
455
430
|
},
|
|
456
431
|
{
|
|
457
432
|
id: 'process-monitor',
|
|
458
433
|
label: 'Runtime Activity Monitor',
|
|
459
434
|
kind: 'modal',
|
|
460
|
-
summary: 'Visible running-process and live-output monitor
|
|
435
|
+
summary: 'Visible running-process and live-output monitor.',
|
|
461
436
|
command: 'F2',
|
|
462
437
|
preferredModelRoute: 'Use this only for visible supervision of runtime activity; use first-class model tools or confirmed commands for actual operations.',
|
|
463
438
|
available: (context) => typeof context.openProcessModal === 'function',
|
|
464
|
-
open: (context) =>
|
|
465
|
-
const surface = findSurfaceById('process-monitor')!;
|
|
466
|
-
if (!context.openProcessModal) return routeUnavailable(surface);
|
|
467
|
-
context.openProcessModal();
|
|
468
|
-
return opened(surface);
|
|
469
|
-
},
|
|
439
|
+
open: (context) => openSimpleContextSurface(context, 'process-monitor', 'openProcessModal'),
|
|
470
440
|
},
|
|
471
441
|
{
|
|
472
442
|
id: 'live-tail',
|
|
473
443
|
label: 'Live Process Output',
|
|
474
444
|
kind: 'modal',
|
|
475
|
-
summary: 'Visible live-output tail for a running process
|
|
445
|
+
summary: 'Visible live-output tail for a running process.',
|
|
476
446
|
command: 'F2, Enter',
|
|
477
447
|
preferredModelRoute: 'Use this only for visible supervision of a running process output stream; use first-class model tools or confirmed commands for actual operations.',
|
|
478
448
|
parameters: ['target', 'query', 'prefix', 'key'],
|
|
@@ -504,7 +474,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
504
474
|
id: 'conversation-search',
|
|
505
475
|
label: 'Conversation Search',
|
|
506
476
|
kind: 'overlay',
|
|
507
|
-
summary: 'Visible transcript search overlay
|
|
477
|
+
summary: 'Visible transcript search overlay.',
|
|
508
478
|
command: 'Ctrl+F',
|
|
509
479
|
preferredModelRoute: 'Use conversation/session/content modes for model-readable inspection; use this surface for visible transcript search navigation.',
|
|
510
480
|
parameters: ['query', 'prefix', 'key'],
|
|
@@ -521,7 +491,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
521
491
|
id: 'prompt-history-search',
|
|
522
492
|
label: 'Prompt History Search',
|
|
523
493
|
kind: 'overlay',
|
|
524
|
-
summary: 'Visible reverse prompt-history search
|
|
494
|
+
summary: 'Visible reverse prompt-history search.',
|
|
525
495
|
command: 'Ctrl+R',
|
|
526
496
|
preferredModelRoute: 'Use this only for visible prompt recall; accepting a result remains an explicit interactive shell action.',
|
|
527
497
|
parameters: ['query', 'prefix', 'key'],
|
|
@@ -538,9 +508,9 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
538
508
|
id: 'slash-command-mode',
|
|
539
509
|
label: 'Slash Command Mode',
|
|
540
510
|
kind: 'overlay',
|
|
541
|
-
summary: 'Slash-command autocomplete route
|
|
511
|
+
summary: 'Slash-command autocomplete route for empty prompts.',
|
|
542
512
|
command: '/',
|
|
543
|
-
preferredModelRoute:
|
|
513
|
+
preferredModelRoute: `Use ${agentHarnessModes('commands', 'command')} for model-readable command discovery and mode:"run_command" for confirmed command execution.`,
|
|
544
514
|
parameters: ['query', 'prefix', 'key'],
|
|
545
515
|
available: (context) => typeof context.openSlashCommandMode === 'function',
|
|
546
516
|
open: (context, args) => {
|
|
@@ -563,9 +533,9 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
563
533
|
id: 'command-browser',
|
|
564
534
|
label: 'Command Browser',
|
|
565
535
|
kind: 'picker',
|
|
566
|
-
summary: '
|
|
536
|
+
summary: 'Searchable slash-command browser opened by commands or help.',
|
|
567
537
|
command: '/commands',
|
|
568
|
-
preferredModelRoute:
|
|
538
|
+
preferredModelRoute: `Use ${agentHarnessModes('commands', 'command')} for model-readable slash-command discovery and mode:"run_command" for confirmed command execution.`,
|
|
569
539
|
available: (context) => typeof context.executeCommand === 'function',
|
|
570
540
|
open: async (context) => {
|
|
571
541
|
const surface = findSurfaceById('command-browser')!;
|
|
@@ -585,7 +555,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
585
555
|
id: 'file-picker',
|
|
586
556
|
label: 'File Picker',
|
|
587
557
|
kind: 'picker',
|
|
588
|
-
summary: 'Visible project file picker
|
|
558
|
+
summary: 'Visible project file picker for file references and injection.',
|
|
589
559
|
command: '@',
|
|
590
560
|
preferredModelRoute: 'Use first-class file, workspace, or artifact tools for model operation; use this for visible file reference navigation.',
|
|
591
561
|
parameters: ['target=reference|inject', 'query', 'prefix', 'key'],
|
|
@@ -604,7 +574,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
604
574
|
id: 'block-actions',
|
|
605
575
|
label: 'Block Actions',
|
|
606
576
|
kind: 'overlay',
|
|
607
|
-
summary: 'Visible nearest-block action menu
|
|
577
|
+
summary: 'Visible nearest-block action menu for transcript content.',
|
|
608
578
|
command: 'Enter on empty prompt',
|
|
609
579
|
preferredModelRoute: 'Use conversation/session/content modes or confirmed slash-command mirrors for concrete block operations; use this surface for visible block-action navigation.',
|
|
610
580
|
available: (context) => typeof context.openBlockActions === 'function',
|
|
@@ -628,14 +598,9 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
628
598
|
kind: 'overlay',
|
|
629
599
|
summary: 'Registry-driven command and shortcut help overlay.',
|
|
630
600
|
command: '/help',
|
|
631
|
-
preferredModelRoute:
|
|
601
|
+
preferredModelRoute: `Use ${agentHarnessModes('commands', 'command', 'shortcuts')} for model-readable discovery.`,
|
|
632
602
|
available: (context) => typeof context.openHelpOverlay === 'function',
|
|
633
|
-
open: (context) =>
|
|
634
|
-
const surface = findSurfaceById('help-overlay')!;
|
|
635
|
-
if (!context.openHelpOverlay) return routeUnavailable(surface);
|
|
636
|
-
context.openHelpOverlay();
|
|
637
|
-
return opened(surface);
|
|
638
|
-
},
|
|
603
|
+
open: (context) => openSimpleContextSurface(context, 'help-overlay', 'openHelpOverlay'),
|
|
639
604
|
},
|
|
640
605
|
{
|
|
641
606
|
id: 'shortcuts-overlay',
|
|
@@ -643,14 +608,9 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
643
608
|
kind: 'overlay',
|
|
644
609
|
summary: 'Keyboard shortcut reference overlay.',
|
|
645
610
|
command: '/shortcuts',
|
|
646
|
-
preferredModelRoute:
|
|
611
|
+
preferredModelRoute: `Use ${agentHarnessModes('shortcuts', 'keybindings')} for model-readable discovery, mode:"run_keybinding" for supported shell-safe actions, and confirmed keybinding edits for binding changes.`,
|
|
647
612
|
available: (context) => typeof context.openShortcutsOverlay === 'function',
|
|
648
|
-
open: (context) =>
|
|
649
|
-
const surface = findSurfaceById('shortcuts-overlay')!;
|
|
650
|
-
if (!context.openShortcutsOverlay) return routeUnavailable(surface);
|
|
651
|
-
context.openShortcutsOverlay();
|
|
652
|
-
return opened(surface);
|
|
653
|
-
},
|
|
613
|
+
open: (context) => openSimpleContextSurface(context, 'shortcuts-overlay', 'openShortcutsOverlay'),
|
|
654
614
|
},
|
|
655
615
|
{
|
|
656
616
|
id: 'onboarding',
|
|
@@ -658,7 +618,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
|
|
|
658
618
|
kind: 'modal',
|
|
659
619
|
summary: 'First-run and setup review wizard for Agent readiness.',
|
|
660
620
|
command: '/setup',
|
|
661
|
-
preferredModelRoute:
|
|
621
|
+
preferredModelRoute: `Use ${agentHarnessModes('workspace_actions', 'settings')} for concrete setup operation.`,
|
|
662
622
|
parameters: ['target=new|edit|reopen'],
|
|
663
623
|
available: (context) => typeof context.openOnboardingWizard === 'function',
|
|
664
624
|
open: (context, args) => {
|
|
@@ -683,6 +643,7 @@ function surfaceMatches(surface: Record<string, unknown>, query: string): boolea
|
|
|
683
643
|
surface.kind,
|
|
684
644
|
surface.summary,
|
|
685
645
|
surface.command,
|
|
646
|
+
surface.modelRoute,
|
|
686
647
|
surface.preferredModelRoute,
|
|
687
648
|
].map((value) => String(value ?? '')).join('\n').toLowerCase().includes(query.toLowerCase());
|
|
688
649
|
}
|
|
@@ -704,10 +665,52 @@ function surfaceCandidate(surface: UiSurfaceDefinition): Record<string, unknown>
|
|
|
704
665
|
kind: surface.kind,
|
|
705
666
|
summary: surface.summary,
|
|
706
667
|
command: surface.command,
|
|
707
|
-
|
|
668
|
+
modelRoute: uiSurfaceModelRoute(surface),
|
|
708
669
|
};
|
|
709
670
|
}
|
|
710
671
|
|
|
672
|
+
function uiSurfaceModelRoute(surface: UiSurfaceDefinition): string {
|
|
673
|
+
switch (surface.id) {
|
|
674
|
+
case 'agent-workspace':
|
|
675
|
+
case 'panel-picker':
|
|
676
|
+
case 'security-panel':
|
|
677
|
+
case 'subscription-panel':
|
|
678
|
+
case 'mcp-workspace':
|
|
679
|
+
case 'onboarding':
|
|
680
|
+
return 'agent_harness mode:"workspace_actions" or mode:"open_ui_surface"';
|
|
681
|
+
case 'knowledge-panel':
|
|
682
|
+
return 'agent_knowledge, agent_knowledge_ingest, or workspace_actions';
|
|
683
|
+
case 'settings':
|
|
684
|
+
case 'tts-provider-picker':
|
|
685
|
+
case 'tts-voice-picker':
|
|
686
|
+
case 'reasoning-effort-picker':
|
|
687
|
+
return 'agent_harness mode:"settings" or mode:"open_ui_surface"';
|
|
688
|
+
case 'model-picker':
|
|
689
|
+
case 'provider-picker':
|
|
690
|
+
return 'agent_harness mode:"settings" or mode:"run_command"';
|
|
691
|
+
case 'session-picker':
|
|
692
|
+
case 'bookmark-modal':
|
|
693
|
+
case 'context-inspector':
|
|
694
|
+
case 'slash-command-mode':
|
|
695
|
+
case 'command-browser':
|
|
696
|
+
case 'block-actions':
|
|
697
|
+
return 'agent_harness mode:"commands" or mode:"run_command"';
|
|
698
|
+
case 'process-monitor':
|
|
699
|
+
case 'live-tail':
|
|
700
|
+
case 'file-picker':
|
|
701
|
+
return 'first-class tools or agent_harness mode:"open_ui_surface"';
|
|
702
|
+
case 'conversation-search':
|
|
703
|
+
case 'prompt-history-search':
|
|
704
|
+
return 'agent_harness mode:"open_ui_surface"';
|
|
705
|
+
case 'help-overlay':
|
|
706
|
+
return 'agent_harness mode:"commands" or mode:"shortcuts"';
|
|
707
|
+
case 'shortcuts-overlay':
|
|
708
|
+
return 'agent_harness mode:"shortcuts" or mode:"keybindings"';
|
|
709
|
+
default:
|
|
710
|
+
return 'agent_harness mode:"open_ui_surface"';
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
711
714
|
function resolveHarnessUiSurface(args: AgentHarnessUiSurfaceArgs): UiSurfaceResolution | null {
|
|
712
715
|
const lookup = surfaceLookupFromArgs(args);
|
|
713
716
|
if (!lookup) return null;
|
|
@@ -740,9 +743,10 @@ function describeSurface(
|
|
|
740
743
|
summary: surface.summary,
|
|
741
744
|
command: surface.command,
|
|
742
745
|
...(options.lookup ? { lookup: options.lookup } : {}),
|
|
743
|
-
|
|
746
|
+
modelRoute: uiSurfaceModelRoute(surface),
|
|
744
747
|
available: surface.available(context),
|
|
745
748
|
...(options.includeParameters ? {
|
|
749
|
+
preferredModelRoute: surface.preferredModelRoute,
|
|
746
750
|
parameters: surface.parameters ?? [],
|
|
747
751
|
policy: {
|
|
748
752
|
effect: 'visible-ui-navigation',
|