@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.
Files changed (87) hide show
  1. package/CHANGELOG.md +28 -13
  2. package/README.md +11 -8
  3. package/dist/package/main.js +1592 -921
  4. package/docs/README.md +6 -5
  5. package/docs/channels-remote-and-api.md +3 -3
  6. package/docs/connected-host.md +3 -3
  7. package/docs/getting-started.md +20 -12
  8. package/docs/knowledge-artifacts-and-multimodal.md +9 -4
  9. package/docs/project-planning.md +3 -3
  10. package/docs/providers-and-routing.md +2 -2
  11. package/docs/release-and-publishing.md +8 -8
  12. package/docs/tools-and-commands.md +34 -17
  13. package/docs/voice-and-live-tts.md +1 -1
  14. package/package.json +1 -1
  15. package/release/live-verification/live-verification.json +15 -15
  16. package/release/live-verification/live-verification.md +19 -21
  17. package/release/release-notes.md +6 -6
  18. package/release/release-readiness.json +64 -64
  19. package/src/agent/harness-control.ts +35 -9
  20. package/src/agent/reminder-schedule-format.ts +2 -5
  21. package/src/agent/reminder-schedule.ts +4 -11
  22. package/src/agent/routine-schedule-format.ts +3 -6
  23. package/src/agent/routine-schedule-promotion.ts +5 -14
  24. package/src/agent/routine-schedule-receipts.ts +4 -9
  25. package/src/cli/agent-knowledge-command.ts +6 -11
  26. package/src/cli/agent-knowledge-format.ts +4 -9
  27. package/src/cli/agent-knowledge-runtime.ts +7 -14
  28. package/src/cli/external-runtime.ts +3 -46
  29. package/src/cli/help.ts +2 -2
  30. package/src/cli/status.ts +6 -7
  31. package/src/input/agent-workspace-categories.ts +23 -23
  32. package/src/input/agent-workspace-channels.ts +3 -3
  33. package/src/input/agent-workspace-operations-command-editors.ts +1 -1
  34. package/src/input/command-registry.ts +1 -1
  35. package/src/input/commands/compat-runtime.ts +1 -1
  36. package/src/input/commands/planning-runtime.ts +1 -1
  37. package/src/input/commands/runtime-services.ts +1 -1
  38. package/src/input/mcp-workspace.ts +1 -1
  39. package/src/input/submission-router.ts +1 -1
  40. package/src/panels/builtin/shared.ts +1 -1
  41. package/src/panels/project-planning-panel.ts +4 -4
  42. package/src/panels/qr-panel.ts +2 -2
  43. package/src/renderer/conversation-overlays.ts +1 -0
  44. package/src/runtime/bootstrap-command-parts.ts +1 -1
  45. package/src/runtime/bootstrap-core.ts +3 -1
  46. package/src/runtime/bootstrap-hook-bridge.ts +1 -1
  47. package/src/runtime/bootstrap-shell.ts +1 -1
  48. package/src/runtime/bootstrap.ts +7 -4
  49. package/src/runtime/context.ts +2 -2
  50. package/src/runtime/index.ts +88 -5
  51. package/src/runtime/store/state.ts +1 -1
  52. package/src/tools/agent-channel-send-tool.ts +1 -1
  53. package/src/tools/agent-harness-channel-metadata.ts +36 -25
  54. package/src/tools/agent-harness-cli-metadata.ts +19 -1
  55. package/src/tools/agent-harness-command-catalog.ts +15 -4
  56. package/src/tools/agent-harness-connected-host-status.ts +7 -6
  57. package/src/tools/agent-harness-delegation-posture.ts +15 -4
  58. package/src/tools/agent-harness-keybinding-metadata.ts +67 -16
  59. package/src/tools/agent-harness-mcp-metadata.ts +11 -3
  60. package/src/tools/agent-harness-media-posture.ts +25 -14
  61. package/src/tools/agent-harness-metadata.ts +140 -37
  62. package/src/tools/agent-harness-mode-catalog.ts +258 -0
  63. package/src/tools/agent-harness-model-routing.ts +18 -3
  64. package/src/tools/agent-harness-model-tool-catalog.ts +85 -7
  65. package/src/tools/agent-harness-notification-metadata.ts +30 -19
  66. package/src/tools/agent-harness-operator-methods.ts +15 -10
  67. package/src/tools/agent-harness-pairing-posture.ts +17 -5
  68. package/src/tools/agent-harness-panel-metadata.ts +10 -4
  69. package/src/tools/agent-harness-provider-account-metadata.ts +46 -35
  70. package/src/tools/agent-harness-release-evidence.ts +31 -3
  71. package/src/tools/agent-harness-release-readiness.ts +30 -0
  72. package/src/tools/agent-harness-security-posture.ts +18 -4
  73. package/src/tools/agent-harness-service-posture.ts +9 -2
  74. package/src/tools/agent-harness-session-metadata.ts +24 -8
  75. package/src/tools/agent-harness-setup-posture.ts +32 -21
  76. package/src/tools/agent-harness-text.ts +6 -0
  77. package/src/tools/agent-harness-tool-schema.ts +1 -1
  78. package/src/tools/agent-harness-tool.ts +38 -36
  79. package/src/tools/agent-harness-ui-surface-metadata.ts +105 -101
  80. package/src/tools/agent-harness-workspace-actions.ts +64 -3
  81. package/src/tools/agent-knowledge-ingest-tool.ts +1 -1
  82. package/src/tools/agent-knowledge-tool.ts +1 -1
  83. package/src/tools/agent-media-generate-tool.ts +2 -2
  84. package/src/tools/agent-notify-tool.ts +1 -1
  85. package/src/tools/agent-reminder-schedule-tool.ts +1 -1
  86. package/src/tools/tool-definition-compaction.ts +76 -0
  87. 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
- discover: [
133
- 'cli_commands', 'panels', 'ui_surfaces', 'shortcuts', 'keybindings',
134
- 'commands', 'channels', 'notifications', 'provider_accounts', 'mcp_servers',
135
- 'setup_posture', 'model_routing', 'pairing_posture', 'delegation_posture',
136
- 'security_posture', 'support_bundles', 'media_posture', 'sessions',
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/workspace_action/run_workspace_action; includeParameters:true inlines editor schemas.',
179
- settings: 'List mode:"settings" with category|prefix|query|includeHidden:true; get_setting/set_setting/reset_setting use key|target|query and confirmation for writes.',
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
- releaseEvidence: 'List mode:"release_evidence"; inspect mode:"release_evidence_artifact"; includeParameters:true inlines artifact detail.',
182
- releaseReadiness: 'List mode:"release_readiness"; inspect mode:"release_readiness_item"; includeParameters:true inlines item detail.',
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, SDK compatibility, token posture, and Knowledge readiness.',
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 bridge exists for ${action.editorKind}.`);
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 shell bridge.',
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 settings = listHarnessSettings(deps.commandContext.platform.configManager, {
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, 100),
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
- return output({ settings, returned: settings.length, policy: settingsPolicySummary() });
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 shell bridge.',
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-bridge',
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: 'Fullscreen operator workspace with setup, knowledge, local state, channels, automation, and delegation routes.',
176
+ summary: 'Operator workspace for setup, knowledge, channels, and automation.',
165
177
  command: '/agent',
166
- preferredModelRoute: 'Use workspace_actions/workspace_action/run_workspace_action for model operation; use open_ui_surface only to visibly navigate.',
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: 'Keyboard-accessible operator panel route that now opens the Agent Workspace home surface.',
193
+ summary: 'Operator panel route into Agent Workspace home.',
182
194
  command: 'Ctrl+P',
183
- preferredModelRoute: 'Use panels/panel/open_panel for panel catalog and routing, or workspace_actions for concrete model operation.',
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: 'Security review operator surface for token posture, MCP attack paths, policy posture, and plugin risk.',
210
+ summary: 'Operator security review for tokens, MCP, policy, and plugin risk.',
199
211
  command: '/security',
200
- preferredModelRoute: 'Use workspace_actions for security review actions or run_command /security review for compact read-only output.',
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: 'Agent Knowledge operator surface for isolated status, source/node/issue libraries, item lookup, map review, connectors, ask/search, and ingest forms.',
228
+ summary: 'Operator Knowledge surface for isolated status, search, and ingest.',
221
229
  command: '/knowledge',
222
- preferredModelRoute: 'Use agent_knowledge, agent_knowledge_ingest, workspace_actions, or run_command /knowledge for concrete model operation.',
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: 'Provider subscription operator surface for subscription review, provider inspection, login, logout, and bundle flows.',
246
+ summary: 'Operator subscription surface for provider review, auth, and bundles.',
243
247
  command: '/subscription',
244
- preferredModelRoute: 'Use workspace_actions or confirmed run_command /subscription mirrors for concrete subscription operation.',
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-owned configuration, subscriptions, secrets, MCP, tools, and surface settings.',
264
+ summary: 'Fullscreen settings workspace for Agent config, secrets, MCP, and tools.',
265
265
  command: '/settings',
266
- preferredModelRoute: 'Use settings/get_setting/set_setting/reset_setting for model operation; use open_ui_surface only to visibly navigate.',
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: 'Use workspace_actions, tools, and settings modes for model operation.',
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: 'Use settings mode for direct provider.model changes, or run_command /model with confirmation when a concrete model id is known.',
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: 'Use settings mode for direct provider routing changes, or run confirmed slash-command mirrors for concrete provider changes.',
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: 'Interactive reasoning-effort selector for the current main chat model when that model exposes effort levels.',
333
+ summary: 'Reasoning-effort selector for models that expose effort levels.',
339
334
  command: '/effort',
340
- preferredModelRoute: 'Use settings/get_setting/set_setting for provider.reasoningEffort when a concrete level is known, or run_workspace_action setup-effort with confirmation.',
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: 'Interactive streaming TTS provider picker opened from the Agent settings flow.',
361
+ summary: 'Streaming TTS provider picker from Agent settings.',
367
362
  command: '/config tts.provider',
368
- preferredModelRoute: 'Use settings/get_setting/set_setting for tts.provider when a concrete provider id is known; use open_ui_surface only to visibly navigate.',
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: 'Interactive TTS voice picker opened from the Agent settings flow for the selected or supplied provider.',
376
+ summary: 'TTS voice picker for the selected or supplied provider.',
382
377
  command: '/config tts.voice',
383
- preferredModelRoute: 'Use settings/get_setting/set_setting/reset_setting for tts.voice when a concrete voice id is known; use open_ui_surface only to visibly navigate.',
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 opened by the same shell route as F2.',
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, opened by the same shell route as Enter from the runtime activity monitor.',
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 opened by the same shell route as Ctrl+F.',
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 opened by the same shell route as Ctrl+R.',
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 opened by the same shell path as typing / in an empty prompt.',
511
+ summary: 'Slash-command autocomplete route for empty prompts.',
542
512
  command: '/',
543
- preferredModelRoute: 'Use commands/command for model-readable command discovery and run_command for confirmed command execution.',
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: 'Registry-driven searchable slash-command browser opened by /commands and /help.',
536
+ summary: 'Searchable slash-command browser opened by commands or help.',
567
537
  command: '/commands',
568
- preferredModelRoute: 'Use commands/command for model-readable slash-command discovery and run_command for confirmed command execution.',
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 opened by the same prompt route as @ and !@ references.',
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 opened by the same shell route as pressing Enter on an empty prompt near transcript content.',
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: 'Use commands/command and shortcuts modes for model-readable discovery.',
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: 'Use shortcuts/keybindings modes for model-readable discovery, run_keybinding for supported shell-safe actions, and confirmed keybinding edits for binding changes.',
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: 'Use workspace setup actions and settings modes for concrete model operation.',
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
- preferredModelRoute: surface.preferredModelRoute,
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
- preferredModelRoute: surface.preferredModelRoute,
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',