@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.
- package/CHANGELOG.md +20 -9
- package/README.md +8 -7
- package/dist/package/{ast-grep-napi.linux-x64-gnu-swtppvy9.node → ast-grep-napi.linux-x64-gnu-mkk8xwww.node} +0 -0
- package/dist/package/{ast-grep-napi.linux-x64-musl-ttfcdtap.node → ast-grep-napi.linux-x64-musl-ryqtgdv6.node} +0 -0
- package/dist/package/main.js +51495 -49329
- 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 +12 -7
- 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 +31 -18
- package/docs/voice-and-live-tts.md +1 -1
- package/package.json +1 -1
- package/release/live-verification/live-verification.json +3 -3
- package/release/live-verification/live-verification.md +2 -4
- package/release/release-notes.md +4 -4
- package/release/release-readiness.json +46 -46
- 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/renderer/onboarding/onboarding-wizard.ts +1 -2
- package/src/runtime/bootstrap-command-parts.ts +1 -1
- package/src/runtime/bootstrap-core.ts +1 -1
- package/src/runtime/bootstrap-hook-bridge.ts +1 -1
- package/src/runtime/bootstrap-shell.ts +1 -1
- package/src/runtime/bootstrap.ts +5 -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 +97 -6
- package/src/tools/agent-harness-mode-catalog.ts +81 -28
- 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 +13 -8
- 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 +8 -1
- 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.ts +26 -34
- package/src/tools/agent-harness-ui-surface-metadata.ts +84 -84
- 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 +35 -8
- package/src/version.ts +2 -8
|
@@ -222,6 +222,8 @@ function bindingCandidate(manager: KeybindingsManager | null, entry: KeybindingE
|
|
|
222
222
|
action: entry.action,
|
|
223
223
|
description: entry.description,
|
|
224
224
|
labels: entry.combos.map((combo) => formatCombo(manager, combo)),
|
|
225
|
+
modelRoute: keybindingModelRoute(entry.action),
|
|
226
|
+
inspectRoute: `agent_harness mode:"keybinding" actionId:"${entry.action}"`,
|
|
225
227
|
};
|
|
226
228
|
}
|
|
227
229
|
|
|
@@ -246,9 +248,30 @@ function resolveHarnessKeybinding(context: CommandContext, args: HarnessKeybindi
|
|
|
246
248
|
return null;
|
|
247
249
|
}
|
|
248
250
|
|
|
251
|
+
function keybindingModelRoute(action: KeyAction): string {
|
|
252
|
+
const route = keybindingOperationRoute(action);
|
|
253
|
+
if (route.preferredMode === 'run_keybinding') return `agent_harness mode:"run_keybinding" actionId:"${action}"`;
|
|
254
|
+
if (route.preferredMode === 'open_ui_surface' && route.surfaceId) return `agent_harness mode:"open_ui_surface" surfaceId:"${route.surfaceId}"`;
|
|
255
|
+
if (route.preferredMode === 'open_ui_surface') return 'agent_harness mode:"open_ui_surface"';
|
|
256
|
+
if (route.preferredMode === 'run_command' && route.command) return `agent_harness mode:"run_command" command:"${route.command}"`;
|
|
257
|
+
if (route.preferredMode === 'run_command') return 'agent_harness mode:"run_command"';
|
|
258
|
+
return 'direct-user-interaction';
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
function keybindingModelAccess(action: KeyAction, operation: KeybindingOperationRoute): Record<string, unknown> {
|
|
262
|
+
return {
|
|
263
|
+
inspect: `agent_harness mode:"keybinding" actionId:"${action}"`,
|
|
264
|
+
run: operation.supported ? `agent_harness mode:"run_keybinding" actionId:"${action}" confirm:true explicitUserRequest:"..."` : 'not exposed',
|
|
265
|
+
set: `agent_harness mode:"set_keybinding" actionId:"${action}" combo:{...} confirm:true explicitUserRequest:"..."`,
|
|
266
|
+
reset: `agent_harness mode:"reset_keybinding" actionId:"${action}" confirm:true explicitUserRequest:"..."`,
|
|
267
|
+
preferred: keybindingModelRoute(action),
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
|
|
249
271
|
function describeBinding(manager: KeybindingsManager | null, action: KeyAction, combos: KeyCombo[], lookup?: KeybindingLookup): Record<string, unknown> {
|
|
250
272
|
const defaults = DEFAULT_KEYBINDINGS[action];
|
|
251
273
|
const customized = !combosEqual(combos, defaults);
|
|
274
|
+
const modelOperation = keybindingOperationRoute(action);
|
|
252
275
|
return {
|
|
253
276
|
action,
|
|
254
277
|
description: ACTION_DESCRIPTIONS[action],
|
|
@@ -258,7 +281,10 @@ function describeBinding(manager: KeybindingsManager | null, action: KeyAction,
|
|
|
258
281
|
defaultBindings: defaults.map((combo) => describeCombo(manager, combo)),
|
|
259
282
|
customized,
|
|
260
283
|
source: manager ? (customized ? 'custom' : 'default') : 'default-fallback',
|
|
261
|
-
|
|
284
|
+
modelRoute: keybindingModelRoute(action),
|
|
285
|
+
inspectRoute: `agent_harness mode:"keybinding" actionId:"${action}"`,
|
|
286
|
+
modelAccess: keybindingModelAccess(action, modelOperation),
|
|
287
|
+
modelOperation,
|
|
262
288
|
};
|
|
263
289
|
}
|
|
264
290
|
|
|
@@ -270,7 +296,7 @@ function keybindingOperationRoute(action: KeyAction): KeybindingOperationRoute {
|
|
|
270
296
|
effect: 'shell-action',
|
|
271
297
|
preferredMode: 'run_keybinding',
|
|
272
298
|
confirmation: 'agent_harness mode:"run_keybinding" requires confirm:true and explicitUserRequest.',
|
|
273
|
-
note: '
|
|
299
|
+
note: 'Runs the available cancel-generation route. Prompt clearing and double-press exit remain direct user interaction.',
|
|
274
300
|
};
|
|
275
301
|
case 'screen-clear':
|
|
276
302
|
return {
|
|
@@ -278,7 +304,7 @@ function keybindingOperationRoute(action: KeyAction): KeybindingOperationRoute {
|
|
|
278
304
|
effect: 'shell-action',
|
|
279
305
|
preferredMode: 'run_keybinding',
|
|
280
306
|
confirmation: 'agent_harness mode:"run_keybinding" requires confirm:true and explicitUserRequest.',
|
|
281
|
-
note: '
|
|
307
|
+
note: 'Runs the available clear-screen route.',
|
|
282
308
|
};
|
|
283
309
|
case 'panel-picker':
|
|
284
310
|
return {
|
|
@@ -295,7 +321,7 @@ function keybindingOperationRoute(action: KeyAction): KeybindingOperationRoute {
|
|
|
295
321
|
effect: 'visible-ui-navigation',
|
|
296
322
|
preferredMode: 'run_keybinding',
|
|
297
323
|
confirmation: 'agent_harness mode:"run_keybinding" requires confirm:true and explicitUserRequest.',
|
|
298
|
-
note: 'Dismisses
|
|
324
|
+
note: 'Dismisses Agent workspace first. If it is not active, closes the active panel and focuses the prompt when focus is available.',
|
|
299
325
|
};
|
|
300
326
|
case 'panel-close-all':
|
|
301
327
|
return {
|
|
@@ -303,7 +329,7 @@ function keybindingOperationRoute(action: KeyAction): KeybindingOperationRoute {
|
|
|
303
329
|
effect: 'visible-ui-navigation',
|
|
304
330
|
preferredMode: 'run_keybinding',
|
|
305
331
|
confirmation: 'agent_harness mode:"run_keybinding" requires confirm:true and explicitUserRequest.',
|
|
306
|
-
note: 'Dismisses
|
|
332
|
+
note: 'Dismisses Agent workspace first. If it is not active, closes open panels and focuses the prompt when focus is available.',
|
|
307
333
|
};
|
|
308
334
|
case 'history-search':
|
|
309
335
|
return {
|
|
@@ -330,7 +356,7 @@ function keybindingOperationRoute(action: KeyAction): KeybindingOperationRoute {
|
|
|
330
356
|
preferredMode: 'run_keybinding',
|
|
331
357
|
command: '/paste',
|
|
332
358
|
confirmation: 'agent_harness mode:"run_keybinding" requires confirm:true and explicitUserRequest.',
|
|
333
|
-
note: '
|
|
359
|
+
note: 'Runs the paste route and reports whether text, image, or nothing was pasted.',
|
|
334
360
|
};
|
|
335
361
|
case 'block-copy':
|
|
336
362
|
case 'bookmark':
|
|
@@ -408,13 +434,38 @@ export function totalHarnessShortcuts(context: CommandContext): number {
|
|
|
408
434
|
return totalHarnessKeybindings(context) + FIXED_SHORTCUTS.length;
|
|
409
435
|
}
|
|
410
436
|
|
|
437
|
+
function fixedShortcutModelRoute(shortcut: Record<string, string>): string {
|
|
438
|
+
if (shortcut.key.includes('/shortcuts')) return 'agent_harness mode:"shortcuts"';
|
|
439
|
+
if (shortcut.key.includes('/keybindings')) return 'agent_harness mode:"keybindings"';
|
|
440
|
+
if (shortcut.key.includes('?') || shortcut.key.includes('F1')) return 'agent_harness mode:"open_ui_surface" surfaceId:"help-overlay"';
|
|
441
|
+
if (shortcut.key.includes('F2')) return 'agent_harness mode:"open_ui_surface" surfaceId:"process-monitor"';
|
|
442
|
+
if (shortcut.key.includes('Esc')) return 'direct-user-interaction';
|
|
443
|
+
if (shortcut.key.includes('Tab')) return 'agent_harness mode:"commands"';
|
|
444
|
+
if (shortcut.key.includes('Enter')) return 'main conversation';
|
|
445
|
+
return 'direct-user-interaction';
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function describeFixedShortcut(shortcut: Record<string, string>): Record<string, unknown> {
|
|
449
|
+
return {
|
|
450
|
+
...shortcut,
|
|
451
|
+
source: 'fixed',
|
|
452
|
+
userEditable: false,
|
|
453
|
+
modelRoute: fixedShortcutModelRoute(shortcut),
|
|
454
|
+
modelAccess: {
|
|
455
|
+
inspectShortcuts: 'agent_harness mode:"shortcuts"',
|
|
456
|
+
inspectKeybindings: 'agent_harness mode:"keybindings"',
|
|
457
|
+
preferred: fixedShortcutModelRoute(shortcut),
|
|
458
|
+
},
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
|
|
411
462
|
export function listHarnessShortcuts(context: CommandContext, args: HarnessKeybindingArgs): Record<string, unknown> {
|
|
412
463
|
const keybindings = listHarnessKeybindings(context, args);
|
|
413
464
|
const query = readString(args.query).toLowerCase();
|
|
414
465
|
const fixed = FIXED_SHORTCUTS
|
|
415
466
|
.filter((shortcut) => !query || `${shortcut.key}\n${shortcut.description}`.toLowerCase().includes(query))
|
|
416
467
|
.slice(0, readLimit(args.limit, 200))
|
|
417
|
-
.map(
|
|
468
|
+
.map(describeFixedShortcut);
|
|
418
469
|
const degraded = keybindings.status === 'degraded';
|
|
419
470
|
return {
|
|
420
471
|
status: degraded ? 'degraded' : 'available',
|
|
@@ -496,11 +547,11 @@ export function runHarnessKeybinding(context: CommandContext, args: HarnessKeybi
|
|
|
496
547
|
|
|
497
548
|
switch (resolved.action) {
|
|
498
549
|
case 'clear-cancel':
|
|
499
|
-
if (!context.cancelGeneration) return runUnavailable(resolved.action, route, '
|
|
550
|
+
if (!context.cancelGeneration) return runUnavailable(resolved.action, route, 'Cancel-generation route is unavailable.');
|
|
500
551
|
context.cancelGeneration();
|
|
501
552
|
return { status: 'executed', action: resolved.action, effect: 'cancel-generation', keybinding: descriptor };
|
|
502
553
|
case 'screen-clear':
|
|
503
|
-
if (!context.clearScreen) return runUnavailable(resolved.action, route, '
|
|
554
|
+
if (!context.clearScreen) return runUnavailable(resolved.action, route, 'Clear-screen route is unavailable.');
|
|
504
555
|
context.clearScreen();
|
|
505
556
|
return { status: 'executed', action: resolved.action, effect: 'screen-clear', keybinding: descriptor };
|
|
506
557
|
case 'panel-picker':
|
|
@@ -512,7 +563,7 @@ export function runHarnessKeybinding(context: CommandContext, args: HarnessKeybi
|
|
|
512
563
|
context.openAgentWorkspace('home');
|
|
513
564
|
return { status: 'executed', action: resolved.action, effect: 'agent-workspace-opened', route: 'openAgentWorkspace', categoryId: 'home', keybinding: descriptor };
|
|
514
565
|
}
|
|
515
|
-
return runUnavailable(resolved.action, route, 'No panel picker or Agent workspace
|
|
566
|
+
return runUnavailable(resolved.action, route, 'No panel picker or Agent workspace route is available.');
|
|
516
567
|
case 'panel-close': {
|
|
517
568
|
const dismissedAgentWorkspace = context.dismissAgentWorkspace?.() ?? false;
|
|
518
569
|
if (dismissedAgentWorkspace) {
|
|
@@ -526,7 +577,7 @@ export function runHarnessKeybinding(context: CommandContext, args: HarnessKeybi
|
|
|
526
577
|
}
|
|
527
578
|
const active = context.workspace.panelManager?.getActivePanel() ?? null;
|
|
528
579
|
if (active) context.workspace.panelManager?.close(active.id);
|
|
529
|
-
if (!active && !context.focusPrompt) return runUnavailable(resolved.action, route, 'No active Agent workspace, active
|
|
580
|
+
if (!active && !context.focusPrompt) return runUnavailable(resolved.action, route, 'No active Agent workspace, active panel, or prompt focus route is available.');
|
|
530
581
|
if (context.focusPrompt) context.focusPrompt();
|
|
531
582
|
context.renderRequest();
|
|
532
583
|
return {
|
|
@@ -552,7 +603,7 @@ export function runHarnessKeybinding(context: CommandContext, args: HarnessKeybi
|
|
|
552
603
|
const openPanels = managerPanel?.getAllOpen() ?? [];
|
|
553
604
|
for (const panel of openPanels) managerPanel?.close(panel.id);
|
|
554
605
|
managerPanel?.hide();
|
|
555
|
-
if (openPanels.length === 0 && !context.focusPrompt) return runUnavailable(resolved.action, route, 'No active Agent workspace, open
|
|
606
|
+
if (openPanels.length === 0 && !context.focusPrompt) return runUnavailable(resolved.action, route, 'No active Agent workspace, open panels, or prompt focus route is available.');
|
|
556
607
|
if (context.focusPrompt) context.focusPrompt();
|
|
557
608
|
context.renderRequest();
|
|
558
609
|
return {
|
|
@@ -564,26 +615,26 @@ export function runHarnessKeybinding(context: CommandContext, args: HarnessKeybi
|
|
|
564
615
|
};
|
|
565
616
|
}
|
|
566
617
|
case 'history-search': {
|
|
567
|
-
if (!context.openPromptHistorySearch) return runUnavailable(resolved.action, route, '
|
|
618
|
+
if (!context.openPromptHistorySearch) return runUnavailable(resolved.action, route, 'Prompt history search route is unavailable.');
|
|
568
619
|
const query = readString(args.value);
|
|
569
620
|
context.openPromptHistorySearch(query || undefined);
|
|
570
621
|
return { status: 'executed', action: resolved.action, effect: 'prompt-history-search-opened', query, keybinding: descriptor };
|
|
571
622
|
}
|
|
572
623
|
case 'search': {
|
|
573
|
-
if (!context.openConversationSearch) return runUnavailable(resolved.action, route, '
|
|
624
|
+
if (!context.openConversationSearch) return runUnavailable(resolved.action, route, 'Conversation search route is unavailable.');
|
|
574
625
|
const query = readString(args.value);
|
|
575
626
|
context.openConversationSearch(query || undefined);
|
|
576
627
|
return { status: 'executed', action: resolved.action, effect: 'conversation-search-opened', query, keybinding: descriptor };
|
|
577
628
|
}
|
|
578
629
|
case 'paste': {
|
|
579
|
-
if (!context.pasteFromClipboard) return runUnavailable(resolved.action, route, '
|
|
630
|
+
if (!context.pasteFromClipboard) return runUnavailable(resolved.action, route, 'Paste route is unavailable.');
|
|
580
631
|
const pasted = context.pasteFromClipboard();
|
|
581
632
|
return { status: 'executed', action: resolved.action, effect: 'paste-from-clipboard', pasted, keybinding: descriptor };
|
|
582
633
|
}
|
|
583
634
|
case 'block-copy':
|
|
584
635
|
case 'bookmark':
|
|
585
636
|
case 'block-save': {
|
|
586
|
-
if (!context.openBlockActions) return runUnavailable(resolved.action, route, '
|
|
637
|
+
if (!context.openBlockActions) return runUnavailable(resolved.action, route, 'Block action surface route is unavailable.');
|
|
587
638
|
const opened = context.openBlockActions();
|
|
588
639
|
return opened
|
|
589
640
|
? {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CommandContext } from '../input/command-registry.ts';
|
|
2
|
+
import { previewHarnessText } from './agent-harness-text.ts';
|
|
2
3
|
|
|
3
4
|
export interface AgentHarnessMcpArgs {
|
|
4
5
|
readonly mcpServerId?: unknown;
|
|
@@ -76,9 +77,14 @@ function describeCandidate(server: McpServerRecord): Record<string, unknown> {
|
|
|
76
77
|
trustMode: server.trustMode,
|
|
77
78
|
role: server.role,
|
|
78
79
|
schemaFreshness: server.schemaFreshness,
|
|
80
|
+
modelRoute: mcpServerModelRoute(),
|
|
79
81
|
};
|
|
80
82
|
}
|
|
81
83
|
|
|
84
|
+
function mcpServerModelRoute(): string {
|
|
85
|
+
return 'agent_harness mode:"mcp_server" or mode:"run_command"';
|
|
86
|
+
}
|
|
87
|
+
|
|
82
88
|
function toolsByServer(tools: readonly McpToolRecord[]): ReadonlyMap<string, readonly McpToolRecord[]> {
|
|
83
89
|
const grouped = new Map<string, McpToolRecord[]>();
|
|
84
90
|
for (const tool of tools) {
|
|
@@ -108,6 +114,7 @@ function describeServer(
|
|
|
108
114
|
allowedHostCount: server.allowedHosts.length,
|
|
109
115
|
...(server.quarantineReason ? { quarantineReason: server.quarantineReason } : {}),
|
|
110
116
|
...(server.quarantineDetail ? { quarantineDetail: server.quarantineDetail } : {}),
|
|
117
|
+
modelRoute: mcpServerModelRoute(),
|
|
111
118
|
...(options.lookup ? { lookup: options.lookup } : {}),
|
|
112
119
|
...(options.includeParameters ? {
|
|
113
120
|
tools: tools.map((tool) => ({
|
|
@@ -115,8 +122,6 @@ function describeServer(
|
|
|
115
122
|
...(tool.description ? { description: tool.description } : {}),
|
|
116
123
|
})),
|
|
117
124
|
toolCount: tools.length,
|
|
118
|
-
} : { toolCount: tools.length }),
|
|
119
|
-
...(options.includeParameters ? {
|
|
120
125
|
policy: {
|
|
121
126
|
effect: 'read-only',
|
|
122
127
|
values: 'Server posture returns trust, role, connection, quarantine, and tool metadata; env values and secret config values are never returned.',
|
|
@@ -145,7 +150,10 @@ function describeServer(
|
|
|
145
150
|
`/mcp remove ${server.name} --yes`,
|
|
146
151
|
],
|
|
147
152
|
},
|
|
148
|
-
} : {
|
|
153
|
+
} : {
|
|
154
|
+
toolCount: tools.length,
|
|
155
|
+
summary: previewHarnessText(`${server.connected ? 'connected' : 'disconnected'} ${server.trustMode} ${server.schemaFreshness}`),
|
|
156
|
+
}),
|
|
149
157
|
};
|
|
150
158
|
}
|
|
151
159
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { buildAgentWorkspaceVoiceMediaReadiness } from '../input/agent-workspace-voice-media.ts';
|
|
2
2
|
import type { AgentWorkspaceVoiceMediaProviderStatus } from '../input/agent-workspace-voice-media.ts';
|
|
3
3
|
import type { CommandContext } from '../input/command-registry.ts';
|
|
4
|
+
import { previewHarnessText } from './agent-harness-text.ts';
|
|
4
5
|
|
|
5
6
|
export interface AgentHarnessMediaArgs {
|
|
6
7
|
readonly mediaProviderId?: unknown;
|
|
@@ -77,9 +78,14 @@ function describeProviderCandidate(provider: AgentWorkspaceVoiceMediaProviderSta
|
|
|
77
78
|
label: provider.label,
|
|
78
79
|
setupState: provider.setupState,
|
|
79
80
|
selected: provider.selected,
|
|
81
|
+
modelRoute: mediaProviderModelRoute(),
|
|
80
82
|
};
|
|
81
83
|
}
|
|
82
84
|
|
|
85
|
+
function mediaProviderModelRoute(): string {
|
|
86
|
+
return 'agent_media_generate or agent_harness mode:"media_provider"';
|
|
87
|
+
}
|
|
88
|
+
|
|
83
89
|
function statusMap(statuses: readonly RuntimeProviderStatus[]): ReadonlyMap<string, RuntimeProviderStatus> {
|
|
84
90
|
return new Map(statuses.map((status) => [status.id, status]));
|
|
85
91
|
}
|
|
@@ -103,27 +109,32 @@ function describeProvider(
|
|
|
103
109
|
configuredSecretKeyNames: provider.configuredSecretKeys,
|
|
104
110
|
missingSecretKeyNames: provider.missingSecretKeyOptions,
|
|
105
111
|
nextStep: provider.nextStep,
|
|
112
|
+
modelRoute: mediaProviderModelRoute(),
|
|
106
113
|
...(runtimeStatus ? {
|
|
107
114
|
runtimeStatus: {
|
|
108
115
|
state: runtimeStatus.state,
|
|
109
116
|
configured: runtimeStatus.configured,
|
|
110
|
-
...(runtimeStatus.detail ? { detail: runtimeStatus.detail } : {}),
|
|
117
|
+
...(options.includeParameters && runtimeStatus.detail ? { detail: runtimeStatus.detail } : {}),
|
|
111
118
|
},
|
|
112
119
|
} : {}),
|
|
113
120
|
...(options.lookup ? { lookup: options.lookup } : {}),
|
|
114
|
-
...(options.includeParameters
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
121
|
+
...(options.includeParameters
|
|
122
|
+
? {
|
|
123
|
+
modelRoutes: {
|
|
124
|
+
inspectPosture: 'agent_harness mode:"media_posture"',
|
|
125
|
+
inspectProvider: 'agent_harness mode:"media_provider"',
|
|
126
|
+
generateMedia: 'agent_media_generate with confirm:true and explicitUserRequest',
|
|
127
|
+
ttsSettings: 'agent_harness mode:"settings", mode:"get_setting", mode:"set_setting" for tts.provider, tts.voice, tts.llmProvider, and tts.llmModel',
|
|
128
|
+
},
|
|
129
|
+
policy: {
|
|
130
|
+
effect: 'read-only',
|
|
131
|
+
values: 'Provider posture returns capability, setup, selected, health, and safe environment key names only; secret values and media payloads are never returned.',
|
|
132
|
+
mutation: 'Media generation, voice enable/disable, TTS setting changes, and bundle export stay explicit confirmation-gated tool, setting, workspace, or slash-command flows.',
|
|
133
|
+
},
|
|
134
|
+
}
|
|
135
|
+
: {
|
|
136
|
+
summary: previewHarnessText(provider.nextStep || `${provider.domain} provider ${provider.setupState}`),
|
|
137
|
+
}),
|
|
127
138
|
};
|
|
128
139
|
}
|
|
129
140
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
|
|
2
2
|
import type { CommandContext } from '../input/command-registry.ts';
|
|
3
3
|
import { resolveAgentConnectedHostConnection } from '../agent/routine-schedule-promotion.ts';
|
|
4
|
+
import { previewHarnessText } from './agent-harness-text.ts';
|
|
4
5
|
|
|
5
6
|
export interface CommandExecutionPolicy {
|
|
6
7
|
readonly effect: 'read-only' | 'local-state' | 'connected-host-state' | 'external-network' | 'ui-navigation' | 'session-lifecycle' | 'delegated-work' | 'mixed' | 'unknown';
|
|
@@ -269,7 +270,7 @@ export function describeCommandPolicy(commandName: string): CommandExecutionPoli
|
|
|
269
270
|
return {
|
|
270
271
|
effect: 'ui-navigation',
|
|
271
272
|
confirmation,
|
|
272
|
-
preferredModelTool: root === 'bookmarks' ? agentHarnessModes('open_ui_surface') : agentHarnessModes('run_command'),
|
|
273
|
+
preferredModelTool: root === 'bookmarks' ? `${agentHarnessModes('open_ui_surface')} or ${agentHarnessModes('run_command')}` : agentHarnessModes('run_command'),
|
|
273
274
|
boundary: 'Conversation display navigation mutates only the visible transcript view or scroll position.',
|
|
274
275
|
};
|
|
275
276
|
}
|
|
@@ -331,7 +332,7 @@ export function describeCliCommandPolicy(commandName: string): CommandExecutionP
|
|
|
331
332
|
return {
|
|
332
333
|
effect: 'unknown',
|
|
333
334
|
confirmation,
|
|
334
|
-
boundary: 'Blocked package CLI token. Agent can launch its own TUI and use public connected-host routes, but it does not manage connected-host lifecycle, listeners, servers,
|
|
335
|
+
boundary: 'Blocked package CLI token. Agent can launch its own TUI and use public connected-host routes, but it does not manage connected-host lifecycle, listeners, servers, route relays, remotes, web surfaces, or webhook listeners.',
|
|
335
336
|
};
|
|
336
337
|
}
|
|
337
338
|
if (root === 'tui' || root === 'onboarding' || root === 'help' || root === 'version' || root === 'completion') {
|
|
@@ -341,7 +342,7 @@ export function describeCliCommandPolicy(commandName: string): CommandExecutionP
|
|
|
341
342
|
preferredModelTool: root === 'onboarding' || root === 'tui'
|
|
342
343
|
? agentHarnessModes('workspace', 'workspace_actions', 'workspace_action', 'run_workspace_action')
|
|
343
344
|
: agentHarnessModes('cli_commands', 'cli_command'),
|
|
344
|
-
boundary: 'Top-level CLI launch, setup, help, version, and completion commands are package entrypoint surfaces; use in-process workspace and slash-command
|
|
345
|
+
boundary: 'Top-level CLI launch, setup, help, version, and completion commands are package entrypoint surfaces; use in-process workspace and slash-command routes from the model when operating inside the TUI.',
|
|
345
346
|
};
|
|
346
347
|
}
|
|
347
348
|
if (root === 'run') {
|
|
@@ -405,9 +406,30 @@ function toolIsAvailable(toolRegistry: ToolRegistry, toolName: string): boolean
|
|
|
405
406
|
return toolRegistry.getToolDefinitions().some((tool) => tool.name === toolName);
|
|
406
407
|
}
|
|
407
408
|
|
|
409
|
+
function connectedHostCapabilityModelRoute(capability: Record<string, unknown>): string {
|
|
410
|
+
const modelTools = Array.isArray(capability.modelTools)
|
|
411
|
+
? capability.modelTools.filter((tool): tool is string => typeof tool === 'string')
|
|
412
|
+
: [];
|
|
413
|
+
if (modelTools.length > 0) return previewHarnessText(modelTools.join(' or '));
|
|
414
|
+
return 'agent_harness mode:"connected_host_capability"';
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function blockedConnectedHostModelRoute(): string {
|
|
418
|
+
return 'agent_harness mode:"service_posture" or mode:"connected_host_status"';
|
|
419
|
+
}
|
|
420
|
+
|
|
408
421
|
export function connectedHostCapabilityMap(toolRegistry: ToolRegistry): readonly Record<string, unknown>[] {
|
|
409
422
|
const withAvailability = (capability: Record<string, unknown> & { readonly modelTools: readonly string[] }): Record<string, unknown> => ({
|
|
410
423
|
...capability,
|
|
424
|
+
modelRoute: connectedHostCapabilityModelRoute(capability),
|
|
425
|
+
harnessRoute: 'agent_harness mode:"connected_host_capability"',
|
|
426
|
+
modelAccess: {
|
|
427
|
+
inspectCapability: 'agent_harness mode:"connected_host_capability"',
|
|
428
|
+
liveStatus: 'agent_harness mode:"connected_host_status"',
|
|
429
|
+
endpointPosture: 'agent_harness mode:"service_posture"',
|
|
430
|
+
routeFamilies: 'agent_harness mode:"connected_host" includeParameters:true',
|
|
431
|
+
operate: connectedHostCapabilityModelRoute(capability),
|
|
432
|
+
},
|
|
411
433
|
available: capability.modelTools.every((toolName) => toolIsAvailable(toolRegistry, toolName)),
|
|
412
434
|
});
|
|
413
435
|
return [
|
|
@@ -510,6 +532,7 @@ export function connectedHostRouteFamilies(): readonly Record<string, unknown>[]
|
|
|
510
532
|
id: 'agent-knowledge',
|
|
511
533
|
prefixes: ['/api/goodvibes-agent/knowledge/*'],
|
|
512
534
|
modelTools: ['agent_knowledge', 'agent_knowledge_ingest'],
|
|
535
|
+
modelRoute: 'agent_knowledge or agent_knowledge_ingest',
|
|
513
536
|
boundary: 'Agent-owned knowledge segment only; no fallback to default or non-Agent knowledge.',
|
|
514
537
|
},
|
|
515
538
|
{
|
|
@@ -522,24 +545,28 @@ export function connectedHostRouteFamilies(): readonly Record<string, unknown>[]
|
|
|
522
545
|
'/api/runtime/scheduler',
|
|
523
546
|
],
|
|
524
547
|
modelTools: ['agent_operator_briefing'],
|
|
548
|
+
modelRoute: 'agent_operator_briefing',
|
|
525
549
|
boundary: 'Read-only public operator briefing routes.',
|
|
526
550
|
},
|
|
527
551
|
{
|
|
528
552
|
id: 'operator-actions',
|
|
529
553
|
routes: ['public operator action methods for approvals, automation jobs, automation runs, and schedules'],
|
|
530
554
|
modelTools: ['agent_operator_action'],
|
|
555
|
+
modelRoute: 'agent_operator_action',
|
|
531
556
|
boundary: 'Allowlisted confirmed mutations only; no arbitrary route invocation.',
|
|
532
557
|
},
|
|
533
558
|
{
|
|
534
559
|
id: 'delivery',
|
|
535
560
|
routes: ['configured channel, notification, and delivery targets'],
|
|
536
561
|
modelTools: ['agent_channel_send', 'agent_notify'],
|
|
562
|
+
modelRoute: 'agent_channel_send or agent_notify',
|
|
537
563
|
boundary: 'Explicit user-approved delivery only; no route/account creation.',
|
|
538
564
|
},
|
|
539
565
|
{
|
|
540
566
|
id: 'connected-schedules',
|
|
541
567
|
routes: ['public schedule creation/run routes'],
|
|
542
568
|
modelTools: ['agent_reminder_schedule', 'agent_operator_action'],
|
|
569
|
+
modelRoute: 'agent_reminder_schedule or agent_operator_action',
|
|
543
570
|
boundary: 'Connected schedules only; no hidden local scheduler or separate Agent job.',
|
|
544
571
|
},
|
|
545
572
|
];
|
|
@@ -582,6 +609,9 @@ function describeConnectedHostCapabilityCandidates(
|
|
|
582
609
|
capabilityId: typeof entry.capability.id === 'string' ? entry.capability.id : '',
|
|
583
610
|
purpose: typeof entry.capability.purpose === 'string' ? entry.capability.purpose : undefined,
|
|
584
611
|
reason: typeof entry.capability.reason === 'string' ? entry.capability.reason : undefined,
|
|
612
|
+
modelRoute: entry.status === 'allowed'
|
|
613
|
+
? connectedHostCapabilityModelRoute(entry.capability)
|
|
614
|
+
: blockedConnectedHostModelRoute(),
|
|
585
615
|
}));
|
|
586
616
|
}
|
|
587
617
|
|
|
@@ -590,18 +620,36 @@ function connectedHostCapabilityDetail(entry: { readonly status: 'allowed' | 'bl
|
|
|
590
620
|
return {
|
|
591
621
|
status: 'allowed',
|
|
592
622
|
capability: entry.capability,
|
|
623
|
+
modelRoute: connectedHostCapabilityModelRoute(entry.capability),
|
|
624
|
+
harnessRoute: 'agent_harness mode:"connected_host_capability"',
|
|
593
625
|
relatedRouteFamilies: relatedConnectedHostRouteFamilies(entry.capability),
|
|
626
|
+
modelAccess: {
|
|
627
|
+
inspectCapability: 'agent_harness mode:"connected_host_capability"',
|
|
628
|
+
connectedHostInventory: 'agent_harness mode:"connected_host" includeParameters:true',
|
|
629
|
+
liveStatus: 'agent_harness mode:"connected_host_status"',
|
|
630
|
+
endpointPosture: 'agent_harness mode:"service_posture"',
|
|
631
|
+
operate: connectedHostCapabilityModelRoute(entry.capability),
|
|
632
|
+
},
|
|
594
633
|
operatorMethodMode: 'Use agent_harness mode:"operator_methods" for the public operator and Agent Knowledge method catalog. Use mode:"operator_method" for one method.',
|
|
595
634
|
servicePostureMode: 'Use agent_harness mode:"service_posture" for endpoint binding, network-facing posture, issue, and redacted-log diagnostics. Use mode:"service_endpoint" for one endpoint.',
|
|
596
|
-
statusMode: 'Use agent_harness mode:"connected_host_status" for live read-only reachability,
|
|
597
|
-
boundary: 'Use only the listed first-class model tools, slash-command families, and workspace categories. Mutations still require explicit confirmation through those tools or command
|
|
635
|
+
statusMode: 'Use agent_harness mode:"connected_host_status" for live read-only reachability, token posture, and Agent Knowledge route readiness.',
|
|
636
|
+
boundary: 'Use only the listed first-class model tools, slash-command families, and workspace categories. Mutations still require explicit confirmation through those tools or command routes.',
|
|
598
637
|
};
|
|
599
638
|
}
|
|
600
639
|
return {
|
|
601
640
|
status: 'blocked',
|
|
602
641
|
capability: entry.capability,
|
|
642
|
+
modelRoute: blockedConnectedHostModelRoute(),
|
|
643
|
+
harnessRoute: 'agent_harness mode:"connected_host_capability"',
|
|
603
644
|
allowed: false,
|
|
604
645
|
available: false,
|
|
646
|
+
modelAccess: {
|
|
647
|
+
inspectCapability: 'agent_harness mode:"connected_host_capability"',
|
|
648
|
+
connectedHostInventory: 'agent_harness mode:"connected_host" includeParameters:true',
|
|
649
|
+
liveStatus: 'agent_harness mode:"connected_host_status"',
|
|
650
|
+
endpointPosture: 'agent_harness mode:"service_posture"',
|
|
651
|
+
operate: 'not exposed',
|
|
652
|
+
},
|
|
605
653
|
boundary: 'This connected-host surface is intentionally not exposed to the model as an Agent operation.',
|
|
606
654
|
servicePostureMode: 'Use agent_harness mode:"service_posture" or mode:"service_endpoint" only for read-only endpoint diagnostics.',
|
|
607
655
|
statusMode: 'Use agent_harness mode:"connected_host_status" only for read-only readiness diagnostics.',
|
|
@@ -652,6 +700,17 @@ export function connectedHostSummary(
|
|
|
652
700
|
operatorMethods: agentHarnessModes('operator_methods', 'operator_method'),
|
|
653
701
|
liveStatus: agentHarnessModes('connected_host_status'),
|
|
654
702
|
capabilityDetail: agentHarnessModes('connected_host_capability'),
|
|
703
|
+
daemonAliases: agentHarnessModes('daemon', 'daemon_status'),
|
|
704
|
+
},
|
|
705
|
+
modelRoute: 'agent_harness mode:"connected_host" or mode:"connected_host_capability"',
|
|
706
|
+
modelAccess: {
|
|
707
|
+
inventory: 'agent_harness mode:"connected_host" includeParameters:true',
|
|
708
|
+
liveStatus: 'agent_harness mode:"connected_host_status"',
|
|
709
|
+
capabilityDetail: 'agent_harness mode:"connected_host_capability" capabilityId:"..."',
|
|
710
|
+
servicePosture: 'agent_harness mode:"service_posture"',
|
|
711
|
+
daemonAliases: 'agent_harness mode:"daemon" or mode:"daemon_status"',
|
|
712
|
+
daemonStatusAlias: 'agent_harness mode:"daemon_status"',
|
|
713
|
+
lifecycleBlocked: 'start, stop, restart, install, upgrade, expose-listener, and listener mutation are not exposed through Agent.',
|
|
655
714
|
},
|
|
656
715
|
counts: {
|
|
657
716
|
routeFamilies: routeFamilies.length,
|
|
@@ -672,22 +731,54 @@ export function blockedConnectedHostCapabilities(): readonly Record<string, unkn
|
|
|
672
731
|
{
|
|
673
732
|
id: 'connected-host-lifecycle',
|
|
674
733
|
blocked: ['start', 'stop', 'restart', 'install', 'upgrade', 'expose-listener', 'mutate-listener'],
|
|
734
|
+
modelRoute: blockedConnectedHostModelRoute(),
|
|
735
|
+
harnessRoute: 'agent_harness mode:"connected_host_capability"',
|
|
736
|
+
modelAccess: {
|
|
737
|
+
inspectCapability: 'agent_harness mode:"connected_host_capability"',
|
|
738
|
+
liveStatus: 'agent_harness mode:"connected_host_status"',
|
|
739
|
+
endpointPosture: 'agent_harness mode:"service_posture"',
|
|
740
|
+
operate: 'not exposed',
|
|
741
|
+
},
|
|
675
742
|
reason: 'The connected host and listener are externally owned by GoodVibes; Agent can use public operator routes but not manage hosting.',
|
|
676
743
|
},
|
|
677
744
|
{
|
|
678
745
|
id: 'non-agent-knowledge',
|
|
679
746
|
blocked: ['default-knowledge', 'non-agent-knowledge-segments', 'fallback-knowledge'],
|
|
747
|
+
modelRoute: blockedConnectedHostModelRoute(),
|
|
748
|
+
harnessRoute: 'agent_harness mode:"connected_host_capability"',
|
|
749
|
+
modelAccess: {
|
|
750
|
+
inspectCapability: 'agent_harness mode:"connected_host_capability"',
|
|
751
|
+
allowedAgentKnowledge: 'agent_knowledge or agent_knowledge_ingest',
|
|
752
|
+
liveStatus: 'agent_harness mode:"connected_host_status"',
|
|
753
|
+
operate: 'not exposed',
|
|
754
|
+
},
|
|
680
755
|
reason: 'Agent model tools must stay inside the isolated Agent Knowledge route family.',
|
|
681
756
|
},
|
|
682
757
|
{
|
|
683
758
|
id: 'hidden-background-work',
|
|
684
759
|
blocked: ['separate-agent-jobs', 'implicit-delegated-review', 'local-schedulers'],
|
|
760
|
+
modelRoute: blockedConnectedHostModelRoute(),
|
|
761
|
+
harnessRoute: 'agent_harness mode:"connected_host_capability"',
|
|
762
|
+
modelAccess: {
|
|
763
|
+
inspectCapability: 'agent_harness mode:"connected_host_capability"',
|
|
764
|
+
allowedDelegation: 'agent_harness mode:"delegation_posture"',
|
|
765
|
+
liveStatus: 'agent_harness mode:"connected_host_status"',
|
|
766
|
+
operate: 'not exposed',
|
|
767
|
+
},
|
|
685
768
|
reason: 'All model work is serial and visible unless the user explicitly requests delegation through an exposed surface.',
|
|
686
769
|
},
|
|
687
770
|
{
|
|
688
771
|
id: 'arbitrary-connected-host-mutations',
|
|
689
772
|
blocked: ['route-discovery-mutation', 'account-creation', 'automation-definition-creation'],
|
|
690
|
-
|
|
773
|
+
modelRoute: blockedConnectedHostModelRoute(),
|
|
774
|
+
harnessRoute: 'agent_harness mode:"connected_host_capability"',
|
|
775
|
+
modelAccess: {
|
|
776
|
+
inspectCapability: 'agent_harness mode:"connected_host_capability"',
|
|
777
|
+
allowedActions: 'agent_operator_action for documented allowlisted mutations only',
|
|
778
|
+
liveStatus: 'agent_harness mode:"connected_host_status"',
|
|
779
|
+
operate: 'not exposed',
|
|
780
|
+
},
|
|
781
|
+
reason: 'Only the documented allowlisted model tools and slash-command routes are exposed.',
|
|
691
782
|
},
|
|
692
783
|
];
|
|
693
784
|
}
|