@pellux/goodvibes-agent 1.0.16 → 1.0.18
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 +12 -0
- package/README.md +2 -2
- package/dist/package/main.js +447 -106
- package/docs/README.md +1 -1
- package/docs/getting-started.md +2 -2
- package/docs/tools-and-commands.md +5 -5
- package/package.json +1 -1
- package/src/agent/harness-control.ts +138 -3
- package/src/tools/agent-harness-keybinding-metadata.ts +83 -23
- package/src/tools/agent-harness-metadata.ts +2 -2
- package/src/tools/agent-harness-panel-metadata.ts +84 -14
- package/src/tools/agent-harness-tool-schema.ts +6 -6
- package/src/tools/agent-harness-tool.ts +43 -17
- package/src/tools/agent-harness-ui-surface-metadata.ts +75 -11
- package/src/version.ts +1 -1
|
@@ -23,7 +23,7 @@ export const AGENT_HARNESS_PARAMETER_PROPERTIES = {
|
|
|
23
23
|
},
|
|
24
24
|
query: {
|
|
25
25
|
type: 'string',
|
|
26
|
-
description: 'Search text for command, workspace action, setting,
|
|
26
|
+
description: 'Search text for command, panel, UI surface, keybinding, workspace action, setting, or tool catalogs; also slash-command, setting, panel, UI surface, or keybinding lookup for single-item modes.',
|
|
27
27
|
},
|
|
28
28
|
command: {
|
|
29
29
|
type: 'string',
|
|
@@ -48,15 +48,15 @@ export const AGENT_HARNESS_PARAMETER_PROPERTIES = {
|
|
|
48
48
|
},
|
|
49
49
|
surfaceId: {
|
|
50
50
|
type: 'string',
|
|
51
|
-
description: 'UI surface id for ui_surface or open_ui_surface modes.',
|
|
51
|
+
description: 'UI surface id for ui_surface or open_ui_surface modes. target or query can also look up one UI surface when the exact id is not known.',
|
|
52
52
|
},
|
|
53
53
|
panelId: {
|
|
54
54
|
type: 'string',
|
|
55
|
-
description: 'Built-in panel id for panel or open_panel modes.',
|
|
55
|
+
description: 'Built-in panel id for panel or open_panel modes. target or query can also look up one panel when the exact id is not known.',
|
|
56
56
|
},
|
|
57
57
|
actionId: {
|
|
58
58
|
type: 'string',
|
|
59
|
-
description: 'Agent workspace action id for workspace_action or run_workspace_action, or keybinding action id for keybinding/set_keybinding/reset_keybinding.',
|
|
59
|
+
description: 'Agent workspace action id for workspace_action or run_workspace_action, or keybinding action id for keybinding/set_keybinding/reset_keybinding. target or query can also look up one keybinding action.',
|
|
60
60
|
},
|
|
61
61
|
fields: {
|
|
62
62
|
type: 'object',
|
|
@@ -78,7 +78,7 @@ export const AGENT_HARNESS_PARAMETER_PROPERTIES = {
|
|
|
78
78
|
},
|
|
79
79
|
key: {
|
|
80
80
|
type: 'string',
|
|
81
|
-
description: 'Agent setting key for get_setting, set_setting, or reset_setting.',
|
|
81
|
+
description: 'Agent setting key for get_setting, set_setting, or reset_setting. target or query can also look up one setting when the exact key is not known.',
|
|
82
82
|
},
|
|
83
83
|
value: {
|
|
84
84
|
anyOf: [
|
|
@@ -90,7 +90,7 @@ export const AGENT_HARNESS_PARAMETER_PROPERTIES = {
|
|
|
90
90
|
},
|
|
91
91
|
target: {
|
|
92
92
|
type: 'string',
|
|
93
|
-
description: 'Optional lookup target, such as a model-picker target, workspace action id/search text, slash command root or invocation,
|
|
93
|
+
description: 'Optional lookup target, such as a model-picker target, panel id/search text, UI surface id/search text, workspace action id/search text, slash command root or invocation, setting key/search text, keybinding action/search text, model tool name, or connected-host capability id.',
|
|
94
94
|
},
|
|
95
95
|
capabilityId: {
|
|
96
96
|
type: 'string',
|
|
@@ -33,9 +33,9 @@ import {
|
|
|
33
33
|
} from './agent-harness-metadata.ts';
|
|
34
34
|
import {
|
|
35
35
|
formatHarnessError,
|
|
36
|
-
getHarnessSetting,
|
|
37
36
|
listHarnessSettings,
|
|
38
37
|
resetHarnessSetting,
|
|
38
|
+
resolveHarnessSetting,
|
|
39
39
|
setHarnessSetting,
|
|
40
40
|
} from '../agent/harness-control.ts';
|
|
41
41
|
|
|
@@ -109,6 +109,17 @@ function readString(value: unknown): string {
|
|
|
109
109
|
return typeof value === 'string' ? value.trim() : '';
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
function settingLookupArgs(args: AgentHarnessToolArgs) {
|
|
113
|
+
return {
|
|
114
|
+
key: readString(args.key) || undefined,
|
|
115
|
+
target: readString(args.target) || undefined,
|
|
116
|
+
query: readString(args.query) || undefined,
|
|
117
|
+
category: readString(args.category) || undefined,
|
|
118
|
+
prefix: readString(args.prefix) || undefined,
|
|
119
|
+
includeHidden: args.includeHidden === true,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
112
123
|
function readLimit(value: unknown, fallback: number): number {
|
|
113
124
|
const parsed = typeof value === 'string' && value.trim() ? Number(value) : value;
|
|
114
125
|
if (typeof parsed !== 'number' || !Number.isFinite(parsed)) return fallback;
|
|
@@ -584,12 +595,12 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
584
595
|
tools: deps.toolRegistry.getToolDefinitions().length,
|
|
585
596
|
modelAccess: {
|
|
586
597
|
cliCommands: 'Use mode:"cli_commands" and mode:"cli_command" to inspect package CLI mirrors and their preferred in-process model routes. CLI modes are discovery-only.',
|
|
587
|
-
panels: 'Use mode:"panels" and mode:"panel" to inspect built-in panel catalog/open state; use mode:"open_panel" with confirm:true plus explicitUserRequest to route a visible panel/workspace change.',
|
|
588
|
-
uiSurfaces: 'Use mode:"ui_surfaces" and mode:"ui_surface" to inspect modal/overlay/picker/workspace surfaces; use mode:"open_ui_surface" with confirm:true plus explicitUserRequest to route visible UI navigation.',
|
|
589
|
-
shortcuts: 'Use mode:"shortcuts" to inspect fixed shortcuts plus configurable keybindings. Use mode:"set_keybinding" and mode:"reset_keybinding" with confirm:true plus explicitUserRequest to edit the same config file the user edits.',
|
|
598
|
+
panels: 'Use mode:"panels" to list and mode:"panel" with panelId, target, or query to inspect built-in panel catalog/open state; use mode:"open_panel" with confirm:true plus explicitUserRequest to route a visible panel/workspace change.',
|
|
599
|
+
uiSurfaces: 'Use mode:"ui_surfaces" to list and mode:"ui_surface" with surfaceId, target, or query to inspect modal/overlay/picker/workspace surfaces; use mode:"open_ui_surface" with confirm:true plus explicitUserRequest to route visible UI navigation.',
|
|
600
|
+
shortcuts: 'Use mode:"shortcuts" to inspect fixed shortcuts plus configurable keybindings. Use mode:"keybinding" with actionId, target, key, or query; use mode:"set_keybinding" and mode:"reset_keybinding" with confirm:true plus explicitUserRequest to edit the same config file the user edits.',
|
|
590
601
|
slashCommands: 'Use mode:"commands" to list slash commands and mode:"command" with command, commandName, target, or query to inspect one command; use mode:"run_command" with confirm:true plus explicitUserRequest to execute.',
|
|
591
602
|
workspace: 'Use mode:"workspace_actions" to list and mode:"workspace_action" with actionId, command, target, or query for one action and editor schema; set includeParameters:true on workspace_actions to inline editor schemas.',
|
|
592
|
-
settings: 'Use mode:"settings"
|
|
603
|
+
settings: 'Use mode:"settings" to list and mode:"get_setting" with key, target, or query for one setting. Use mode:"set_setting" or mode:"reset_setting" with key, target, or query plus confirm:true and explicitUserRequest.',
|
|
593
604
|
tools: 'Use mode:"tools" to list first-class model tools, or mode:"tool" with toolName, target, or query to inspect one schema.',
|
|
594
605
|
connectedHost: 'Use mode:"connected_host" for the connected-host capability map and blocked boundaries. Use mode:"connected_host_capability" with capabilityId, target, or query for one allowed or blocked capability.',
|
|
595
606
|
connectedHostStatus: 'Use mode:"connected_host_status" for live read-only host reachability, SDK compatibility, token posture, and Agent Knowledge route readiness.',
|
|
@@ -622,7 +633,7 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
622
633
|
}
|
|
623
634
|
if (args.mode === 'panel') {
|
|
624
635
|
const panel = describeHarnessPanel(deps.commandContext, args);
|
|
625
|
-
return panel ? output(panel) : error(`Unknown panel ${readString(args.panelId || args.query) || '<missing>'}.`);
|
|
636
|
+
return panel ? output(panel) : error(`Unknown panel ${readString(args.panelId || args.target || args.query) || '<missing>'}.`);
|
|
626
637
|
}
|
|
627
638
|
if (args.mode === 'open_panel') {
|
|
628
639
|
const confirmationError = requireConfirmedAction(args, 'Panel routing');
|
|
@@ -635,7 +646,7 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
635
646
|
}
|
|
636
647
|
if (args.mode === 'ui_surface') {
|
|
637
648
|
const surface = describeHarnessUiSurface(deps.commandContext, args);
|
|
638
|
-
return surface ? output(surface) : error(`Unknown UI surface ${readString(args.surfaceId || args.query) || '<missing>'}.`);
|
|
649
|
+
return surface ? output(surface) : error(`Unknown UI surface ${readString(args.surfaceId || args.query || args.target) || '<missing>'}.`);
|
|
639
650
|
}
|
|
640
651
|
if (args.mode === 'open_ui_surface') {
|
|
641
652
|
const confirmationError = requireConfirmedAction(args, 'UI surface routing');
|
|
@@ -646,7 +657,7 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
646
657
|
if (args.mode === 'keybindings') return output(listHarnessKeybindings(deps.commandContext, args));
|
|
647
658
|
if (args.mode === 'keybinding') {
|
|
648
659
|
const binding = describeHarnessKeybinding(deps.commandContext, args);
|
|
649
|
-
return binding ? output(binding) : error(`Unknown keybinding action ${readString(args.actionId || args.key || args.query) || '<missing>'}.`);
|
|
660
|
+
return binding ? output(binding) : error(`Unknown keybinding action ${readString(args.actionId || args.target || args.key || args.query) || '<missing>'}.`);
|
|
650
661
|
}
|
|
651
662
|
if (args.mode === 'set_keybinding') {
|
|
652
663
|
const confirmationError = requireConfirmedAction(args, 'Keybinding mutation');
|
|
@@ -681,33 +692,48 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
681
692
|
return output({ settings, returned: settings.length, policy: settingsPolicySummary() });
|
|
682
693
|
}
|
|
683
694
|
if (args.mode === 'get_setting') {
|
|
684
|
-
const
|
|
685
|
-
|
|
686
|
-
|
|
695
|
+
const setting = resolveHarnessSetting(deps.commandContext.platform.configManager, settingLookupArgs(args));
|
|
696
|
+
if (setting?.status === 'found') return output(setting.setting);
|
|
697
|
+
if (setting?.status === 'ambiguous') {
|
|
698
|
+
return error(`Ambiguous setting ${setting.input}. Candidates: ${JSON.stringify(setting.candidates)}`);
|
|
699
|
+
}
|
|
700
|
+
return error(`Unknown setting ${readString(args.key || args.target || args.query) || '<missing>'}. Use mode:"settings" to inspect available settings.`);
|
|
687
701
|
}
|
|
688
702
|
if (args.mode === 'set_setting') {
|
|
689
703
|
const confirmationError = requireConfirmedAction(args, 'Setting mutation');
|
|
690
704
|
if (confirmationError) return error(confirmationError);
|
|
691
705
|
if (args.value === undefined) return error('set_setting requires value.');
|
|
692
|
-
const
|
|
706
|
+
const setting = resolveHarnessSetting(deps.commandContext.platform.configManager, settingLookupArgs(args));
|
|
707
|
+
if (setting?.status === 'ambiguous') {
|
|
708
|
+
return error(`Ambiguous setting ${setting.input}. Candidates: ${JSON.stringify(setting.candidates)}`);
|
|
709
|
+
}
|
|
710
|
+
if (setting?.status !== 'found') {
|
|
711
|
+
return error(`Unknown setting ${readString(args.key || args.target || args.query) || '<missing>'}. Use mode:"settings" to inspect available settings.`);
|
|
712
|
+
}
|
|
693
713
|
const result = await setHarnessSetting(
|
|
694
714
|
deps.commandContext.platform.configManager,
|
|
695
715
|
deps.commandContext.platform.secretsManager,
|
|
696
|
-
key,
|
|
716
|
+
setting.setting.key,
|
|
697
717
|
args.value,
|
|
698
718
|
);
|
|
699
|
-
return output(result);
|
|
719
|
+
return output({ ...result, lookup: setting.lookup });
|
|
700
720
|
}
|
|
701
721
|
if (args.mode === 'reset_setting') {
|
|
702
722
|
const confirmationError = requireConfirmedAction(args, 'Setting reset');
|
|
703
723
|
if (confirmationError) return error(confirmationError);
|
|
704
|
-
const
|
|
724
|
+
const setting = resolveHarnessSetting(deps.commandContext.platform.configManager, settingLookupArgs(args));
|
|
725
|
+
if (setting?.status === 'ambiguous') {
|
|
726
|
+
return error(`Ambiguous setting ${setting.input}. Candidates: ${JSON.stringify(setting.candidates)}`);
|
|
727
|
+
}
|
|
728
|
+
if (setting?.status !== 'found') {
|
|
729
|
+
return error(`Unknown setting ${readString(args.key || args.target || args.query) || '<missing>'}. Use mode:"settings" to inspect available settings.`);
|
|
730
|
+
}
|
|
705
731
|
const result = await resetHarnessSetting(
|
|
706
732
|
deps.commandContext.platform.configManager,
|
|
707
733
|
deps.commandContext.platform.secretsManager,
|
|
708
|
-
key,
|
|
734
|
+
setting.setting.key,
|
|
709
735
|
);
|
|
710
|
-
return output(result);
|
|
736
|
+
return output({ ...result, lookup: setting.lookup });
|
|
711
737
|
}
|
|
712
738
|
if (args.mode === 'workspace' || args.mode === 'workspace_categories') {
|
|
713
739
|
return output({
|
|
@@ -27,6 +27,24 @@ interface UiSurfaceDefinition {
|
|
|
27
27
|
readonly open: (context: CommandContext, args: AgentHarnessUiSurfaceArgs) => Record<string, unknown> | Promise<Record<string, unknown>>;
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
+
interface UiSurfaceLookup {
|
|
31
|
+
readonly source: 'surfaceId' | 'target' | 'query';
|
|
32
|
+
readonly input: string;
|
|
33
|
+
readonly resolvedBy: 'id' | 'case-insensitive-id' | 'label' | 'case-insensitive-label' | 'search';
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
type UiSurfaceResolution =
|
|
37
|
+
| {
|
|
38
|
+
readonly status: 'found';
|
|
39
|
+
readonly surface: UiSurfaceDefinition;
|
|
40
|
+
readonly lookup: UiSurfaceLookup;
|
|
41
|
+
}
|
|
42
|
+
| {
|
|
43
|
+
readonly status: 'ambiguous';
|
|
44
|
+
readonly input: string;
|
|
45
|
+
readonly candidates: readonly Record<string, unknown>[];
|
|
46
|
+
};
|
|
47
|
+
|
|
30
48
|
function readString(value: unknown): string {
|
|
31
49
|
return typeof value === 'string' ? value.trim() : '';
|
|
32
50
|
}
|
|
@@ -668,7 +686,17 @@ function surfaceMatches(surface: Record<string, unknown>, query: string): boolea
|
|
|
668
686
|
].map((value) => String(value ?? '')).join('\n').toLowerCase().includes(query.toLowerCase());
|
|
669
687
|
}
|
|
670
688
|
|
|
671
|
-
function
|
|
689
|
+
function surfaceLookupFromArgs(args: AgentHarnessUiSurfaceArgs): { readonly source: UiSurfaceLookup['source']; readonly input: string } | null {
|
|
690
|
+
const surfaceId = readString(args.surfaceId);
|
|
691
|
+
if (surfaceId) return { source: 'surfaceId', input: surfaceId };
|
|
692
|
+
const query = readString(args.query);
|
|
693
|
+
if (query) return { source: 'query', input: query };
|
|
694
|
+
const target = readString(args.target);
|
|
695
|
+
if (target) return { source: 'target', input: target };
|
|
696
|
+
return null;
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
function surfaceCandidate(surface: UiSurfaceDefinition): Record<string, unknown> {
|
|
672
700
|
return {
|
|
673
701
|
id: surface.id,
|
|
674
702
|
label: surface.label,
|
|
@@ -676,6 +704,38 @@ function describeSurface(context: CommandContext, surface: UiSurfaceDefinition):
|
|
|
676
704
|
summary: surface.summary,
|
|
677
705
|
command: surface.command,
|
|
678
706
|
preferredModelRoute: surface.preferredModelRoute,
|
|
707
|
+
};
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
function resolveHarnessUiSurface(args: AgentHarnessUiSurfaceArgs): UiSurfaceResolution | null {
|
|
711
|
+
const lookup = surfaceLookupFromArgs(args);
|
|
712
|
+
if (!lookup) return null;
|
|
713
|
+
const exactId = UI_SURFACES.find((surface) => surface.id === lookup.input);
|
|
714
|
+
if (exactId) return { status: 'found', surface: exactId, lookup: { ...lookup, resolvedBy: 'id' } };
|
|
715
|
+
const exactLabel = UI_SURFACES.find((surface) => surface.label === lookup.input);
|
|
716
|
+
if (exactLabel) return { status: 'found', surface: exactLabel, lookup: { ...lookup, resolvedBy: 'label' } };
|
|
717
|
+
const inputLower = lookup.input.toLowerCase();
|
|
718
|
+
const ciId = UI_SURFACES.filter((surface) => surface.id.toLowerCase() === inputLower);
|
|
719
|
+
if (ciId.length === 1) return { status: 'found', surface: ciId[0]!, lookup: { ...lookup, resolvedBy: 'case-insensitive-id' } };
|
|
720
|
+
if (ciId.length > 1) return { status: 'ambiguous', input: lookup.input, candidates: ciId.map(surfaceCandidate).slice(0, 8) };
|
|
721
|
+
const ciLabel = UI_SURFACES.filter((surface) => surface.label.toLowerCase() === inputLower);
|
|
722
|
+
if (ciLabel.length === 1) return { status: 'found', surface: ciLabel[0]!, lookup: { ...lookup, resolvedBy: 'case-insensitive-label' } };
|
|
723
|
+
if (ciLabel.length > 1) return { status: 'ambiguous', input: lookup.input, candidates: ciLabel.map(surfaceCandidate).slice(0, 8) };
|
|
724
|
+
const search = UI_SURFACES.filter((surface) => surfaceMatches(surfaceCandidate(surface), lookup.input));
|
|
725
|
+
if (search.length === 1) return { status: 'found', surface: search[0]!, lookup: { ...lookup, resolvedBy: 'search' } };
|
|
726
|
+
if (search.length > 1) return { status: 'ambiguous', input: lookup.input, candidates: search.map(surfaceCandidate).slice(0, 8) };
|
|
727
|
+
return null;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
function describeSurface(context: CommandContext, surface: UiSurfaceDefinition, lookup?: UiSurfaceLookup): Record<string, unknown> {
|
|
731
|
+
return {
|
|
732
|
+
id: surface.id,
|
|
733
|
+
label: surface.label,
|
|
734
|
+
kind: surface.kind,
|
|
735
|
+
summary: surface.summary,
|
|
736
|
+
command: surface.command,
|
|
737
|
+
...(lookup ? { lookup } : {}),
|
|
738
|
+
preferredModelRoute: surface.preferredModelRoute,
|
|
679
739
|
parameters: surface.parameters ?? [],
|
|
680
740
|
available: surface.available(context),
|
|
681
741
|
policy: {
|
|
@@ -700,25 +760,29 @@ export function listHarnessUiSurfaces(context: CommandContext, args: AgentHarnes
|
|
|
700
760
|
}
|
|
701
761
|
|
|
702
762
|
export function describeHarnessUiSurface(context: CommandContext, args: AgentHarnessUiSurfaceArgs): Record<string, unknown> | null {
|
|
703
|
-
const
|
|
704
|
-
if (
|
|
705
|
-
|
|
706
|
-
|
|
763
|
+
const resolved = resolveHarnessUiSurface(args);
|
|
764
|
+
if (resolved?.status === 'found') return describeSurface(context, resolved.surface, resolved.lookup);
|
|
765
|
+
if (resolved?.status === 'ambiguous') {
|
|
766
|
+
return { status: 'ambiguous', input: resolved.input, candidates: resolved.candidates };
|
|
767
|
+
}
|
|
768
|
+
return null;
|
|
707
769
|
}
|
|
708
770
|
|
|
709
771
|
export async function openHarnessUiSurface(context: CommandContext, args: AgentHarnessUiSurfaceArgs): Promise<Record<string, unknown>> {
|
|
710
|
-
const
|
|
711
|
-
|
|
712
|
-
|
|
772
|
+
const resolved = resolveHarnessUiSurface(args);
|
|
773
|
+
if (resolved?.status === 'ambiguous') {
|
|
774
|
+
return { status: 'ambiguous_ui_surface', input: resolved.input, candidates: resolved.candidates };
|
|
775
|
+
}
|
|
776
|
+
if (!resolved) {
|
|
713
777
|
return {
|
|
714
778
|
status: 'unknown_ui_surface',
|
|
715
|
-
surfaceId: surfaceId || '<missing>',
|
|
779
|
+
surfaceId: readString(args.surfaceId || args.query || args.target) || '<missing>',
|
|
716
780
|
availableSurfaces: UI_SURFACES.map((entry) => entry.id),
|
|
717
781
|
};
|
|
718
782
|
}
|
|
719
|
-
const routed = await surface.open(context, args);
|
|
783
|
+
const routed = await resolved.surface.open(context, args);
|
|
720
784
|
return {
|
|
721
785
|
...routed,
|
|
722
|
-
descriptor: describeSurface(context, surface),
|
|
786
|
+
descriptor: describeSurface(context, resolved.surface, resolved.lookup),
|
|
723
787
|
};
|
|
724
788
|
}
|
package/src/version.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { join } from 'node:path';
|
|
|
6
6
|
// The prebuild script updates the fallback value before compilation.
|
|
7
7
|
// Uses import.meta.dir (Bun) to locate package.json relative to this file,
|
|
8
8
|
// which is correct regardless of the process working directory.
|
|
9
|
-
let _version = '1.0.
|
|
9
|
+
let _version = '1.0.18';
|
|
10
10
|
let _sdkVersion = '0.33.35';
|
|
11
11
|
try {
|
|
12
12
|
const pkg = JSON.parse(readFileSync(join(import.meta.dir, '..', 'package.json'), 'utf-8')) as {
|