@pellux/goodvibes-agent 1.0.35 → 1.0.37

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 (89) hide show
  1. package/CHANGELOG.md +20 -9
  2. package/README.md +8 -7
  3. package/dist/package/{ast-grep-napi.linux-x64-gnu-swtppvy9.node → ast-grep-napi.linux-x64-gnu-mkk8xwww.node} +0 -0
  4. package/dist/package/{ast-grep-napi.linux-x64-musl-ttfcdtap.node → ast-grep-napi.linux-x64-musl-ryqtgdv6.node} +0 -0
  5. package/dist/package/main.js +51495 -49329
  6. package/docs/README.md +6 -5
  7. package/docs/channels-remote-and-api.md +3 -3
  8. package/docs/connected-host.md +3 -3
  9. package/docs/getting-started.md +12 -7
  10. package/docs/knowledge-artifacts-and-multimodal.md +9 -4
  11. package/docs/project-planning.md +3 -3
  12. package/docs/providers-and-routing.md +2 -2
  13. package/docs/release-and-publishing.md +8 -8
  14. package/docs/tools-and-commands.md +31 -18
  15. package/docs/voice-and-live-tts.md +1 -1
  16. package/package.json +1 -1
  17. package/release/live-verification/live-verification.json +3 -3
  18. package/release/live-verification/live-verification.md +2 -4
  19. package/release/release-notes.md +4 -4
  20. package/release/release-readiness.json +46 -46
  21. package/src/agent/harness-control.ts +35 -9
  22. package/src/agent/reminder-schedule-format.ts +2 -5
  23. package/src/agent/reminder-schedule.ts +4 -11
  24. package/src/agent/routine-schedule-format.ts +3 -6
  25. package/src/agent/routine-schedule-promotion.ts +5 -14
  26. package/src/agent/routine-schedule-receipts.ts +4 -9
  27. package/src/cli/agent-knowledge-command.ts +6 -11
  28. package/src/cli/agent-knowledge-format.ts +4 -9
  29. package/src/cli/agent-knowledge-runtime.ts +7 -14
  30. package/src/cli/external-runtime.ts +3 -46
  31. package/src/cli/help.ts +2 -2
  32. package/src/cli/status.ts +6 -7
  33. package/src/input/agent-workspace-categories.ts +23 -23
  34. package/src/input/agent-workspace-channels.ts +3 -3
  35. package/src/input/agent-workspace-operations-command-editors.ts +1 -1
  36. package/src/input/command-registry.ts +1 -1
  37. package/src/input/commands/compat-runtime.ts +1 -1
  38. package/src/input/commands/planning-runtime.ts +1 -1
  39. package/src/input/commands/runtime-services.ts +1 -1
  40. package/src/input/mcp-workspace.ts +1 -1
  41. package/src/input/submission-router.ts +1 -1
  42. package/src/panels/builtin/shared.ts +1 -1
  43. package/src/panels/project-planning-panel.ts +4 -4
  44. package/src/panels/qr-panel.ts +2 -2
  45. package/src/renderer/conversation-overlays.ts +1 -0
  46. package/src/renderer/onboarding/onboarding-wizard.ts +1 -2
  47. package/src/runtime/bootstrap-command-parts.ts +1 -1
  48. package/src/runtime/bootstrap-core.ts +1 -1
  49. package/src/runtime/bootstrap-hook-bridge.ts +1 -1
  50. package/src/runtime/bootstrap-shell.ts +1 -1
  51. package/src/runtime/bootstrap.ts +5 -4
  52. package/src/runtime/context.ts +2 -2
  53. package/src/runtime/index.ts +88 -5
  54. package/src/runtime/store/state.ts +1 -1
  55. package/src/tools/agent-channel-send-tool.ts +1 -1
  56. package/src/tools/agent-harness-channel-metadata.ts +36 -25
  57. package/src/tools/agent-harness-cli-metadata.ts +19 -1
  58. package/src/tools/agent-harness-command-catalog.ts +15 -4
  59. package/src/tools/agent-harness-connected-host-status.ts +7 -6
  60. package/src/tools/agent-harness-delegation-posture.ts +15 -4
  61. package/src/tools/agent-harness-keybinding-metadata.ts +67 -16
  62. package/src/tools/agent-harness-mcp-metadata.ts +11 -3
  63. package/src/tools/agent-harness-media-posture.ts +25 -14
  64. package/src/tools/agent-harness-metadata.ts +97 -6
  65. package/src/tools/agent-harness-mode-catalog.ts +81 -28
  66. package/src/tools/agent-harness-model-routing.ts +18 -3
  67. package/src/tools/agent-harness-model-tool-catalog.ts +85 -7
  68. package/src/tools/agent-harness-notification-metadata.ts +30 -19
  69. package/src/tools/agent-harness-operator-methods.ts +13 -8
  70. package/src/tools/agent-harness-pairing-posture.ts +17 -5
  71. package/src/tools/agent-harness-panel-metadata.ts +10 -4
  72. package/src/tools/agent-harness-provider-account-metadata.ts +46 -35
  73. package/src/tools/agent-harness-release-evidence.ts +31 -3
  74. package/src/tools/agent-harness-release-readiness.ts +30 -0
  75. package/src/tools/agent-harness-security-posture.ts +18 -4
  76. package/src/tools/agent-harness-service-posture.ts +8 -1
  77. package/src/tools/agent-harness-session-metadata.ts +24 -8
  78. package/src/tools/agent-harness-setup-posture.ts +32 -21
  79. package/src/tools/agent-harness-text.ts +6 -0
  80. package/src/tools/agent-harness-tool.ts +26 -34
  81. package/src/tools/agent-harness-ui-surface-metadata.ts +84 -84
  82. package/src/tools/agent-harness-workspace-actions.ts +64 -3
  83. package/src/tools/agent-knowledge-ingest-tool.ts +1 -1
  84. package/src/tools/agent-knowledge-tool.ts +1 -1
  85. package/src/tools/agent-media-generate-tool.ts +2 -2
  86. package/src/tools/agent-notify-tool.ts +1 -1
  87. package/src/tools/agent-reminder-schedule-tool.ts +1 -1
  88. package/src/tools/tool-definition-compaction.ts +35 -8
  89. package/src/version.ts +2 -8
@@ -33,7 +33,7 @@ import { describeHarnessUiSurface, listHarnessUiSurfaces, openHarnessUiSurface,
33
33
  import { AGENT_WORKSPACE_CATEGORIES, allWorkspaceActions, buildWorkspaceEditorContext, createWorkspaceEditor, describeWorkspaceAction, describeWorkspaceCategory, describeWorkspaceEditor, listWorkspaceActions, resolveWorkspaceActionDetail } from './agent-harness-workspace-actions.ts';
34
34
  import { describeWorkspaceEditorModelExecution } from './agent-harness-workspace-editor-execution.ts';
35
35
  import { connectedHostSummary, describeConnectedHostCapability, settingsPolicySummary } from './agent-harness-metadata.ts';
36
- import { formatHarnessError, listHarnessSettings, resetHarnessSetting, resolveHarnessSetting, setHarnessSetting } from '../agent/harness-control.ts';
36
+ import { countHarnessSettings, formatHarnessError, listHarnessSettings, resetHarnessSetting, resolveHarnessSetting, setHarnessSetting } from '../agent/harness-control.ts';
37
37
 
38
38
  interface AgentHarnessToolArgs {
39
39
  readonly mode?: unknown;
@@ -126,33 +126,21 @@ function output(value: unknown): { readonly success: true; readonly output: stri
126
126
 
127
127
  function error(message: string): { readonly success: false; readonly error: string } { return { success: false, error: message }; }
128
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
+
129
137
  function compactHarnessModeGuide(): Record<string, unknown> {
130
138
  return {
131
- discover: [
132
- 'modes',
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
- 'mode',
143
- 'cli_command', 'panel', 'ui_surface', 'keybinding', 'command', 'channel',
144
- 'notification_target', 'provider_account', 'mcp_server', 'setup_item',
145
- 'model_route', 'pairing_route', 'delegation_route', 'security_finding',
146
- 'support_bundle', 'media_provider', 'session', 'get_setting',
147
- 'workspace_action', 'tool', 'release_evidence_artifact',
148
- 'release_readiness_item', 'operator_method', 'service_endpoint',
149
- 'connected_host_capability', 'connected_host_status', 'daemon_status',
150
- ],
151
- effects: [
152
- 'open_panel', 'open_ui_surface', 'run_keybinding', 'set_keybinding',
153
- 'reset_keybinding', 'run_command', 'set_setting', 'reset_setting',
154
- 'run_workspace_action',
155
- ],
139
+ start: ['summary', 'modes', 'mode'],
140
+ discover: harnessModeIdsByKind('discover'),
141
+ inspect: harnessModeIdsByKind('inspect'),
142
+ effects: harnessModeIdsByKind('effect'),
143
+ aliases: harnessModeIdsByKind('alias'),
156
144
  pattern: 'Use query|target for search, exact ids for inspect modes, and confirm:true plus explicitUserRequest for effects.',
157
145
  };
158
146
  }
@@ -180,12 +168,12 @@ function detailedHarnessModelAccessGuide(): Record<string, string> {
180
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.',
181
169
  tools: 'List mode:"tools" with query|limit|includeParameters:true; inspect mode:"tool" with toolName|target|query.',
182
170
  modeCatalog: 'Search mode:"modes" with query|target; inspect one contract with mode:"mode" target:"...".',
183
- releaseEvidence: 'List mode:"release_evidence"; inspect mode:"release_evidence_artifact"; includeParameters:true inlines artifact detail.',
184
- releaseReadiness: 'List mode:"release_readiness"; inspect mode:"release_readiness_item"; includeParameters:true inlines item detail.',
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.',
185
173
  operatorMethods: 'List mode:"operator_methods"; inspect mode:"operator_method"; execute only through the returned first-class tool.',
186
174
  servicePosture: 'List mode:"service_posture"; inspect mode:"service_endpoint"; includeParameters:true adds probes and redacted log tail.',
187
175
  connectedHost: 'Map mode:"connected_host"; inspect mode:"connected_host_capability"; no lifecycle control.',
188
- 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.',
189
177
  daemon: 'Daemon aliases route to mode:"connected_host" and mode:"connected_host_status"; lifecycle control is not exposed.',
190
178
  };
191
179
  }
@@ -394,7 +382,7 @@ async function runWorkspaceAction(
394
382
  }
395
383
  if (action.kind === 'editor' && action.editorKind) {
396
384
  const editor = createWorkspaceEditor(action.editorKind, buildWorkspaceEditorContext(deps.commandContext, args));
397
- 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}.`);
398
386
  return runWorkspaceEditorAction(deps, action, editor, args);
399
387
  }
400
388
  if (action.kind === 'local-selection' || action.kind === 'local-operation') {
@@ -501,7 +489,7 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
501
489
  panels,
502
490
  returned: panels.length,
503
491
  total: totalHarnessPanels(deps.commandContext),
504
- 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.',
505
493
  });
506
494
  }
507
495
  if (args.mode === 'panel') {
@@ -640,16 +628,20 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
640
628
  return error(resolved.usage);
641
629
  }
642
630
  if (args.mode === 'settings') {
643
- const settings = listHarnessSettings(deps.commandContext.platform.configManager, {
631
+ const filters = {
644
632
  category: readString(args.category) || undefined,
645
633
  prefix: readString(args.prefix) || undefined,
646
634
  query: readString(args.query) || undefined,
647
635
  includeHidden: args.includeHidden === true,
648
- limit: readLimit(args.limit, 100),
636
+ limit: readLimit(args.limit, 500),
637
+ };
638
+ const settings = listHarnessSettings(deps.commandContext.platform.configManager, {
639
+ ...filters,
649
640
  }, {
650
641
  includeParameters: args.includeParameters === true,
651
642
  });
652
- 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() });
653
645
  }
654
646
  if (args.mode === 'get_setting') {
655
647
  const setting = resolveHarnessSetting(deps.commandContext.platform.configManager, settingLookupArgs(args));
@@ -74,7 +74,7 @@ function opened(surface: UiSurfaceDefinition, extra: Record<string, unknown> = {
74
74
  surface: surface.id,
75
75
  kind: surface.kind,
76
76
  ...extra,
77
- note: 'UI routing was handed to the current Agent shell bridge.',
77
+ note: 'UI routing was handed to the current Agent operator surface.',
78
78
  };
79
79
  }
80
80
 
@@ -154,18 +154,26 @@ function openPanelWorkspaceSurface(
154
154
  categoryId: options.categoryId,
155
155
  panelId: options.panelId,
156
156
  pane: pane ?? 'default',
157
- route: 'panel-bridge',
157
+ route: 'panel-route',
158
158
  });
159
159
  }
160
160
  return routeUnavailable(surface);
161
161
  }
162
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
+
163
171
  const UI_SURFACES: readonly UiSurfaceDefinition[] = [
164
172
  {
165
173
  id: 'agent-workspace',
166
174
  label: 'Agent Workspace',
167
175
  kind: 'workspace',
168
- summary: 'Fullscreen operator workspace with setup, knowledge, local state, channels, automation, and delegation routes.',
176
+ summary: 'Operator workspace for setup, knowledge, channels, and automation.',
169
177
  command: '/agent',
170
178
  preferredModelRoute: `Use ${agentHarnessModes('workspace_actions', 'workspace_action', 'run_workspace_action')} for model operation; use mode:"open_ui_surface" only to visibly navigate.`,
171
179
  parameters: ['categoryId'],
@@ -182,7 +190,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
182
190
  id: 'panel-picker',
183
191
  label: 'Panel Picker',
184
192
  kind: 'picker',
185
- summary: 'Keyboard-accessible operator panel route that now opens the Agent Workspace home surface.',
193
+ summary: 'Operator panel route into Agent Workspace home.',
186
194
  command: 'Ctrl+P',
187
195
  preferredModelRoute: `Use ${agentHarnessModes('panels', 'panel', 'open_panel')} for panel catalog and routing, or mode:"workspace_actions" for concrete model operation.`,
188
196
  available: (context) => typeof context.openPanelPicker === 'function' || typeof context.openAgentWorkspace === 'function',
@@ -199,15 +207,11 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
199
207
  id: 'security-panel',
200
208
  label: 'Security Panel',
201
209
  kind: 'workspace',
202
- 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.',
203
211
  command: '/security',
204
212
  preferredModelRoute: `Use mode:"workspace_actions" for security review actions or ${agentHarnessModes('run_command')} for confirmed /security review output.`,
205
213
  parameters: ['pane'],
206
- available: (context) => (
207
- typeof context.openAgentWorkspace === 'function'
208
- || typeof context.openSecurityPanel === 'function'
209
- || typeof context.showPanel === 'function'
210
- ),
214
+ available: (context) => typeof context.openAgentWorkspace === 'function' || typeof context.openSecurityPanel === 'function' || typeof context.showPanel === 'function',
211
215
  open: (context, args) => {
212
216
  const surface = findSurfaceById('security-panel')!;
213
217
  return openPanelWorkspaceSurface(context, args, surface, {
@@ -221,15 +225,11 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
221
225
  id: 'knowledge-panel',
222
226
  label: 'Knowledge Panel',
223
227
  kind: 'workspace',
224
- 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.',
225
229
  command: '/knowledge',
226
230
  preferredModelRoute: `Use agent_knowledge, agent_knowledge_ingest, mode:"workspace_actions", or ${agentHarnessModes('run_command')} for confirmed /knowledge operation.`,
227
231
  parameters: ['pane'],
228
- available: (context) => (
229
- typeof context.openAgentWorkspace === 'function'
230
- || typeof context.openKnowledgePanel === 'function'
231
- || typeof context.showPanel === 'function'
232
- ),
232
+ available: (context) => typeof context.openAgentWorkspace === 'function' || typeof context.openKnowledgePanel === 'function' || typeof context.showPanel === 'function',
233
233
  open: (context, args) => {
234
234
  const surface = findSurfaceById('knowledge-panel')!;
235
235
  return openPanelWorkspaceSurface(context, args, surface, {
@@ -243,15 +243,11 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
243
243
  id: 'subscription-panel',
244
244
  label: 'Subscription Panel',
245
245
  kind: 'workspace',
246
- 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.',
247
247
  command: '/subscription',
248
248
  preferredModelRoute: `Use mode:"workspace_actions" or ${agentHarnessModes('run_command')} for confirmed /subscription mirrors.`,
249
249
  parameters: ['pane'],
250
- available: (context) => (
251
- typeof context.openAgentWorkspace === 'function'
252
- || typeof context.openSubscriptionPanel === 'function'
253
- || typeof context.showPanel === 'function'
254
- ),
250
+ available: (context) => typeof context.openAgentWorkspace === 'function' || typeof context.openSubscriptionPanel === 'function' || typeof context.showPanel === 'function',
255
251
  open: (context, args) => {
256
252
  const surface = findSurfaceById('subscription-panel')!;
257
253
  return openPanelWorkspaceSurface(context, args, surface, {
@@ -265,7 +261,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
265
261
  id: 'settings',
266
262
  label: 'Settings',
267
263
  kind: 'modal',
268
- 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.',
269
265
  command: '/settings',
270
266
  preferredModelRoute: `Use ${agentHarnessModes('settings', 'get_setting', 'set_setting', 'reset_setting')} for model operation; use mode:"open_ui_surface" only to visibly navigate.`,
271
267
  parameters: ['target', 'key', 'prefix'],
@@ -286,12 +282,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
286
282
  command: '/mcp',
287
283
  preferredModelRoute: `Use ${agentHarnessModes('workspace_actions', 'tools', 'settings')} for model operation.`,
288
284
  available: (context) => typeof context.openMcpWorkspace === 'function',
289
- open: (context) => {
290
- const surface = findSurfaceById('mcp-workspace')!;
291
- if (!context.openMcpWorkspace) return routeUnavailable(surface);
292
- context.openMcpWorkspace();
293
- return opened(surface);
294
- },
285
+ open: (context) => openSimpleContextSurface(context, 'mcp-workspace', 'openMcpWorkspace'),
295
286
  },
296
287
  {
297
288
  id: 'model-picker',
@@ -339,7 +330,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
339
330
  id: 'reasoning-effort-picker',
340
331
  label: 'Reasoning Effort Picker',
341
332
  kind: 'picker',
342
- 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.',
343
334
  command: '/effort',
344
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.`,
345
336
  available: (context) => typeof context.openReasoningEffortPicker === 'function',
@@ -367,7 +358,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
367
358
  id: 'tts-provider-picker',
368
359
  label: 'TTS Provider Picker',
369
360
  kind: 'picker',
370
- summary: 'Interactive streaming TTS provider picker opened from the Agent settings flow.',
361
+ summary: 'Streaming TTS provider picker from Agent settings.',
371
362
  command: '/config tts.provider',
372
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.`,
373
364
  available: (context) => typeof context.openSelection === 'function' && Boolean(context.platform.voiceProviderRegistry),
@@ -382,7 +373,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
382
373
  id: 'tts-voice-picker',
383
374
  label: 'TTS Voice Picker',
384
375
  kind: 'picker',
385
- 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.',
386
377
  command: '/config tts.voice',
387
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.`,
388
379
  parameters: ['target'],
@@ -405,12 +396,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
405
396
  command: '/sessions',
406
397
  preferredModelRoute: 'Use session slash-command mirrors with confirmation for concrete save/load/export actions.',
407
398
  available: (context) => typeof context.openSessionPicker === 'function',
408
- open: (context) => {
409
- const surface = findSurfaceById('session-picker')!;
410
- if (!context.openSessionPicker) return routeUnavailable(surface);
411
- context.openSessionPicker();
412
- return opened(surface);
413
- },
399
+ open: (context) => openSimpleContextSurface(context, 'session-picker', 'openSessionPicker'),
414
400
  },
415
401
  {
416
402
  id: 'profile-picker',
@@ -420,12 +406,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
420
406
  command: '/agent-profile',
421
407
  preferredModelRoute: 'Use workspace profile actions or profile slash-command mirrors for concrete model operation.',
422
408
  available: (context) => typeof context.openProfilePicker === 'function',
423
- open: (context) => {
424
- const surface = findSurfaceById('profile-picker')!;
425
- if (!context.openProfilePicker) return routeUnavailable(surface);
426
- context.openProfilePicker();
427
- return opened(surface);
428
- },
409
+ open: (context) => openSimpleContextSurface(context, 'profile-picker', 'openProfilePicker'),
429
410
  },
430
411
  {
431
412
  id: 'bookmark-modal',
@@ -435,12 +416,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
435
416
  command: '/bookmarks',
436
417
  preferredModelRoute: 'Use slash-command mirrors for concrete bookmark inspection; opening is visible navigation only.',
437
418
  available: (context) => typeof context.openBookmarkModal === 'function',
438
- open: (context) => {
439
- const surface = findSurfaceById('bookmark-modal')!;
440
- if (!context.openBookmarkModal) return routeUnavailable(surface);
441
- context.openBookmarkModal();
442
- return opened(surface);
443
- },
419
+ open: (context) => openSimpleContextSurface(context, 'bookmark-modal', 'openBookmarkModal'),
444
420
  },
445
421
  {
446
422
  id: 'context-inspector',
@@ -450,33 +426,23 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
450
426
  command: '/context',
451
427
  preferredModelRoute: 'Use slash-command mirrors for text output; opening is visible navigation only.',
452
428
  available: (context) => typeof context.openContextInspector === 'function',
453
- open: (context) => {
454
- const surface = findSurfaceById('context-inspector')!;
455
- if (!context.openContextInspector) return routeUnavailable(surface);
456
- context.openContextInspector();
457
- return opened(surface);
458
- },
429
+ open: (context) => openSimpleContextSurface(context, 'context-inspector', 'openContextInspector'),
459
430
  },
460
431
  {
461
432
  id: 'process-monitor',
462
433
  label: 'Runtime Activity Monitor',
463
434
  kind: 'modal',
464
- 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.',
465
436
  command: 'F2',
466
437
  preferredModelRoute: 'Use this only for visible supervision of runtime activity; use first-class model tools or confirmed commands for actual operations.',
467
438
  available: (context) => typeof context.openProcessModal === 'function',
468
- open: (context) => {
469
- const surface = findSurfaceById('process-monitor')!;
470
- if (!context.openProcessModal) return routeUnavailable(surface);
471
- context.openProcessModal();
472
- return opened(surface);
473
- },
439
+ open: (context) => openSimpleContextSurface(context, 'process-monitor', 'openProcessModal'),
474
440
  },
475
441
  {
476
442
  id: 'live-tail',
477
443
  label: 'Live Process Output',
478
444
  kind: 'modal',
479
- 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.',
480
446
  command: 'F2, Enter',
481
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.',
482
448
  parameters: ['target', 'query', 'prefix', 'key'],
@@ -508,7 +474,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
508
474
  id: 'conversation-search',
509
475
  label: 'Conversation Search',
510
476
  kind: 'overlay',
511
- summary: 'Visible transcript search overlay opened by the same shell route as Ctrl+F.',
477
+ summary: 'Visible transcript search overlay.',
512
478
  command: 'Ctrl+F',
513
479
  preferredModelRoute: 'Use conversation/session/content modes for model-readable inspection; use this surface for visible transcript search navigation.',
514
480
  parameters: ['query', 'prefix', 'key'],
@@ -525,7 +491,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
525
491
  id: 'prompt-history-search',
526
492
  label: 'Prompt History Search',
527
493
  kind: 'overlay',
528
- summary: 'Visible reverse prompt-history search opened by the same shell route as Ctrl+R.',
494
+ summary: 'Visible reverse prompt-history search.',
529
495
  command: 'Ctrl+R',
530
496
  preferredModelRoute: 'Use this only for visible prompt recall; accepting a result remains an explicit interactive shell action.',
531
497
  parameters: ['query', 'prefix', 'key'],
@@ -542,7 +508,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
542
508
  id: 'slash-command-mode',
543
509
  label: 'Slash Command Mode',
544
510
  kind: 'overlay',
545
- 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.',
546
512
  command: '/',
547
513
  preferredModelRoute: `Use ${agentHarnessModes('commands', 'command')} for model-readable command discovery and mode:"run_command" for confirmed command execution.`,
548
514
  parameters: ['query', 'prefix', 'key'],
@@ -567,7 +533,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
567
533
  id: 'command-browser',
568
534
  label: 'Command Browser',
569
535
  kind: 'picker',
570
- summary: 'Registry-driven searchable slash-command browser opened by /commands and /help.',
536
+ summary: 'Searchable slash-command browser opened by commands or help.',
571
537
  command: '/commands',
572
538
  preferredModelRoute: `Use ${agentHarnessModes('commands', 'command')} for model-readable slash-command discovery and mode:"run_command" for confirmed command execution.`,
573
539
  available: (context) => typeof context.executeCommand === 'function',
@@ -589,7 +555,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
589
555
  id: 'file-picker',
590
556
  label: 'File Picker',
591
557
  kind: 'picker',
592
- 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.',
593
559
  command: '@',
594
560
  preferredModelRoute: 'Use first-class file, workspace, or artifact tools for model operation; use this for visible file reference navigation.',
595
561
  parameters: ['target=reference|inject', 'query', 'prefix', 'key'],
@@ -608,7 +574,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
608
574
  id: 'block-actions',
609
575
  label: 'Block Actions',
610
576
  kind: 'overlay',
611
- 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.',
612
578
  command: 'Enter on empty prompt',
613
579
  preferredModelRoute: 'Use conversation/session/content modes or confirmed slash-command mirrors for concrete block operations; use this surface for visible block-action navigation.',
614
580
  available: (context) => typeof context.openBlockActions === 'function',
@@ -634,12 +600,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
634
600
  command: '/help',
635
601
  preferredModelRoute: `Use ${agentHarnessModes('commands', 'command', 'shortcuts')} for model-readable discovery.`,
636
602
  available: (context) => typeof context.openHelpOverlay === 'function',
637
- open: (context) => {
638
- const surface = findSurfaceById('help-overlay')!;
639
- if (!context.openHelpOverlay) return routeUnavailable(surface);
640
- context.openHelpOverlay();
641
- return opened(surface);
642
- },
603
+ open: (context) => openSimpleContextSurface(context, 'help-overlay', 'openHelpOverlay'),
643
604
  },
644
605
  {
645
606
  id: 'shortcuts-overlay',
@@ -649,12 +610,7 @@ const UI_SURFACES: readonly UiSurfaceDefinition[] = [
649
610
  command: '/shortcuts',
650
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.`,
651
612
  available: (context) => typeof context.openShortcutsOverlay === 'function',
652
- open: (context) => {
653
- const surface = findSurfaceById('shortcuts-overlay')!;
654
- if (!context.openShortcutsOverlay) return routeUnavailable(surface);
655
- context.openShortcutsOverlay();
656
- return opened(surface);
657
- },
613
+ open: (context) => openSimpleContextSurface(context, 'shortcuts-overlay', 'openShortcutsOverlay'),
658
614
  },
659
615
  {
660
616
  id: 'onboarding',
@@ -687,6 +643,7 @@ function surfaceMatches(surface: Record<string, unknown>, query: string): boolea
687
643
  surface.kind,
688
644
  surface.summary,
689
645
  surface.command,
646
+ surface.modelRoute,
690
647
  surface.preferredModelRoute,
691
648
  ].map((value) => String(value ?? '')).join('\n').toLowerCase().includes(query.toLowerCase());
692
649
  }
@@ -708,10 +665,52 @@ function surfaceCandidate(surface: UiSurfaceDefinition): Record<string, unknown>
708
665
  kind: surface.kind,
709
666
  summary: surface.summary,
710
667
  command: surface.command,
711
- preferredModelRoute: surface.preferredModelRoute,
668
+ modelRoute: uiSurfaceModelRoute(surface),
712
669
  };
713
670
  }
714
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
+
715
714
  function resolveHarnessUiSurface(args: AgentHarnessUiSurfaceArgs): UiSurfaceResolution | null {
716
715
  const lookup = surfaceLookupFromArgs(args);
717
716
  if (!lookup) return null;
@@ -744,9 +743,10 @@ function describeSurface(
744
743
  summary: surface.summary,
745
744
  command: surface.command,
746
745
  ...(options.lookup ? { lookup: options.lookup } : {}),
747
- preferredModelRoute: surface.preferredModelRoute,
746
+ modelRoute: uiSurfaceModelRoute(surface),
748
747
  available: surface.available(context),
749
748
  ...(options.includeParameters ? {
749
+ preferredModelRoute: surface.preferredModelRoute,
750
750
  parameters: surface.parameters ?? [],
751
751
  policy: {
752
752
  effect: 'visible-ui-navigation',
@@ -4,6 +4,8 @@ import { AGENT_WORKSPACE_CATEGORIES } from '../input/agent-workspace-categories.
4
4
  import { searchAgentWorkspaceActions } from '../input/agent-workspace-search.ts';
5
5
  import { buildAgentWorkspaceRuntimeSnapshot } from '../input/agent-workspace-snapshot.ts';
6
6
  import type { AgentWorkspaceAction, AgentWorkspaceCategory, AgentWorkspaceEditorKind, AgentWorkspaceLocalEditor, AgentWorkspaceLocalLibraryItem, AgentWorkspaceRuntimeSnapshot } from '../input/agent-workspace-types.ts';
7
+ import { parseSlashCommand } from '../input/slash-command-parser.ts';
8
+ import { describeCommandPolicy } from './agent-harness-metadata.ts';
7
9
  import { describeLocalWorkspaceModelExecution } from './agent-harness-local-operations.ts';
8
10
  import { describeWorkspaceEditorModelExecution } from './agent-harness-workspace-editor-execution.ts';
9
11
 
@@ -97,9 +99,66 @@ export function describeWorkspaceEditor(editor: AgentWorkspaceLocalEditor): Reco
97
99
  };
98
100
  }
99
101
 
100
- function previewText(value: string, maxLength = 120): string {
102
+ function previewText(value: string, maxLength = 56): string {
101
103
  const normalized = value.replace(/\s+/g, ' ').trim();
102
- return normalized.length <= maxLength ? normalized : `${normalized.slice(0, maxLength - 1).trimEnd()}...`;
104
+ return normalized.length <= maxLength ? normalized : `${normalized.slice(0, maxLength - 3).trimEnd()}...`;
105
+ }
106
+
107
+ function commandRouteHint(command: string): string {
108
+ const parsed = parseSlashCommand(command);
109
+ const commandName = parsed.name || command.replace(/^\//, '').trim().split(/\s+/)[0] || command;
110
+ return describeCommandPolicy(commandName).preferredModelTool ?? 'agent_harness mode:"run_command"';
111
+ }
112
+
113
+ function editorRouteHint(editorKind: AgentWorkspaceEditorKind): string {
114
+ if (
115
+ editorKind === 'memory'
116
+ || editorKind === 'note'
117
+ || editorKind === 'persona'
118
+ || editorKind === 'skill'
119
+ || editorKind === 'routine'
120
+ ) return 'agent_local_registry';
121
+ if (
122
+ editorKind === 'knowledge-url'
123
+ || editorKind === 'knowledge-urls'
124
+ || editorKind === 'knowledge-file'
125
+ || editorKind === 'knowledge-bookmarks'
126
+ || editorKind === 'knowledge-browser-history'
127
+ || editorKind === 'knowledge-connector-ingest'
128
+ ) return 'agent_knowledge_ingest';
129
+ if (
130
+ editorKind === 'knowledge-reindex'
131
+ || editorKind === 'knowledge-review-issue'
132
+ || editorKind === 'knowledge-consolidate'
133
+ ) return 'agent_harness mode:"run_workspace_action"';
134
+ if (editorKind.startsWith('knowledge-')) return 'agent_knowledge';
135
+ if (editorKind === 'web-research' || editorKind === 'web-fetch') return 'main conversation prompt';
136
+ if (editorKind === 'media-generate') return 'agent_media_generate';
137
+ if (editorKind === 'channel-send') return 'agent_channel_send';
138
+ if (editorKind === 'notify-send' || editorKind === 'notify-webhook-test') return 'agent_notify';
139
+ if (editorKind === 'reminder-schedule') return 'agent_reminder_schedule';
140
+ if (
141
+ editorKind.startsWith('approval-')
142
+ || editorKind.startsWith('automation-')
143
+ || editorKind === 'schedule-run'
144
+ ) return 'agent_operator_action';
145
+ if (editorKind.startsWith('workplan-') || editorKind.startsWith('plan-') || editorKind.startsWith('task-')) return 'agent_work_plan';
146
+ return 'agent_harness mode:"run_workspace_action"';
147
+ }
148
+
149
+ function localActionRouteHint(action: AgentWorkspaceAction): string {
150
+ const modelExecution = describeLocalWorkspaceModelExecution(action);
151
+ const tool = modelExecution && typeof modelExecution.tool === 'string' ? modelExecution.tool : '';
152
+ return tool || 'agent_local_registry';
153
+ }
154
+
155
+ function workspaceActionRouteHint(action: AgentWorkspaceAction): string {
156
+ if (action.command) return commandRouteHint(action.command);
157
+ if (action.editorKind) return editorRouteHint(action.editorKind);
158
+ if (action.kind === 'local-selection' || action.kind === 'local-operation') return localActionRouteHint(action);
159
+ if (action.targetCategoryId || action.kind === 'workspace') return 'agent_harness mode:"open_ui_surface"';
160
+ if (action.kind === 'guidance') return action.safety === 'blocked' ? 'main conversation policy' : 'main conversation';
161
+ return 'agent_harness mode:"workspace_action"';
103
162
  }
104
163
 
105
164
  function selectedRoutineFromArgs(
@@ -152,6 +211,7 @@ export function describeWorkspaceAction(
152
211
  detail: action.detail,
153
212
  kind: action.kind,
154
213
  safety: action.safety,
214
+ modelRoute: previewText(workspaceActionRouteHint(action)),
155
215
  ...(action.command ? { command: action.command } : {}),
156
216
  ...(action.targetCategoryId ? { targetCategoryId: action.targetCategoryId } : {}),
157
217
  ...(action.editorKind ? { editorKind: action.editorKind } : {}),
@@ -181,6 +241,7 @@ function describeWorkspaceActionSummary(
181
241
  summary: previewText(action.detail),
182
242
  kind: action.kind,
183
243
  safety: action.safety,
244
+ modelRoute: previewText(workspaceActionRouteHint(action)),
184
245
  ...(action.command ? { command: action.command } : {}),
185
246
  ...(action.targetCategoryId ? { targetCategoryId: action.targetCategoryId } : {}),
186
247
  ...(action.editorKind ? { editorKind: action.editorKind } : {}),
@@ -195,7 +256,7 @@ export function listWorkspaceActions(
195
256
  ): readonly Record<string, unknown>[] {
196
257
  const query = readString(args.query);
197
258
  const categoryId = readString(args.categoryId || args.category);
198
- const limit = readLimit(args.limit, 200);
259
+ const limit = readLimit(args.limit, 500);
199
260
  const includeEditor = args.includeParameters === true;
200
261
  const editorContext = includeEditor ? buildWorkspaceEditorContext(context, args) : null;
201
262
  const source = query
@@ -326,7 +326,7 @@ export function createAgentKnowledgeIngestTool(
326
326
  },
327
327
  allowPrivateHosts: {
328
328
  type: 'boolean',
329
- description: 'Allow private-host source URLs where the Agent Knowledge route supports it.',
329
+ description: 'Allow supported private-host source URLs.',
330
330
  },
331
331
  confirm: {
332
332
  type: 'boolean',
@@ -142,7 +142,7 @@ export function createAgentKnowledgeTool(
142
142
  },
143
143
  connectorId: {
144
144
  type: 'string',
145
- description: 'Connector id for action connector or connector_doctor. id may also be used.',
145
+ description: 'Connector id for connector or connector_doctor.',
146
146
  },
147
147
  limit: {
148
148
  type: 'number',
@@ -74,11 +74,11 @@ export function createAgentMediaGenerateTool(
74
74
  },
75
75
  confirm: {
76
76
  type: 'boolean',
77
- description: 'Required true only when the user explicitly asked for this media generation.',
77
+ description: 'Required true only when user requested this media.',
78
78
  },
79
79
  explicitUserRequest: {
80
80
  type: 'string',
81
- description: 'Short quote or summary of the user request that authorized this generation.',
81
+ description: 'User request authorizing this media generation.',
82
82
  },
83
83
  },
84
84
  required: ['prompt', 'confirm', 'explicitUserRequest'],
@@ -88,7 +88,7 @@ export function createAgentNotifyTool(
88
88
  },
89
89
  confirm: {
90
90
  type: 'boolean',
91
- description: 'Required true only when the user explicitly asked to send this notification.',
91
+ description: 'Required true only when user requested notification.',
92
92
  },
93
93
  explicitUserRequest: {
94
94
  type: 'string',