@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.
@@ -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, tool, or UI surface catalogs; also a slash-command lookup for mode command.',
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, settings key, model tool name, or connected-host capability id.',
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", mode:"get_setting", mode:"set_setting", and mode:"reset_setting".',
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 key = readString(args.key);
685
- const setting = getHarnessSetting(deps.commandContext.platform.configManager, key);
686
- return setting ? output(setting) : error(`Unknown setting ${key || '<missing>'}.`);
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 key = readString(args.key);
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 key = readString(args.key);
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 describeSurface(context: CommandContext, surface: UiSurfaceDefinition): Record<string, unknown> {
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 surfaceId = readString(args.surfaceId || args.query);
704
- if (!surfaceId) return null;
705
- const surface = UI_SURFACES.find((entry) => entry.id === surfaceId || entry.label.toLowerCase() === surfaceId.toLowerCase());
706
- return surface ? describeSurface(context, surface) : null;
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 surfaceId = readString(args.surfaceId || args.query);
711
- const surface = UI_SURFACES.find((entry) => entry.id === surfaceId || entry.label.toLowerCase() === surfaceId.toLowerCase());
712
- if (!surface) {
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.16';
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 {