@pellux/goodvibes-agent 1.0.13 → 1.0.15
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 +227 -108
- package/docs/README.md +1 -1
- package/docs/getting-started.md +1 -1
- package/docs/tools-and-commands.md +2 -2
- package/package.json +1 -1
- package/src/tools/agent-harness-command-catalog.ts +149 -0
- package/src/tools/agent-harness-model-tool-catalog.ts +20 -0
- package/src/tools/agent-harness-tool-schema.ts +8 -4
- package/src/tools/agent-harness-tool.ts +20 -44
- package/src/version.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
Product-facing release notes for GoodVibes Agent.
|
|
4
4
|
|
|
5
|
+
## 1.0.15 - 2026-06-03
|
|
6
|
+
|
|
7
|
+
- Add forgiving agent_harness slash-command detail lookup by command, commandName, target, or query with parsed invocation metadata.
|
|
8
|
+
- Keep slash-command catalogs lightweight while making one-command inspection work from typed user-style invocations, aliases, case-insensitive roots, and unique description matches.
|
|
9
|
+
- Refresh package-facing docs and focused harness coverage for the updated model-visible slash-command inspection path.
|
|
10
|
+
|
|
11
|
+
## 1.0.14 - 2026-06-03
|
|
12
|
+
|
|
13
|
+
- Add agent_harness mode tool to inspect one first-class model tool schema by toolName, target, or query.
|
|
14
|
+
- Keep broad tools discovery lightweight while making individual model tool parameters, side effects, concurrency, and streaming/progress support directly inspectable.
|
|
15
|
+
- Refresh package-facing docs and focused harness coverage for the updated model tool discovery surface.
|
|
16
|
+
|
|
5
17
|
## 1.0.13 - 2026-06-03
|
|
6
18
|
|
|
7
19
|
- Add connected_host_capability to inspect one allowed or blocked connected-host capability by id, target, or query with related route families and boundary text.
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ GoodVibes Agent is the personal operator assistant TUI for GoodVibes. It is buil
|
|
|
7
7
|
|
|
8
8
|
The Agent product connects to a GoodVibes host owned outside this package. It does not install, start, stop, restart, or own that host.
|
|
9
9
|
|
|
10
|
-
Most work happens in the interactive TUI. The installed CLI exists to launch that TUI and provide scriptable mirrors for workflows that are already reachable from the workspace. The main Agent model can inspect the same harness surface through Agent-owned tools: workspace actions, built-in panels, modal/overlay/picker UI surfaces, named operator surfaces, top-level CLI mirrors, fixed shortcuts, configurable keybindings, slash commands, command policy metadata, settings, model tools, local registries, connected-host capability boundaries, and live connected-host readiness are all discoverable from the conversation without exposing connected-host lifecycle control.
|
|
10
|
+
Most work happens in the interactive TUI. The installed CLI exists to launch that TUI and provide scriptable mirrors for workflows that are already reachable from the workspace. The main Agent model can inspect the same harness surface through Agent-owned tools: workspace actions, built-in panels, modal/overlay/picker UI surfaces, named operator surfaces, top-level CLI mirrors, fixed shortcuts, configurable keybindings, slash commands, single-command lookup with policy metadata, settings, model tools and individual model tool schemas, local registries, connected-host capability boundaries, and live connected-host readiness are all discoverable from the conversation without exposing connected-host lifecycle control.
|
|
11
11
|
|
|
12
12
|
## Install
|
|
13
13
|
|
|
@@ -66,7 +66,7 @@ Use the workspace as the primary product surface:
|
|
|
66
66
|
|
|
67
67
|
Inside the Agent workspace, press `/` to search every workspace action by name, category, command, or detail. This is the primary discovery path for product actions; slash commands and CLI subcommands remain power-user/scriptable mirrors.
|
|
68
68
|
|
|
69
|
-
The model has the same harness map through `agent_harness`: it can list Agent workspace actions, list built-in panels and their workspace routes, inspect modal/overlay/picker UI surfaces, list top-level CLI mirrors, inspect fixed shortcuts and configurable keybindings, list slash commands, inspect command policy metadata, inspect model tool definitions, inspect or change Agent settings with confirmation, run concrete workspace or slash-command mirrors with confirmation, and report connected-host capability and live readiness posture. CLI mirror modes are read-only catalog and parser inspection; inside the main conversation, the model uses the returned preferred model tool, workspace action, setting mode, or confirmed slash-command mirror instead of launching hidden nested CLI processes. Panel modes expose catalog/open state and route visible panel/workspace changes through the current Agent shell bridge with confirmation. UI surface modes expose help, shortcuts, command browser, conversation search, prompt-history search, slash-command mode, file picker, block actions, context, runtime activity, live process output, bookmarks, model/provider/reasoning-effort pickers, TTS provider/voice pickers, session/profile pickers, the panel-picker compatibility route, security/knowledge/subscription operator surfaces, settings, MCP workspace, onboarding, and Agent workspace entrypoints; `open_ui_surface` is confirmation-gated and only performs visible shell navigation. Shortcut modes expose fixed runtime/editor controls plus the live resolved keybinding table; `set_keybinding` and `reset_keybinding` write the same `keybindings.json` file the user edits and require confirmation. Workspace action discovery can inline editor field schemas with `includeParameters:true`; profile editors use the current starter-template inventory, and routine schedule editors can prefill a selected local routine from `recordId`. Selection-based local workspace actions accept a local `recordId` so the model can use the same note promotion and local registry flows as the TUI. Direct local create editors for memory, notes, personas, skills, and routines can execute from submitted fields through `run_workspace_action` and `agent_local_registry` with confirmation. The `connected_host` report includes route families, allowed capabilities, blocked lifecycle/non-Agent surfaces, and availability for the first-class Agent tools; `connected_host_capability` inspects one allowed or blocked capability by id, target, or query with its route families and boundary. The `connected_host_status` report performs a read-only live check of the connected-host status route and the isolated Agent Knowledge status route, reports SDK compatibility, token posture, endpoint bindings, route readiness, and actionable findings, and still refuses connected-host lifecycle control. The model uses those first-class tools for product workflows where they exist, such as Agent Knowledge, local memory/notes/personas/skills/routines, channel sends, notifications, reminders, media generation, work plans, and connected-host operator actions.
|
|
69
|
+
The model has the same harness map through `agent_harness`: it can list Agent workspace actions, list built-in panels and their workspace routes, inspect modal/overlay/picker UI surfaces, list top-level CLI mirrors, inspect fixed shortcuts and configurable keybindings, list slash commands, inspect one slash command by `command`, `commandName`, `target`, or `query` with parsed arguments and policy metadata, inspect model tool definitions or one model tool schema, inspect or change Agent settings with confirmation, run concrete workspace or slash-command mirrors with confirmation, and report connected-host capability and live readiness posture. CLI mirror modes are read-only catalog and parser inspection; inside the main conversation, the model uses the returned preferred model tool, workspace action, setting mode, or confirmed slash-command mirror instead of launching hidden nested CLI processes. Panel modes expose catalog/open state and route visible panel/workspace changes through the current Agent shell bridge with confirmation. UI surface modes expose help, shortcuts, command browser, conversation search, prompt-history search, slash-command mode, file picker, block actions, context, runtime activity, live process output, bookmarks, model/provider/reasoning-effort pickers, TTS provider/voice pickers, session/profile pickers, the panel-picker compatibility route, security/knowledge/subscription operator surfaces, settings, MCP workspace, onboarding, and Agent workspace entrypoints; `open_ui_surface` is confirmation-gated and only performs visible shell navigation. Shortcut modes expose fixed runtime/editor controls plus the live resolved keybinding table; `set_keybinding` and `reset_keybinding` write the same `keybindings.json` file the user edits and require confirmation. Workspace action discovery can inline editor field schemas with `includeParameters:true`; profile editors use the current starter-template inventory, and routine schedule editors can prefill a selected local routine from `recordId`. Selection-based local workspace actions accept a local `recordId` so the model can use the same note promotion and local registry flows as the TUI. Direct local create editors for memory, notes, personas, skills, and routines can execute from submitted fields through `run_workspace_action` and `agent_local_registry` with confirmation. The `connected_host` report includes route families, allowed capabilities, blocked lifecycle/non-Agent surfaces, and availability for the first-class Agent tools; `connected_host_capability` inspects one allowed or blocked capability by id, target, or query with its route families and boundary. The `connected_host_status` report performs a read-only live check of the connected-host status route and the isolated Agent Knowledge status route, reports SDK compatibility, token posture, endpoint bindings, route readiness, and actionable findings, and still refuses connected-host lifecycle control. The model uses those first-class tools for product workflows where they exist, such as Agent Knowledge, local memory/notes/personas/skills/routines, channel sends, notifications, reminders, media generation, work plans, and connected-host operator actions.
|
|
70
70
|
|
|
71
71
|
The setup workspace surfaces discovered Agent-local persona, skill, and routine markdown files so day-one setup can import useful behavior instead of starting from blank records. It can also create one initial scratchpad note, local persona, skill, and routine directly during first-run setup; those records stay in Agent-local registries and never write to default knowledge or non-Agent segments.
|
|
72
72
|
|
package/dist/package/main.js
CHANGED
|
@@ -816566,7 +816566,7 @@ var createStyledCell = (char, overrides = {}) => ({
|
|
|
816566
816566
|
// src/version.ts
|
|
816567
816567
|
import { readFileSync } from "fs";
|
|
816568
816568
|
import { join } from "path";
|
|
816569
|
-
var _version = "1.0.
|
|
816569
|
+
var _version = "1.0.15";
|
|
816570
816570
|
var _sdkVersion = "0.33.35";
|
|
816571
816571
|
try {
|
|
816572
816572
|
const pkg = JSON.parse(readFileSync(join(import.meta.dir, "..", "package.json"), "utf-8"));
|
|
@@ -879834,6 +879834,126 @@ function describeHarnessCliCommand(args2) {
|
|
|
879834
879834
|
};
|
|
879835
879835
|
}
|
|
879836
879836
|
|
|
879837
|
+
// src/tools/agent-harness-command-catalog.ts
|
|
879838
|
+
function readString51(value) {
|
|
879839
|
+
return typeof value === "string" ? value.trim() : "";
|
|
879840
|
+
}
|
|
879841
|
+
function readLimit6(value, fallback) {
|
|
879842
|
+
const parsed = typeof value === "string" && value.trim() ? Number(value) : value;
|
|
879843
|
+
if (typeof parsed !== "number" || !Number.isFinite(parsed))
|
|
879844
|
+
return fallback;
|
|
879845
|
+
return Math.max(1, Math.min(500, Math.trunc(parsed)));
|
|
879846
|
+
}
|
|
879847
|
+
function readStringArray12(value) {
|
|
879848
|
+
if (!Array.isArray(value))
|
|
879849
|
+
return [];
|
|
879850
|
+
return value.map((entry) => typeof entry === "string" ? entry : String(entry));
|
|
879851
|
+
}
|
|
879852
|
+
function commandMatches(command8, query2) {
|
|
879853
|
+
if (!query2)
|
|
879854
|
+
return true;
|
|
879855
|
+
const haystack = [
|
|
879856
|
+
command8.name,
|
|
879857
|
+
...command8.aliases ?? [],
|
|
879858
|
+
command8.description,
|
|
879859
|
+
command8.usage ?? "",
|
|
879860
|
+
command8.argsHint ?? ""
|
|
879861
|
+
].join(`
|
|
879862
|
+
`).toLowerCase();
|
|
879863
|
+
return haystack.includes(query2.toLowerCase());
|
|
879864
|
+
}
|
|
879865
|
+
function describeCommand(command8, lookup) {
|
|
879866
|
+
return {
|
|
879867
|
+
name: command8.name,
|
|
879868
|
+
slash: `/${command8.name}`,
|
|
879869
|
+
aliases: command8.aliases ?? [],
|
|
879870
|
+
description: command8.description,
|
|
879871
|
+
usage: command8.usage ?? "",
|
|
879872
|
+
argsHint: command8.argsHint ?? command8.usage ?? "",
|
|
879873
|
+
...lookup ? {
|
|
879874
|
+
lookup: {
|
|
879875
|
+
source: lookup.source,
|
|
879876
|
+
input: lookup.input,
|
|
879877
|
+
parsedName: lookup.parsedName,
|
|
879878
|
+
parsedArgs: lookup.parsedArgs,
|
|
879879
|
+
resolvedBy: lookup.resolvedBy
|
|
879880
|
+
}
|
|
879881
|
+
} : {},
|
|
879882
|
+
policy: describeCommandPolicy(command8.name)
|
|
879883
|
+
};
|
|
879884
|
+
}
|
|
879885
|
+
function commandDetailLookupFromArgs(args2) {
|
|
879886
|
+
const rawCommand = readString51(args2.command);
|
|
879887
|
+
if (rawCommand) {
|
|
879888
|
+
const parsed = parseSlashCommand(rawCommand);
|
|
879889
|
+
return { source: "command", input: rawCommand, parsedName: parsed.name, parsedArgs: parsed.args };
|
|
879890
|
+
}
|
|
879891
|
+
const rawCommandName = readString51(args2.commandName);
|
|
879892
|
+
if (rawCommandName) {
|
|
879893
|
+
const parsed = parseSlashCommand(rawCommandName);
|
|
879894
|
+
const explicitArgs = readStringArray12(args2.args);
|
|
879895
|
+
return {
|
|
879896
|
+
source: "commandName",
|
|
879897
|
+
input: rawCommandName,
|
|
879898
|
+
parsedName: parsed.name,
|
|
879899
|
+
parsedArgs: explicitArgs.length > 0 ? explicitArgs : parsed.args
|
|
879900
|
+
};
|
|
879901
|
+
}
|
|
879902
|
+
const rawTarget = readString51(args2.target);
|
|
879903
|
+
if (rawTarget) {
|
|
879904
|
+
const parsed = parseSlashCommand(rawTarget);
|
|
879905
|
+
return { source: "target", input: rawTarget, parsedName: parsed.name, parsedArgs: parsed.args };
|
|
879906
|
+
}
|
|
879907
|
+
const rawQuery = readString51(args2.query);
|
|
879908
|
+
if (rawQuery) {
|
|
879909
|
+
const parsed = parseSlashCommand(rawQuery);
|
|
879910
|
+
return { source: "query", input: rawQuery, parsedName: parsed.name, parsedArgs: parsed.args };
|
|
879911
|
+
}
|
|
879912
|
+
return null;
|
|
879913
|
+
}
|
|
879914
|
+
function resolveCommandDetail(commandRegistry, args2) {
|
|
879915
|
+
const lookup = commandDetailLookupFromArgs(args2);
|
|
879916
|
+
if (!lookup?.parsedName)
|
|
879917
|
+
return null;
|
|
879918
|
+
const direct = commandRegistry.get(lookup.parsedName);
|
|
879919
|
+
if (direct) {
|
|
879920
|
+
return {
|
|
879921
|
+
command: direct,
|
|
879922
|
+
lookup: {
|
|
879923
|
+
...lookup,
|
|
879924
|
+
resolvedBy: direct.name === lookup.parsedName ? "name" : "alias"
|
|
879925
|
+
}
|
|
879926
|
+
};
|
|
879927
|
+
}
|
|
879928
|
+
const normalized = lookup.parsedName.toLowerCase();
|
|
879929
|
+
for (const command8 of commandRegistry.list()) {
|
|
879930
|
+
if (command8.name.toLowerCase() === normalized) {
|
|
879931
|
+
return { command: command8, lookup: { ...lookup, resolvedBy: "case-insensitive-name" } };
|
|
879932
|
+
}
|
|
879933
|
+
if ((command8.aliases ?? []).some((alias) => alias.toLowerCase() === normalized)) {
|
|
879934
|
+
return { command: command8, lookup: { ...lookup, resolvedBy: "case-insensitive-alias" } };
|
|
879935
|
+
}
|
|
879936
|
+
}
|
|
879937
|
+
const descriptionMatches = commandRegistry.list().filter((command8) => commandMatches(command8, lookup.input));
|
|
879938
|
+
if (descriptionMatches.length === 1) {
|
|
879939
|
+
return { command: descriptionMatches[0], lookup: { ...lookup, resolvedBy: "description" } };
|
|
879940
|
+
}
|
|
879941
|
+
const prefixMatches = commandRegistry.fuzzyMatch(lookup.parsedName).filter((entry) => entry.score >= 80);
|
|
879942
|
+
if (prefixMatches.length === 1) {
|
|
879943
|
+
return { command: prefixMatches[0].command, lookup: { ...lookup, resolvedBy: "prefix" } };
|
|
879944
|
+
}
|
|
879945
|
+
return null;
|
|
879946
|
+
}
|
|
879947
|
+
function listHarnessCommands(commandRegistry, args2) {
|
|
879948
|
+
const query2 = readString51(args2.query);
|
|
879949
|
+
const limit3 = readLimit6(args2.limit, 200);
|
|
879950
|
+
return commandRegistry.list().filter((command8) => commandMatches(command8, query2)).sort((a4, b3) => a4.name.localeCompare(b3.name)).slice(0, limit3).map((command8) => describeCommand(command8));
|
|
879951
|
+
}
|
|
879952
|
+
function describeHarnessCommand(commandRegistry, args2) {
|
|
879953
|
+
const detail = resolveCommandDetail(commandRegistry, args2);
|
|
879954
|
+
return detail ? describeCommand(detail.command, detail.lookup) : null;
|
|
879955
|
+
}
|
|
879956
|
+
|
|
879837
879957
|
// src/tools/agent-harness-keybinding-metadata.ts
|
|
879838
879958
|
import { existsSync as existsSync82, mkdirSync as mkdirSync67, readFileSync as readFileSync89, writeFileSync as writeFileSync58 } from "fs";
|
|
879839
879959
|
import { dirname as dirname66 } from "path";
|
|
@@ -879847,10 +879967,10 @@ var FIXED_SHORTCUTS = [
|
|
|
879847
879967
|
{ key: "F2 / /shortcuts", description: "Open keyboard shortcut reference" },
|
|
879848
879968
|
{ key: "/keybindings", description: "List configurable keybindings and config path" }
|
|
879849
879969
|
];
|
|
879850
|
-
function
|
|
879970
|
+
function readString52(value) {
|
|
879851
879971
|
return typeof value === "string" ? value.trim() : "";
|
|
879852
879972
|
}
|
|
879853
|
-
function
|
|
879973
|
+
function readLimit7(value, fallback) {
|
|
879854
879974
|
const parsed = typeof value === "string" && value.trim() ? Number(value) : value;
|
|
879855
879975
|
if (typeof parsed !== "number" || !Number.isFinite(parsed))
|
|
879856
879976
|
return fallback;
|
|
@@ -879871,7 +879991,7 @@ function isKeyAction2(action2) {
|
|
|
879871
879991
|
return Object.hasOwn(ACTION_DESCRIPTIONS, action2);
|
|
879872
879992
|
}
|
|
879873
879993
|
function actionFromArgs(args2) {
|
|
879874
|
-
const action2 =
|
|
879994
|
+
const action2 = readString52(args2.actionId || args2.key || args2.query);
|
|
879875
879995
|
return action2 && isKeyAction2(action2) ? action2 : null;
|
|
879876
879996
|
}
|
|
879877
879997
|
function readBoolean15(value) {
|
|
@@ -879890,7 +880010,7 @@ function normalizeCombo(value) {
|
|
|
879890
880010
|
if (typeof value !== "object" || value === null || Array.isArray(value))
|
|
879891
880011
|
return null;
|
|
879892
880012
|
const raw = value;
|
|
879893
|
-
const key =
|
|
880013
|
+
const key = readString52(raw.key);
|
|
879894
880014
|
if (!key)
|
|
879895
880015
|
return null;
|
|
879896
880016
|
const combo = { key };
|
|
@@ -879940,7 +880060,7 @@ function combosFromArgs(args2) {
|
|
|
879940
880060
|
const fieldCombo = normalizeCombo(fields);
|
|
879941
880061
|
if (fieldCombo)
|
|
879942
880062
|
return [fieldCombo];
|
|
879943
|
-
const labelCombo = parseComboLabel(
|
|
880063
|
+
const labelCombo = parseComboLabel(readString52(args2.value));
|
|
879944
880064
|
if (labelCombo)
|
|
879945
880065
|
return [labelCombo];
|
|
879946
880066
|
throw new Error('set_keybinding requires combo, combos, fields.key, or a value such as "Ctrl+G".');
|
|
@@ -880008,9 +880128,9 @@ function totalHarnessShortcuts(context) {
|
|
|
880008
880128
|
}
|
|
880009
880129
|
function listHarnessShortcuts(context, args2) {
|
|
880010
880130
|
const keybindings = listHarnessKeybindings(context, args2);
|
|
880011
|
-
const query2 =
|
|
880131
|
+
const query2 = readString52(args2.query).toLowerCase();
|
|
880012
880132
|
const fixed = FIXED_SHORTCUTS.filter((shortcut) => !query2 || `${shortcut.key}
|
|
880013
|
-
${shortcut.description}`.toLowerCase().includes(query2)).slice(0,
|
|
880133
|
+
${shortcut.description}`.toLowerCase().includes(query2)).slice(0, readLimit7(args2.limit, 200)).map((shortcut) => ({ ...shortcut, source: "fixed", userEditable: false }));
|
|
880014
880134
|
return {
|
|
880015
880135
|
configPath: keybindings.configPath,
|
|
880016
880136
|
fixedShortcuts: fixed,
|
|
@@ -880022,8 +880142,8 @@ ${shortcut.description}`.toLowerCase().includes(query2)).slice(0, readLimit6(arg
|
|
|
880022
880142
|
}
|
|
880023
880143
|
function listHarnessKeybindings(context, args2) {
|
|
880024
880144
|
const manager5 = requireKeybindingsManager2(context);
|
|
880025
|
-
const query2 =
|
|
880026
|
-
const entries = manager5.getAll().filter((entry) => bindingMatches(entry, query2)).slice(0,
|
|
880145
|
+
const query2 = readString52(args2.query);
|
|
880146
|
+
const entries = manager5.getAll().filter((entry) => bindingMatches(entry, query2)).slice(0, readLimit7(args2.limit, 200)).map((entry) => describeBinding(manager5, entry.action, entry.combos));
|
|
880027
880147
|
return {
|
|
880028
880148
|
configPath: manager5.getConfigPath(),
|
|
880029
880149
|
keybindings: entries,
|
|
@@ -880078,10 +880198,10 @@ function resetHarnessKeybinding(context, args2) {
|
|
|
880078
880198
|
}
|
|
880079
880199
|
|
|
880080
880200
|
// src/tools/agent-harness-panel-metadata.ts
|
|
880081
|
-
function
|
|
880201
|
+
function readString53(value) {
|
|
880082
880202
|
return typeof value === "string" ? value.trim() : "";
|
|
880083
880203
|
}
|
|
880084
|
-
function
|
|
880204
|
+
function readLimit8(value, fallback) {
|
|
880085
880205
|
const parsed = typeof value === "string" && value.trim() ? Number(value) : value;
|
|
880086
880206
|
if (typeof parsed !== "number" || !Number.isFinite(parsed))
|
|
880087
880207
|
return fallback;
|
|
@@ -880136,16 +880256,16 @@ function listHarnessPanels(context, args2) {
|
|
|
880136
880256
|
const manager5 = panelManager(context);
|
|
880137
880257
|
if (!manager5)
|
|
880138
880258
|
return [];
|
|
880139
|
-
const query2 =
|
|
880140
|
-
const category =
|
|
880141
|
-
const limit3 =
|
|
880259
|
+
const query2 = readString53(args2.query);
|
|
880260
|
+
const category = readString53(args2.category);
|
|
880261
|
+
const limit3 = readLimit8(args2.limit, 200);
|
|
880142
880262
|
return manager5.getRegisteredTypes().map((registration) => describePanelRegistration(context, registration)).filter((panel) => !category || panel.category === category).filter((panel) => panelMatches(panel, query2)).sort((a4, b3) => String(a4.id).localeCompare(String(b3.id))).slice(0, limit3);
|
|
880143
880263
|
}
|
|
880144
880264
|
function describeHarnessPanel(context, args2) {
|
|
880145
880265
|
const manager5 = panelManager(context);
|
|
880146
880266
|
if (!manager5)
|
|
880147
880267
|
return null;
|
|
880148
|
-
const panelId =
|
|
880268
|
+
const panelId = readString53(args2.panelId || args2.query);
|
|
880149
880269
|
if (!panelId)
|
|
880150
880270
|
return null;
|
|
880151
880271
|
const registration = manager5.getRegisteredTypes().find((panel) => panel.id === panelId || panel.name.toLowerCase() === panelId.toLowerCase());
|
|
@@ -880156,11 +880276,11 @@ function openHarnessPanel(context, args2) {
|
|
|
880156
880276
|
if (!panel) {
|
|
880157
880277
|
return {
|
|
880158
880278
|
status: "unknown_panel",
|
|
880159
|
-
panelId:
|
|
880279
|
+
panelId: readString53(args2.panelId || args2.query) || "<missing>",
|
|
880160
880280
|
availablePanels: listHarnessPanels(context, { limit: 50 }).map((entry) => entry.id)
|
|
880161
880281
|
};
|
|
880162
880282
|
}
|
|
880163
|
-
const requestedPane =
|
|
880283
|
+
const requestedPane = readString53(args2.pane);
|
|
880164
880284
|
const pane = requestedPane === "bottom" || requestedPane === "top" ? requestedPane : undefined;
|
|
880165
880285
|
if (!context.showPanel) {
|
|
880166
880286
|
return {
|
|
@@ -880184,7 +880304,7 @@ import { join as join98 } from "path";
|
|
|
880184
880304
|
function isRecord42(value) {
|
|
880185
880305
|
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
880186
880306
|
}
|
|
880187
|
-
function
|
|
880307
|
+
function readString54(record2, key) {
|
|
880188
880308
|
const value = record2?.[key];
|
|
880189
880309
|
return typeof value === "string" ? value : null;
|
|
880190
880310
|
}
|
|
@@ -880235,7 +880355,7 @@ async function inspectCliExternalRuntime(options) {
|
|
|
880235
880355
|
try {
|
|
880236
880356
|
const status = await fetchJson2(`${baseUrl}/status`, token.token, timeoutMs);
|
|
880237
880357
|
const statusRecord = isRecord42(status.body) ? status.body : {};
|
|
880238
|
-
const version6 =
|
|
880358
|
+
const version6 = readString54(statusRecord, "version") ?? "unknown";
|
|
880239
880359
|
const compatible = status.ok && version6 === SDK_VERSION;
|
|
880240
880360
|
if (!status.ok) {
|
|
880241
880361
|
return {
|
|
@@ -880453,7 +880573,7 @@ function output6(value) {
|
|
|
880453
880573
|
function error51(message) {
|
|
880454
880574
|
return { success: false, error: message };
|
|
880455
880575
|
}
|
|
880456
|
-
function
|
|
880576
|
+
function readString55(value) {
|
|
880457
880577
|
return typeof value === "string" ? value.trim() : "";
|
|
880458
880578
|
}
|
|
880459
880579
|
function readFieldMap2(value) {
|
|
@@ -880480,10 +880600,10 @@ function describeEditor(editor) {
|
|
|
880480
880600
|
}
|
|
880481
880601
|
function readRecordId(args2) {
|
|
880482
880602
|
const fields = readFieldMap2(args2.fields);
|
|
880483
|
-
return
|
|
880603
|
+
return readString55(args2.recordId ?? args2.id ?? fields.recordId ?? fields.id);
|
|
880484
880604
|
}
|
|
880485
880605
|
function requireConfirmed(args2, label) {
|
|
880486
|
-
if (!
|
|
880606
|
+
if (!readString55(args2.explicitUserRequest))
|
|
880487
880607
|
return `${label} requires explicitUserRequest with the user's exact request or a short faithful summary.`;
|
|
880488
880608
|
if (args2.confirm !== true)
|
|
880489
880609
|
return `${label} requires confirm:true after an explicit user request.`;
|
|
@@ -880611,7 +880731,7 @@ function localRegistryArgsForTarget(target, args2, recordId) {
|
|
|
880611
880731
|
...base2,
|
|
880612
880732
|
...edit,
|
|
880613
880733
|
...target.action === "stale" && fields.reason ? { reason: fields.reason } : {},
|
|
880614
|
-
...target.action === "delete" ? { confirm: args2.confirm, explicitUserRequest:
|
|
880734
|
+
...target.action === "delete" ? { confirm: args2.confirm, explicitUserRequest: readString55(args2.explicitUserRequest) } : {}
|
|
880615
880735
|
};
|
|
880616
880736
|
}
|
|
880617
880737
|
async function executeTool(toolRegistry, name51, toolArgs) {
|
|
@@ -880677,7 +880797,7 @@ async function runLocalWorkspaceAction(deps, action2, args2) {
|
|
|
880677
880797
|
if (missing.length > 0)
|
|
880678
880798
|
return output6({ status: "missing_required_fields", missing, action: action2.id, editor: describeEditor(editor) });
|
|
880679
880799
|
if (editor.kind === "knowledge-url")
|
|
880680
|
-
return executeTool(deps.toolRegistry, "agent_knowledge_ingest", { sourceKind: "url", url: fieldReader(editor, fields)("url"), tags: splitList5(fieldReader(editor, fields)("tags")), folderPath: fieldReader(editor, fields)("folder"), confirm: args2.confirm, explicitUserRequest:
|
|
880800
|
+
return executeTool(deps.toolRegistry, "agent_knowledge_ingest", { sourceKind: "url", url: fieldReader(editor, fields)("url"), tags: splitList5(fieldReader(editor, fields)("tags")), folderPath: fieldReader(editor, fields)("folder"), confirm: args2.confirm, explicitUserRequest: readString55(args2.explicitUserRequest) });
|
|
880681
880801
|
return executeTool(deps.toolRegistry, "agent_local_registry", localRegistryArgsFromEditor(editor, fields, recordId));
|
|
880682
880802
|
}
|
|
880683
880803
|
if (!target)
|
|
@@ -880686,19 +880806,19 @@ async function runLocalWorkspaceAction(deps, action2, args2) {
|
|
|
880686
880806
|
}
|
|
880687
880807
|
|
|
880688
880808
|
// src/tools/agent-harness-model-tool-catalog.ts
|
|
880689
|
-
function
|
|
880809
|
+
function readString56(value) {
|
|
880690
880810
|
return typeof value === "string" ? value.trim() : "";
|
|
880691
880811
|
}
|
|
880692
|
-
function
|
|
880812
|
+
function readLimit9(value, fallback) {
|
|
880693
880813
|
const parsed = typeof value === "string" && value.trim() ? Number(value) : value;
|
|
880694
880814
|
if (typeof parsed !== "number" || !Number.isFinite(parsed))
|
|
880695
880815
|
return fallback;
|
|
880696
880816
|
return Math.max(1, Math.min(500, Math.trunc(parsed)));
|
|
880697
880817
|
}
|
|
880698
880818
|
function listHarnessModelTools(toolRegistry, args2) {
|
|
880699
|
-
const query2 =
|
|
880819
|
+
const query2 = readString56(args2.query).toLowerCase();
|
|
880700
880820
|
const includeParameters = args2.includeParameters === true;
|
|
880701
|
-
const limit3 =
|
|
880821
|
+
const limit3 = readLimit9(args2.limit, 200);
|
|
880702
880822
|
return toolRegistry.getToolDefinitions().filter((tool2) => !query2 || [tool2.name, tool2.description, ...tool2.sideEffects ?? []].join(`
|
|
880703
880823
|
`).toLowerCase().includes(query2)).sort((a4, b3) => a4.name.localeCompare(b3.name)).slice(0, limit3).map((tool2) => ({
|
|
880704
880824
|
name: tool2.name,
|
|
@@ -880710,6 +880830,24 @@ function listHarnessModelTools(toolRegistry, args2) {
|
|
|
880710
880830
|
...includeParameters ? { parameters: tool2.parameters } : {}
|
|
880711
880831
|
}));
|
|
880712
880832
|
}
|
|
880833
|
+
function describeHarnessModelTool(toolRegistry, args2) {
|
|
880834
|
+
const query2 = readString56(args2.toolName || args2.target || args2.query).toLowerCase();
|
|
880835
|
+
if (!query2)
|
|
880836
|
+
return null;
|
|
880837
|
+
const tool2 = toolRegistry.getToolDefinitions().find((candidate) => candidate.name.toLowerCase() === query2 || candidate.name.toLowerCase().includes(query2));
|
|
880838
|
+
if (!tool2)
|
|
880839
|
+
return null;
|
|
880840
|
+
return {
|
|
880841
|
+
name: tool2.name,
|
|
880842
|
+
description: tool2.description,
|
|
880843
|
+
sideEffects: tool2.sideEffects ?? [],
|
|
880844
|
+
concurrency: tool2.concurrency ?? "parallel",
|
|
880845
|
+
supportsProgress: tool2.supportsProgress ?? false,
|
|
880846
|
+
supportsStreamingOutput: tool2.supportsStreamingOutput ?? false,
|
|
880847
|
+
parameters: tool2.parameters,
|
|
880848
|
+
policy: "This is a first-class model tool definition. Use the returned JSON schema directly; mutating or external side-effect tools still require the explicit confirmation arguments defined by that tool."
|
|
880849
|
+
};
|
|
880850
|
+
}
|
|
880713
880851
|
|
|
880714
880852
|
// src/tools/agent-harness-tool-schema.ts
|
|
880715
880853
|
var AGENT_HARNESS_MODES = [
|
|
@@ -880740,6 +880878,7 @@ var AGENT_HARNESS_MODES = [
|
|
|
880740
880878
|
"workspace_action",
|
|
880741
880879
|
"run_workspace_action",
|
|
880742
880880
|
"tools",
|
|
880881
|
+
"tool",
|
|
880743
880882
|
"connected_host",
|
|
880744
880883
|
"connected_host_status",
|
|
880745
880884
|
"connected_host_capability"
|
|
@@ -880758,11 +880897,11 @@ var AGENT_HARNESS_PARAMETER_PROPERTIES = {
|
|
|
880758
880897
|
},
|
|
880759
880898
|
query: {
|
|
880760
880899
|
type: "string",
|
|
880761
|
-
description: "Search text for command, setting, tool, or UI surface catalogs."
|
|
880900
|
+
description: "Search text for command, setting, tool, or UI surface catalogs, or a slash-command lookup for mode command."
|
|
880762
880901
|
},
|
|
880763
880902
|
command: {
|
|
880764
880903
|
type: "string",
|
|
880765
|
-
description: 'Full slash command string for mode run_command, for example "/settings get provider.model". In cli_command mode this may also hold a top-level CLI string such as "goodvibes-agent status --json".'
|
|
880904
|
+
description: 'Full slash command string for mode command or run_command, for example "/settings get provider.model". In cli_command mode this may also hold a top-level CLI string such as "goodvibes-agent status --json".'
|
|
880766
880905
|
},
|
|
880767
880906
|
cliCommand: {
|
|
880768
880907
|
type: "string",
|
|
@@ -880825,12 +880964,16 @@ var AGENT_HARNESS_PARAMETER_PROPERTIES = {
|
|
|
880825
880964
|
},
|
|
880826
880965
|
target: {
|
|
880827
880966
|
type: "string",
|
|
880828
|
-
description: "Optional
|
|
880967
|
+
description: "Optional lookup target, such as a model-picker target, slash command root or invocation, settings key, model tool name, or connected-host capability id."
|
|
880829
880968
|
},
|
|
880830
880969
|
capabilityId: {
|
|
880831
880970
|
type: "string",
|
|
880832
880971
|
description: "Connected-host allowed or blocked capability id for mode connected_host_capability, such as agent-knowledge-read or connected-host-lifecycle."
|
|
880833
880972
|
},
|
|
880973
|
+
toolName: {
|
|
880974
|
+
type: "string",
|
|
880975
|
+
description: "First-class model tool name for mode tool, such as agent_harness or agent_local_registry."
|
|
880976
|
+
},
|
|
880834
880977
|
category: {
|
|
880835
880978
|
type: "string",
|
|
880836
880979
|
description: "Setting category filter such as provider, behavior, tools, ui, tts, permissions, automation, or surfaces."
|
|
@@ -880962,10 +881105,10 @@ async function openTtsVoicePicker(ctx, providerArg) {
|
|
|
880962
881105
|
}
|
|
880963
881106
|
|
|
880964
881107
|
// src/tools/agent-harness-ui-surface-metadata.ts
|
|
880965
|
-
function
|
|
881108
|
+
function readString57(value) {
|
|
880966
881109
|
return typeof value === "string" ? value.trim() : "";
|
|
880967
881110
|
}
|
|
880968
|
-
function
|
|
881111
|
+
function readLimit10(value, fallback) {
|
|
880969
881112
|
const parsed = typeof value === "string" && value.trim() ? Number(value) : value;
|
|
880970
881113
|
if (typeof parsed !== "number" || !Number.isFinite(parsed))
|
|
880971
881114
|
return fallback;
|
|
@@ -880988,35 +881131,35 @@ function opened(surface, extra = {}) {
|
|
|
880988
881131
|
};
|
|
880989
881132
|
}
|
|
880990
881133
|
function optionalModelTarget(args2) {
|
|
880991
|
-
const target =
|
|
881134
|
+
const target = readString57(args2.target);
|
|
880992
881135
|
return target === "main" || target === "helper" || target === "tool" || target === "tts" ? target : undefined;
|
|
880993
881136
|
}
|
|
880994
881137
|
function optionalOnboardingMode(args2) {
|
|
880995
|
-
const target =
|
|
881138
|
+
const target = readString57(args2.target);
|
|
880996
881139
|
return target === "new" || target === "edit" || target === "reopen" ? target : undefined;
|
|
880997
881140
|
}
|
|
880998
881141
|
function workspaceCategory(args2) {
|
|
880999
|
-
return
|
|
881142
|
+
return readString57(args2.categoryId || args2.category || args2.target) || undefined;
|
|
881000
881143
|
}
|
|
881001
881144
|
function settingsTarget(args2) {
|
|
881002
|
-
return
|
|
881145
|
+
return readString57(args2.target || args2.key || args2.prefix) || undefined;
|
|
881003
881146
|
}
|
|
881004
881147
|
function providerTarget(args2) {
|
|
881005
|
-
return
|
|
881148
|
+
return readString57(args2.target || args2.key || args2.prefix) || undefined;
|
|
881006
881149
|
}
|
|
881007
881150
|
function optionalPane(args2) {
|
|
881008
|
-
const pane =
|
|
881151
|
+
const pane = readString57(args2.pane);
|
|
881009
881152
|
return pane === "top" || pane === "bottom" ? pane : undefined;
|
|
881010
881153
|
}
|
|
881011
881154
|
function surfaceInputText(args2) {
|
|
881012
|
-
return
|
|
881155
|
+
return readString57(args2.prefix || args2.key || (args2.surfaceId ? args2.query : undefined) || args2.target) || undefined;
|
|
881013
881156
|
}
|
|
881014
881157
|
function filePickerOptions(args2) {
|
|
881015
|
-
const target =
|
|
881158
|
+
const target = readString57(args2.target).toLowerCase();
|
|
881016
881159
|
const injectMode = target === "inject" || target === "inject-mode" || target === "!@";
|
|
881017
881160
|
return {
|
|
881018
881161
|
injectMode,
|
|
881019
|
-
query:
|
|
881162
|
+
query: readString57(args2.prefix || args2.key || (args2.surfaceId ? args2.query : undefined)) || undefined
|
|
881020
881163
|
};
|
|
881021
881164
|
}
|
|
881022
881165
|
function openAgentWorkspaceCategory(context, surface, categoryId, extra = {}) {
|
|
@@ -881592,19 +881735,19 @@ function totalHarnessUiSurfaces() {
|
|
|
881592
881735
|
return UI_SURFACES.length;
|
|
881593
881736
|
}
|
|
881594
881737
|
function listHarnessUiSurfaces(context, args2) {
|
|
881595
|
-
const query2 =
|
|
881596
|
-
const limit3 =
|
|
881738
|
+
const query2 = readString57(args2.query);
|
|
881739
|
+
const limit3 = readLimit10(args2.limit, 200);
|
|
881597
881740
|
return UI_SURFACES.map((surface) => describeSurface(context, surface)).filter((surface) => surfaceMatches(surface, query2)).slice(0, limit3);
|
|
881598
881741
|
}
|
|
881599
881742
|
function describeHarnessUiSurface(context, args2) {
|
|
881600
|
-
const surfaceId =
|
|
881743
|
+
const surfaceId = readString57(args2.surfaceId || args2.query);
|
|
881601
881744
|
if (!surfaceId)
|
|
881602
881745
|
return null;
|
|
881603
881746
|
const surface = UI_SURFACES.find((entry) => entry.id === surfaceId || entry.label.toLowerCase() === surfaceId.toLowerCase());
|
|
881604
881747
|
return surface ? describeSurface(context, surface) : null;
|
|
881605
881748
|
}
|
|
881606
881749
|
async function openHarnessUiSurface(context, args2) {
|
|
881607
|
-
const surfaceId =
|
|
881750
|
+
const surfaceId = readString57(args2.surfaceId || args2.query);
|
|
881608
881751
|
const surface = UI_SURFACES.find((entry) => entry.id === surfaceId || entry.label.toLowerCase() === surfaceId.toLowerCase());
|
|
881609
881752
|
if (!surface) {
|
|
881610
881753
|
return {
|
|
@@ -881624,16 +881767,16 @@ async function openHarnessUiSurface(context, args2) {
|
|
|
881624
881767
|
function isMode(value) {
|
|
881625
881768
|
return typeof value === "string" && AGENT_HARNESS_MODES.includes(value);
|
|
881626
881769
|
}
|
|
881627
|
-
function
|
|
881770
|
+
function readString58(value) {
|
|
881628
881771
|
return typeof value === "string" ? value.trim() : "";
|
|
881629
881772
|
}
|
|
881630
|
-
function
|
|
881773
|
+
function readLimit11(value, fallback) {
|
|
881631
881774
|
const parsed = typeof value === "string" && value.trim() ? Number(value) : value;
|
|
881632
881775
|
if (typeof parsed !== "number" || !Number.isFinite(parsed))
|
|
881633
881776
|
return fallback;
|
|
881634
881777
|
return Math.max(1, Math.min(500, Math.trunc(parsed)));
|
|
881635
881778
|
}
|
|
881636
|
-
function
|
|
881779
|
+
function readStringArray13(value) {
|
|
881637
881780
|
if (!Array.isArray(value))
|
|
881638
881781
|
return [];
|
|
881639
881782
|
return value.map((entry) => typeof entry === "string" ? entry : String(entry));
|
|
@@ -881652,30 +881795,6 @@ function output7(value) {
|
|
|
881652
881795
|
function error52(message) {
|
|
881653
881796
|
return { success: false, error: message };
|
|
881654
881797
|
}
|
|
881655
|
-
function commandMatches(command8, query2) {
|
|
881656
|
-
if (!query2)
|
|
881657
|
-
return true;
|
|
881658
|
-
const haystack = [
|
|
881659
|
-
command8.name,
|
|
881660
|
-
...command8.aliases ?? [],
|
|
881661
|
-
command8.description,
|
|
881662
|
-
command8.usage ?? "",
|
|
881663
|
-
command8.argsHint ?? ""
|
|
881664
|
-
].join(`
|
|
881665
|
-
`).toLowerCase();
|
|
881666
|
-
return haystack.includes(query2.toLowerCase());
|
|
881667
|
-
}
|
|
881668
|
-
function describeCommand(command8) {
|
|
881669
|
-
return {
|
|
881670
|
-
name: command8.name,
|
|
881671
|
-
slash: `/${command8.name}`,
|
|
881672
|
-
aliases: command8.aliases ?? [],
|
|
881673
|
-
description: command8.description,
|
|
881674
|
-
usage: command8.usage ?? "",
|
|
881675
|
-
argsHint: command8.argsHint ?? command8.usage ?? "",
|
|
881676
|
-
policy: describeCommandPolicy(command8.name)
|
|
881677
|
-
};
|
|
881678
|
-
}
|
|
881679
881798
|
function allWorkspaceActions() {
|
|
881680
881799
|
return AGENT_WORKSPACE_CATEGORIES.flatMap((category) => category.actions.map((action2) => ({ category, action: action2 })));
|
|
881681
881800
|
}
|
|
@@ -881708,7 +881827,7 @@ function describeWorkspaceEditor(editor) {
|
|
|
881708
881827
|
}
|
|
881709
881828
|
function selectedRoutineFromArgs(snapshot, args2) {
|
|
881710
881829
|
const fields = readFieldMap3(args2.fields);
|
|
881711
|
-
const routineId =
|
|
881830
|
+
const routineId = readString58(args2.recordId) || readString58(fields.routineId) || readString58(fields.id);
|
|
881712
881831
|
if (!routineId)
|
|
881713
881832
|
return null;
|
|
881714
881833
|
return snapshot.localRoutines.find((routine) => routine.id === routineId || routine.name.toLowerCase() === routineId.toLowerCase()) ?? null;
|
|
@@ -881776,17 +881895,17 @@ function localEditorModelExecution(editorKind) {
|
|
|
881776
881895
|
return "Use the command field, editor schema, or a first-class Agent model tool when available.";
|
|
881777
881896
|
}
|
|
881778
881897
|
function listWorkspaceActions(deps, args2) {
|
|
881779
|
-
const query2 =
|
|
881780
|
-
const categoryId =
|
|
881781
|
-
const limit3 =
|
|
881898
|
+
const query2 = readString58(args2.query);
|
|
881899
|
+
const categoryId = readString58(args2.categoryId || args2.category);
|
|
881900
|
+
const limit3 = readLimit11(args2.limit, 200);
|
|
881782
881901
|
const includeEditor = args2.includeParameters === true;
|
|
881783
881902
|
const editorContext = includeEditor ? buildWorkspaceEditorContext(deps.commandContext, args2) : null;
|
|
881784
881903
|
const source = query2 ? searchAgentWorkspaceActions(AGENT_WORKSPACE_CATEGORIES, query2).map((result2) => ({ category: result2.category, action: result2.action })) : allWorkspaceActions();
|
|
881785
881904
|
return source.filter((entry) => !categoryId || entry.category.id === categoryId).slice(0, limit3).map((entry) => describeWorkspaceAction(entry.category, entry.action, { includeEditor, editorContext }));
|
|
881786
881905
|
}
|
|
881787
881906
|
function findWorkspaceAction(args2) {
|
|
881788
|
-
const actionId =
|
|
881789
|
-
const categoryId =
|
|
881907
|
+
const actionId = readString58(args2.actionId || args2.query);
|
|
881908
|
+
const categoryId = readString58(args2.categoryId || args2.category);
|
|
881790
881909
|
if (!actionId)
|
|
881791
881910
|
return null;
|
|
881792
881911
|
return allWorkspaceActions().find((entry) => {
|
|
@@ -881795,13 +881914,8 @@ function findWorkspaceAction(args2) {
|
|
|
881795
881914
|
return entry.action.id === actionId || entry.action.label.toLowerCase() === actionId.toLowerCase();
|
|
881796
881915
|
}) ?? null;
|
|
881797
881916
|
}
|
|
881798
|
-
function listCommands(commandRegistry, args2) {
|
|
881799
|
-
const query2 = readString57(args2.query);
|
|
881800
|
-
const limit3 = readLimit10(args2.limit, 200);
|
|
881801
|
-
return commandRegistry.list().filter((command8) => commandMatches(command8, query2)).sort((a4, b3) => a4.name.localeCompare(b3.name)).slice(0, limit3).map(describeCommand);
|
|
881802
|
-
}
|
|
881803
881917
|
function requireConfirmedAction(args2, action2) {
|
|
881804
|
-
const explicitUserRequest =
|
|
881918
|
+
const explicitUserRequest = readString58(args2.explicitUserRequest);
|
|
881805
881919
|
if (!explicitUserRequest)
|
|
881806
881920
|
return `${action2} requires explicitUserRequest with the user's exact request or a short faithful summary.`;
|
|
881807
881921
|
if (args2.confirm !== true)
|
|
@@ -881809,7 +881923,7 @@ function requireConfirmedAction(args2, action2) {
|
|
|
881809
881923
|
return null;
|
|
881810
881924
|
}
|
|
881811
881925
|
function commandFromArgs(args2) {
|
|
881812
|
-
const rawCommand =
|
|
881926
|
+
const rawCommand = readString58(args2.command);
|
|
881813
881927
|
if (rawCommand) {
|
|
881814
881928
|
const parsed = parseSlashCommand(rawCommand);
|
|
881815
881929
|
if (!parsed.name)
|
|
@@ -881819,10 +881933,10 @@ function commandFromArgs(args2) {
|
|
|
881819
881933
|
args: parsed.args
|
|
881820
881934
|
};
|
|
881821
881935
|
}
|
|
881822
|
-
const commandName =
|
|
881936
|
+
const commandName = readString58(args2.commandName).replace(/^\//, "");
|
|
881823
881937
|
if (!commandName)
|
|
881824
881938
|
return null;
|
|
881825
|
-
const commandArgs =
|
|
881939
|
+
const commandArgs = readStringArray13(args2.args);
|
|
881826
881940
|
return {
|
|
881827
881941
|
name: commandName,
|
|
881828
881942
|
args: commandArgs
|
|
@@ -882010,7 +882124,7 @@ function createAgentHarnessTool(deps) {
|
|
|
882010
882124
|
name: "agent_harness",
|
|
882011
882125
|
description: [
|
|
882012
882126
|
"Discover and operate the GoodVibes Agent harness from the main conversation.",
|
|
882013
|
-
"Use this tool to inspect Agent workspace actions, built-in panels, top-level CLI mirrors, UI surfaces, keybindings, slash commands with policy metadata, model tools, connected-host capabilities or one connected-host capability detail, and Agent settings, or to invoke a workspace action/command through the same in-process command registry the user uses in the TUI.",
|
|
882127
|
+
"Use this tool to inspect Agent workspace actions, built-in panels, top-level CLI mirrors, UI surfaces, keybindings, slash commands with policy metadata, model tools or one model tool schema, connected-host capabilities or one connected-host capability detail, and Agent settings, or to invoke a workspace action/command through the same in-process command registry the user uses in the TUI.",
|
|
882014
882128
|
"Discovery modes are read-only. Setting/keybinding writes, resets, UI routing, slash command invocation, and workspace action invocation require confirm:true plus explicitUserRequest.",
|
|
882015
882129
|
"This tool preserves Agent product boundaries: connected-host lifecycle and listener posture stay externally owned, connected-host mode reports allowed and blocked route families, and secret-backed settings store raw values through the secret manager while config receives only a secret reference."
|
|
882016
882130
|
].join(" "),
|
|
@@ -882046,10 +882160,10 @@ function createAgentHarnessTool(deps) {
|
|
|
882046
882160
|
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.',
|
|
882047
882161
|
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.',
|
|
882048
882162
|
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.',
|
|
882049
|
-
slashCommands: 'Use mode:"commands" and mode:"command" to inspect; use mode:"run_command" with confirm:true plus explicitUserRequest to execute.',
|
|
882163
|
+
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.',
|
|
882050
882164
|
workspace: 'Use mode:"workspace_actions" to list and mode:"workspace_action" for editor schemas; set includeParameters:true on workspace_actions to inline editor schemas.',
|
|
882051
882165
|
settings: 'Use mode:"settings", mode:"get_setting", mode:"set_setting", and mode:"reset_setting".',
|
|
882052
|
-
tools: 'Use mode:"tools"
|
|
882166
|
+
tools: 'Use mode:"tools" to list first-class model tools, or mode:"tool" with toolName, target, or query to inspect one schema.',
|
|
882053
882167
|
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.',
|
|
882054
882168
|
connectedHostStatus: 'Use mode:"connected_host_status" for live read-only host reachability, SDK compatibility, token posture, and Agent Knowledge route readiness.'
|
|
882055
882169
|
},
|
|
@@ -882081,7 +882195,7 @@ function createAgentHarnessTool(deps) {
|
|
|
882081
882195
|
}
|
|
882082
882196
|
if (args2.mode === "panel") {
|
|
882083
882197
|
const panel = describeHarnessPanel(deps.commandContext, args2);
|
|
882084
|
-
return panel ? output7(panel) : error52(`Unknown panel ${
|
|
882198
|
+
return panel ? output7(panel) : error52(`Unknown panel ${readString58(args2.panelId || args2.query) || "<missing>"}.`);
|
|
882085
882199
|
}
|
|
882086
882200
|
if (args2.mode === "open_panel") {
|
|
882087
882201
|
const confirmationError2 = requireConfirmedAction(args2, "Panel routing");
|
|
@@ -882095,7 +882209,7 @@ function createAgentHarnessTool(deps) {
|
|
|
882095
882209
|
}
|
|
882096
882210
|
if (args2.mode === "ui_surface") {
|
|
882097
882211
|
const surface = describeHarnessUiSurface(deps.commandContext, args2);
|
|
882098
|
-
return surface ? output7(surface) : error52(`Unknown UI surface ${
|
|
882212
|
+
return surface ? output7(surface) : error52(`Unknown UI surface ${readString58(args2.surfaceId || args2.query) || "<missing>"}.`);
|
|
882099
882213
|
}
|
|
882100
882214
|
if (args2.mode === "open_ui_surface") {
|
|
882101
882215
|
const confirmationError2 = requireConfirmedAction(args2, "UI surface routing");
|
|
@@ -882109,7 +882223,7 @@ function createAgentHarnessTool(deps) {
|
|
|
882109
882223
|
return output7(listHarnessKeybindings(deps.commandContext, args2));
|
|
882110
882224
|
if (args2.mode === "keybinding") {
|
|
882111
882225
|
const binding = describeHarnessKeybinding(deps.commandContext, args2);
|
|
882112
|
-
return binding ? output7(binding) : error52(`Unknown keybinding action ${
|
|
882226
|
+
return binding ? output7(binding) : error52(`Unknown keybinding action ${readString58(args2.actionId || args2.key || args2.query) || "<missing>"}.`);
|
|
882113
882227
|
}
|
|
882114
882228
|
if (args2.mode === "set_keybinding") {
|
|
882115
882229
|
const confirmationError2 = requireConfirmedAction(args2, "Keybinding mutation");
|
|
@@ -882124,28 +882238,28 @@ function createAgentHarnessTool(deps) {
|
|
|
882124
882238
|
return output7(resetHarnessKeybinding(deps.commandContext, args2));
|
|
882125
882239
|
}
|
|
882126
882240
|
if (args2.mode === "commands") {
|
|
882127
|
-
const commands3 =
|
|
882241
|
+
const commands3 = listHarnessCommands(deps.commandRegistry, args2);
|
|
882128
882242
|
return output7({ commands: commands3, returned: commands3.length, total: deps.commandRegistry.list().length });
|
|
882129
882243
|
}
|
|
882130
882244
|
if (args2.mode === "command") {
|
|
882131
|
-
const
|
|
882132
|
-
const
|
|
882133
|
-
return
|
|
882245
|
+
const detail = describeHarnessCommand(deps.commandRegistry, args2);
|
|
882246
|
+
const query2 = readString58(args2.command || args2.commandName || args2.target || args2.query);
|
|
882247
|
+
return detail ? output7(detail) : error52(`Unknown slash command ${query2 || "<missing>"}. Use mode:"commands" to inspect available commands.`);
|
|
882134
882248
|
}
|
|
882135
882249
|
if (args2.mode === "run_command")
|
|
882136
882250
|
return runCommand2(deps, args2);
|
|
882137
882251
|
if (args2.mode === "settings") {
|
|
882138
882252
|
const settings = listHarnessSettings(deps.commandContext.platform.configManager, {
|
|
882139
|
-
category:
|
|
882140
|
-
prefix:
|
|
882141
|
-
query:
|
|
882253
|
+
category: readString58(args2.category) || undefined,
|
|
882254
|
+
prefix: readString58(args2.prefix) || undefined,
|
|
882255
|
+
query: readString58(args2.query) || undefined,
|
|
882142
882256
|
includeHidden: args2.includeHidden === true,
|
|
882143
|
-
limit:
|
|
882257
|
+
limit: readLimit11(args2.limit, 100)
|
|
882144
882258
|
});
|
|
882145
882259
|
return output7({ settings, returned: settings.length, policy: settingsPolicySummary() });
|
|
882146
882260
|
}
|
|
882147
882261
|
if (args2.mode === "get_setting") {
|
|
882148
|
-
const key =
|
|
882262
|
+
const key = readString58(args2.key);
|
|
882149
882263
|
const setting = getHarnessSetting(deps.commandContext.platform.configManager, key);
|
|
882150
882264
|
return setting ? output7(setting) : error52(`Unknown setting ${key || "<missing>"}.`);
|
|
882151
882265
|
}
|
|
@@ -882155,7 +882269,7 @@ function createAgentHarnessTool(deps) {
|
|
|
882155
882269
|
return error52(confirmationError2);
|
|
882156
882270
|
if (args2.value === undefined)
|
|
882157
882271
|
return error52("set_setting requires value.");
|
|
882158
|
-
const key =
|
|
882272
|
+
const key = readString58(args2.key);
|
|
882159
882273
|
const result2 = await setHarnessSetting(deps.commandContext.platform.configManager, deps.commandContext.platform.secretsManager, key, args2.value);
|
|
882160
882274
|
return output7(result2);
|
|
882161
882275
|
}
|
|
@@ -882163,7 +882277,7 @@ function createAgentHarnessTool(deps) {
|
|
|
882163
882277
|
const confirmationError2 = requireConfirmedAction(args2, "Setting reset");
|
|
882164
882278
|
if (confirmationError2)
|
|
882165
882279
|
return error52(confirmationError2);
|
|
882166
|
-
const key =
|
|
882280
|
+
const key = readString58(args2.key);
|
|
882167
882281
|
const result2 = await resetHarnessSetting(deps.commandContext.platform.configManager, deps.commandContext.platform.secretsManager, key);
|
|
882168
882282
|
return output7(result2);
|
|
882169
882283
|
}
|
|
@@ -882180,7 +882294,7 @@ function createAgentHarnessTool(deps) {
|
|
|
882180
882294
|
if (args2.mode === "workspace_action") {
|
|
882181
882295
|
const found = findWorkspaceAction(args2);
|
|
882182
882296
|
const editorContext = buildWorkspaceEditorContext(deps.commandContext, args2);
|
|
882183
|
-
return found ? output7(describeWorkspaceAction(found.category, found.action, { includeEditor: true, editorContext })) : error52(`Unknown Agent workspace action ${
|
|
882297
|
+
return found ? output7(describeWorkspaceAction(found.category, found.action, { includeEditor: true, editorContext })) : error52(`Unknown Agent workspace action ${readString58(args2.actionId || args2.query) || "<missing>"}.`);
|
|
882184
882298
|
}
|
|
882185
882299
|
if (args2.mode === "run_workspace_action")
|
|
882186
882300
|
return runWorkspaceAction(deps, args2);
|
|
@@ -882188,10 +882302,15 @@ function createAgentHarnessTool(deps) {
|
|
|
882188
882302
|
const tools3 = listHarnessModelTools(deps.toolRegistry, args2);
|
|
882189
882303
|
return output7({ tools: tools3, returned: tools3.length, total: deps.toolRegistry.getToolDefinitions().length });
|
|
882190
882304
|
}
|
|
882305
|
+
if (args2.mode === "tool") {
|
|
882306
|
+
const query2 = readString58(args2.toolName || args2.target || args2.query);
|
|
882307
|
+
const tool2 = describeHarnessModelTool(deps.toolRegistry, args2);
|
|
882308
|
+
return tool2 ? output7(tool2) : error52(`Unknown model tool ${query2 || "<missing>"}. Use mode:"tools" to inspect available model tools.`);
|
|
882309
|
+
}
|
|
882191
882310
|
if (args2.mode === "connected_host")
|
|
882192
882311
|
return output7(connectedHostSummary(deps.commandContext, deps.toolRegistry));
|
|
882193
882312
|
if (args2.mode === "connected_host_capability") {
|
|
882194
|
-
const query2 =
|
|
882313
|
+
const query2 = readString58(args2.capabilityId || args2.target || args2.query);
|
|
882195
882314
|
const capability = describeConnectedHostCapability(deps.toolRegistry, query2);
|
|
882196
882315
|
return capability ? output7(capability) : error52(`Unknown connected-host capability ${query2 || "<missing>"}. Use mode:"connected_host" to inspect allowed and blocked capability ids.`);
|
|
882197
882316
|
}
|
package/docs/README.md
CHANGED
|
@@ -22,7 +22,7 @@ Important baseline constraints:
|
|
|
22
22
|
- Agent depends on `@pellux/goodvibes-sdk@0.33.35`.
|
|
23
23
|
- Agent connects to a GoodVibes host owned outside this product.
|
|
24
24
|
- Agent does not start, stop, restart, install, uninstall, or own the connected GoodVibes host.
|
|
25
|
-
- User-facing Agent workspace actions, built-in panels, modal/overlay/picker UI surfaces, named operator surfaces, top-level CLI mirrors, fixed shortcuts, configurable keybindings, slash commands, command policy metadata, model tools, settings, local registries, connected-host capability boundaries, single connected-host capability inspection, and live connected-host readiness are model-visible through Agent-owned tools. Visible UI routing includes the command browser, reasoning-effort picker, live process output, runtime activity, settings, workspaces, and pickers the user can open. Local memory, note, persona, skill, and routine create editors can also run through confirmed workspace actions. Mutations and visible UI routing remain explicit and confirmation-gated.
|
|
25
|
+
- User-facing Agent workspace actions, built-in panels, modal/overlay/picker UI surfaces, named operator surfaces, top-level CLI mirrors, fixed shortcuts, configurable keybindings, slash commands, single-command lookup with policy metadata, model tools and individual model tool schemas, settings, local registries, connected-host capability boundaries, single connected-host capability inspection, and live connected-host readiness are model-visible through Agent-owned tools. Visible UI routing includes the command browser, reasoning-effort picker, live process output, runtime activity, settings, workspaces, and pickers the user can open. Local memory, note, persona, skill, and routine create editors can also run through confirmed workspace actions. Mutations and visible UI routing remain explicit and confirmation-gated.
|
|
26
26
|
- Agent Knowledge uses only `/api/goodvibes-agent/knowledge/*`; there is no default knowledge or non-Agent product fallback.
|
|
27
27
|
- Agent supports isolated Agent homes with `GOODVIBES_AGENT_HOME=<path>` and named profile homes with `goodvibes-agent profiles create <name> --template <starter> --yes` plus `--agent-profile <name>`.
|
|
28
28
|
- Agent supports connected-host URL overrides with `--runtime-url http://host:port` or `GOODVIBES_AGENT_RUNTIME_URL=http://host:port`; these only change the Agent connection target.
|
package/docs/getting-started.md
CHANGED
|
@@ -44,7 +44,7 @@ After setup has been applied once, the TUI opens directly into the Agent operato
|
|
|
44
44
|
|
|
45
45
|
Press `/` inside the Agent workspace to search every workspace action by name, category, command, or detail. Use that finder before reaching for shell commands; CLI subcommands are scriptable mirrors of these TUI workflows.
|
|
46
46
|
|
|
47
|
-
The model can inspect and use the same harness surface through Agent-owned tools. `agent_harness` exposes workspace action discovery, built-in panel discovery/routing, modal/overlay/picker UI surface discovery/routing, top-level CLI mirror discovery, fixed shortcut and configurable keybinding discovery, keybinding mutation with confirmation, slash-command discovery, command policy metadata, command execution with confirmation, model tool discovery, settings inspection/mutation, connected-host capability inventory, single connected-host capability inspection, and live connected-host readiness posture. CLI mirror modes are read-only catalog/parser inspection and point the model to the matching in-process tool, workspace action, setting mode, or slash-command mirror. Panel modes expose catalog/open state and route visible panel/workspace changes through the current Agent shell bridge with confirmation. UI surface modes expose help, shortcuts, command browser, conversation search, prompt-history search, slash-command mode, file picker, block actions, context, runtime activity, live process output, bookmarks, model/provider/reasoning-effort pickers, TTS provider/voice pickers, session/profile pickers, the panel-picker compatibility route, security/knowledge/subscription operator surfaces, settings, MCP workspace, onboarding, and Agent workspace entrypoints; `open_ui_surface` is confirmation-gated and only performs visible shell navigation. Shortcut modes expose the fixed runtime/editor shortcuts and the live keybindings table; confirmed keybinding edits write the same `keybindings.json` file the user edits and reload the runtime manager. Workspace action discovery can include editor field schemas with `includeParameters:true`, including starter-template defaults for profile creation and selected-routine defaults for routine schedule promotion when `recordId` is supplied. Selection-based local workspace actions accept a local `recordId`, so the model can use the same note promotion and local registry flows as the TUI. Direct local create editors for memory, notes, personas, skills, and routines can execute from submitted fields through `run_workspace_action` and `agent_local_registry` with confirmation. First-class model tools cover the main product workflows directly: Agent Knowledge, Agent Knowledge ingest, Agent-local memory/notes/personas/skills/routines, operator actions, notifications, channel sends, reminders, generated media, and work plans.
|
|
47
|
+
The model can inspect and use the same harness surface through Agent-owned tools. `agent_harness` exposes workspace action discovery, built-in panel discovery/routing, modal/overlay/picker UI surface discovery/routing, top-level CLI mirror discovery, fixed shortcut and configurable keybinding discovery, keybinding mutation with confirmation, slash-command discovery, single slash-command inspection by typed command or lookup text, command policy metadata, command execution with confirmation, model tool discovery and single-tool schema inspection, settings inspection/mutation, connected-host capability inventory, single connected-host capability inspection, and live connected-host readiness posture. CLI mirror modes are read-only catalog/parser inspection and point the model to the matching in-process tool, workspace action, setting mode, or slash-command mirror. Panel modes expose catalog/open state and route visible panel/workspace changes through the current Agent shell bridge with confirmation. UI surface modes expose help, shortcuts, command browser, conversation search, prompt-history search, slash-command mode, file picker, block actions, context, runtime activity, live process output, bookmarks, model/provider/reasoning-effort pickers, TTS provider/voice pickers, session/profile pickers, the panel-picker compatibility route, security/knowledge/subscription operator surfaces, settings, MCP workspace, onboarding, and Agent workspace entrypoints; `open_ui_surface` is confirmation-gated and only performs visible shell navigation. Shortcut modes expose the fixed runtime/editor shortcuts and the live keybindings table; confirmed keybinding edits write the same `keybindings.json` file the user edits and reload the runtime manager. Workspace action discovery can include editor field schemas with `includeParameters:true`, including starter-template defaults for profile creation and selected-routine defaults for routine schedule promotion when `recordId` is supplied. Selection-based local workspace actions accept a local `recordId`, so the model can use the same note promotion and local registry flows as the TUI. Direct local create editors for memory, notes, personas, skills, and routines can execute from submitted fields through `run_workspace_action` and `agent_local_registry` with confirmation. First-class model tools cover the main product workflows directly: Agent Knowledge, Agent Knowledge ingest, Agent-local memory/notes/personas/skills/routines, operator actions, notifications, channel sends, reminders, generated media, and work plans.
|
|
48
48
|
|
|
49
49
|
Use the Artifacts area for concrete files and generated output: attach images to prompts, export conversations or saved sessions, ingest local source files and URL lists into Agent Knowledge, import bookmarks or browser history, inspect source records, and generate media artifacts from confirmed prompts.
|
|
50
50
|
|
|
@@ -43,14 +43,14 @@ Host-management and coding-first commands that would imply connected-host lifecy
|
|
|
43
43
|
|
|
44
44
|
The main Agent model has an Agent-owned harness bridge rather than generic SDK settings/context control. Use these model tools as the supported parity layer:
|
|
45
45
|
|
|
46
|
-
- `agent_harness`: inspect workspace categories/actions, inspect built-in panels, inspect modal/overlay/picker UI surfaces and named operator surfaces, inspect top-level CLI mirrors, inspect fixed shortcuts and configurable keybindings, inspect slash commands and command policy metadata, run concrete workspace or slash-command mirrors with confirmation, inspect model tools, inspect or change Agent settings/keybindings, inspect connected-host capability boundaries or one connected-host capability, and inspect live connected-host readiness.
|
|
46
|
+
- `agent_harness`: inspect workspace categories/actions, inspect built-in panels, inspect modal/overlay/picker UI surfaces and named operator surfaces, inspect top-level CLI mirrors, inspect fixed shortcuts and configurable keybindings, inspect slash commands and one slash command by typed command or lookup text with policy metadata, run concrete workspace or slash-command mirrors with confirmation, inspect model tools or one model tool schema, inspect or change Agent settings/keybindings, inspect connected-host capability boundaries or one connected-host capability, and inspect live connected-host readiness.
|
|
47
47
|
- `agent_local_registry`: inspect and maintain Agent-local memory, notes, personas, skills, skill bundles, and routines. Deleting local records requires `confirm:true` and `explicitUserRequest`.
|
|
48
48
|
- `agent_knowledge` and `agent_knowledge_ingest`: ask/search and ingest into the isolated Agent Knowledge segment.
|
|
49
49
|
- `agent_operator_briefing` and `agent_operator_action`: inspect connected work/approval/automation posture, or run exact confirmed approval/automation actions.
|
|
50
50
|
- `agent_work_plan`: keep the visible Agent-local work plan current from the conversation.
|
|
51
51
|
- `agent_channel_send`, `agent_notify`, `agent_reminder_schedule`, and `agent_media_generate`: perform confirmed external delivery, notification, reminder, or media actions when the user explicitly asks.
|
|
52
52
|
|
|
53
|
-
`agent_harness` discovery modes are read-only. `summary` reports the model access map; `panels` and `panel` return the built-in panel catalog, current open/focused state, and each panel's matching Agent workspace route; `ui_surfaces` and `ui_surface` return modal, overlay, picker, and workspace entrypoints with shell-opener availability and preferred model routes; `cli_commands` and `cli_command` return top-level package CLI mirror metadata, parser output, blocked command tokens, and preferred in-process model routes; `shortcuts` returns fixed runtime/editor shortcuts plus configurable keybindings; `keybindings` and `keybinding` return the live resolved keybinding table, default bindings, custom state, and config path; `commands`
|
|
53
|
+
`agent_harness` discovery modes are read-only. `summary` reports the model access map; `panels` and `panel` return the built-in panel catalog, current open/focused state, and each panel's matching Agent workspace route; `ui_surfaces` and `ui_surface` return modal, overlay, picker, and workspace entrypoints with shell-opener availability and preferred model routes; `cli_commands` and `cli_command` return top-level package CLI mirror metadata, parser output, blocked command tokens, and preferred in-process model routes; `shortcuts` returns fixed runtime/editor shortcuts plus configurable keybindings; `keybindings` and `keybinding` return the live resolved keybinding table, default bindings, custom state, and config path; `commands` lists slash-command descriptions; `command` returns one slash-command detail by `command`, `commandName`, `target`, or `query`, including parsed arguments plus effect/confirmation/preferred-tool/boundary policy metadata; `workspace_actions` lists Agent workspace actions and can inline editor field schemas with `includeParameters:true`; `workspace_action` returns one action with its editor schema; `tools` lists model tool definitions and can inline JSON schemas with `includeParameters:true`; `tool` returns one model tool schema by `toolName`, `target`, or `query`; `settings` returns setting descriptors plus setting policy; `connected_host` returns the connected-host route families, allowed capabilities, blocked capabilities, and first-class tool availability; `connected_host_capability` returns one allowed or blocked connected-host capability by `capabilityId`, `target`, or `query` with related route families and boundary text; and `connected_host_status` performs a live read-only check of the connected-host status and Agent Knowledge status routes and reports endpoint bindings, token posture, SDK compatibility, route readiness, and findings without printing token values.
|
|
54
54
|
|
|
55
55
|
`open_ui_surface` is a confirmation-gated visible navigation mode for the same shell surfaces the user can open: Agent workspace, settings, MCP workspace, model/provider/reasoning-effort pickers, TTS provider/voice pickers, session/profile pickers, the panel-picker compatibility route, security/knowledge/subscription operator surfaces, conversation search, prompt-history search, slash-command mode, command browser, file picker, block actions, bookmarks, context inspector, runtime activity monitor, live process output, help, shortcuts, and onboarding. It does not perform hidden operations; use first-class model tools, settings modes, workspace actions, or confirmed slash-command mirrors for actual state changes.
|
|
56
56
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pellux/goodvibes-agent",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.15",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "GoodVibes personal operator assistant TUI with a proactive Agent product brain, isolated Agent Knowledge, local profiles, routines, skills, personas, and explicit build delegation.",
|
|
6
6
|
"type": "module",
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import type { CommandRegistry, SlashCommand } from '../input/command-registry.ts';
|
|
2
|
+
import { parseSlashCommand } from '../input/slash-command-parser.ts';
|
|
3
|
+
import { describeCommandPolicy } from './agent-harness-metadata.ts';
|
|
4
|
+
|
|
5
|
+
export interface AgentHarnessCommandCatalogArgs {
|
|
6
|
+
readonly query?: unknown;
|
|
7
|
+
readonly command?: unknown;
|
|
8
|
+
readonly commandName?: unknown;
|
|
9
|
+
readonly args?: unknown;
|
|
10
|
+
readonly target?: unknown;
|
|
11
|
+
readonly limit?: unknown;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface CommandDetailLookup {
|
|
15
|
+
readonly source: 'command' | 'commandName' | 'target' | 'query';
|
|
16
|
+
readonly input: string;
|
|
17
|
+
readonly parsedName: string;
|
|
18
|
+
readonly parsedArgs: readonly string[];
|
|
19
|
+
readonly resolvedBy: 'name' | 'alias' | 'case-insensitive-name' | 'case-insensitive-alias' | 'description' | 'prefix';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function readString(value: unknown): string {
|
|
23
|
+
return typeof value === 'string' ? value.trim() : '';
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function readLimit(value: unknown, fallback: number): number {
|
|
27
|
+
const parsed = typeof value === 'string' && value.trim() ? Number(value) : value;
|
|
28
|
+
if (typeof parsed !== 'number' || !Number.isFinite(parsed)) return fallback;
|
|
29
|
+
return Math.max(1, Math.min(500, Math.trunc(parsed)));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function readStringArray(value: unknown): readonly string[] {
|
|
33
|
+
if (!Array.isArray(value)) return [];
|
|
34
|
+
return value.map((entry) => typeof entry === 'string' ? entry : String(entry));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
function commandMatches(command: SlashCommand, query: string): boolean {
|
|
38
|
+
if (!query) return true;
|
|
39
|
+
const haystack = [
|
|
40
|
+
command.name,
|
|
41
|
+
...(command.aliases ?? []),
|
|
42
|
+
command.description,
|
|
43
|
+
command.usage ?? '',
|
|
44
|
+
command.argsHint ?? '',
|
|
45
|
+
].join('\n').toLowerCase();
|
|
46
|
+
return haystack.includes(query.toLowerCase());
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function describeCommand(command: SlashCommand, lookup?: CommandDetailLookup): Record<string, unknown> {
|
|
50
|
+
return {
|
|
51
|
+
name: command.name,
|
|
52
|
+
slash: `/${command.name}`,
|
|
53
|
+
aliases: command.aliases ?? [],
|
|
54
|
+
description: command.description,
|
|
55
|
+
usage: command.usage ?? '',
|
|
56
|
+
argsHint: command.argsHint ?? command.usage ?? '',
|
|
57
|
+
...(lookup ? {
|
|
58
|
+
lookup: {
|
|
59
|
+
source: lookup.source,
|
|
60
|
+
input: lookup.input,
|
|
61
|
+
parsedName: lookup.parsedName,
|
|
62
|
+
parsedArgs: lookup.parsedArgs,
|
|
63
|
+
resolvedBy: lookup.resolvedBy,
|
|
64
|
+
},
|
|
65
|
+
} : {}),
|
|
66
|
+
policy: describeCommandPolicy(command.name),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function commandDetailLookupFromArgs(args: AgentHarnessCommandCatalogArgs): Omit<CommandDetailLookup, 'resolvedBy'> | null {
|
|
71
|
+
const rawCommand = readString(args.command);
|
|
72
|
+
if (rawCommand) {
|
|
73
|
+
const parsed = parseSlashCommand(rawCommand);
|
|
74
|
+
return { source: 'command', input: rawCommand, parsedName: parsed.name, parsedArgs: parsed.args };
|
|
75
|
+
}
|
|
76
|
+
const rawCommandName = readString(args.commandName);
|
|
77
|
+
if (rawCommandName) {
|
|
78
|
+
const parsed = parseSlashCommand(rawCommandName);
|
|
79
|
+
const explicitArgs = readStringArray(args.args);
|
|
80
|
+
return {
|
|
81
|
+
source: 'commandName',
|
|
82
|
+
input: rawCommandName,
|
|
83
|
+
parsedName: parsed.name,
|
|
84
|
+
parsedArgs: explicitArgs.length > 0 ? explicitArgs : parsed.args,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
const rawTarget = readString(args.target);
|
|
88
|
+
if (rawTarget) {
|
|
89
|
+
const parsed = parseSlashCommand(rawTarget);
|
|
90
|
+
return { source: 'target', input: rawTarget, parsedName: parsed.name, parsedArgs: parsed.args };
|
|
91
|
+
}
|
|
92
|
+
const rawQuery = readString(args.query);
|
|
93
|
+
if (rawQuery) {
|
|
94
|
+
const parsed = parseSlashCommand(rawQuery);
|
|
95
|
+
return { source: 'query', input: rawQuery, parsedName: parsed.name, parsedArgs: parsed.args };
|
|
96
|
+
}
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function resolveCommandDetail(commandRegistry: CommandRegistry, args: AgentHarnessCommandCatalogArgs): { readonly command: SlashCommand; readonly lookup: CommandDetailLookup } | null {
|
|
101
|
+
const lookup = commandDetailLookupFromArgs(args);
|
|
102
|
+
if (!lookup?.parsedName) return null;
|
|
103
|
+
const direct = commandRegistry.get(lookup.parsedName);
|
|
104
|
+
if (direct) {
|
|
105
|
+
return {
|
|
106
|
+
command: direct,
|
|
107
|
+
lookup: {
|
|
108
|
+
...lookup,
|
|
109
|
+
resolvedBy: direct.name === lookup.parsedName ? 'name' : 'alias',
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const normalized = lookup.parsedName.toLowerCase();
|
|
115
|
+
for (const command of commandRegistry.list()) {
|
|
116
|
+
if (command.name.toLowerCase() === normalized) {
|
|
117
|
+
return { command, lookup: { ...lookup, resolvedBy: 'case-insensitive-name' } };
|
|
118
|
+
}
|
|
119
|
+
if ((command.aliases ?? []).some((alias) => alias.toLowerCase() === normalized)) {
|
|
120
|
+
return { command, lookup: { ...lookup, resolvedBy: 'case-insensitive-alias' } };
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const descriptionMatches = commandRegistry.list().filter((command) => commandMatches(command, lookup.input));
|
|
125
|
+
if (descriptionMatches.length === 1) {
|
|
126
|
+
return { command: descriptionMatches[0]!, lookup: { ...lookup, resolvedBy: 'description' } };
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const prefixMatches = commandRegistry.fuzzyMatch(lookup.parsedName).filter((entry) => entry.score >= 80);
|
|
130
|
+
if (prefixMatches.length === 1) {
|
|
131
|
+
return { command: prefixMatches[0]!.command, lookup: { ...lookup, resolvedBy: 'prefix' } };
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export function listHarnessCommands(commandRegistry: CommandRegistry, args: AgentHarnessCommandCatalogArgs): readonly Record<string, unknown>[] {
|
|
137
|
+
const query = readString(args.query);
|
|
138
|
+
const limit = readLimit(args.limit, 200);
|
|
139
|
+
return commandRegistry.list()
|
|
140
|
+
.filter((command) => commandMatches(command, query))
|
|
141
|
+
.sort((a, b) => a.name.localeCompare(b.name))
|
|
142
|
+
.slice(0, limit)
|
|
143
|
+
.map((command) => describeCommand(command));
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function describeHarnessCommand(commandRegistry: CommandRegistry, args: AgentHarnessCommandCatalogArgs): Record<string, unknown> | null {
|
|
147
|
+
const detail = resolveCommandDetail(commandRegistry, args);
|
|
148
|
+
return detail ? describeCommand(detail.command, detail.lookup) : null;
|
|
149
|
+
}
|
|
@@ -2,6 +2,8 @@ import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
|
|
|
2
2
|
|
|
3
3
|
export interface AgentHarnessModelToolCatalogArgs {
|
|
4
4
|
readonly query?: unknown;
|
|
5
|
+
readonly toolName?: unknown;
|
|
6
|
+
readonly target?: unknown;
|
|
5
7
|
readonly includeParameters?: unknown;
|
|
6
8
|
readonly limit?: unknown;
|
|
7
9
|
}
|
|
@@ -34,3 +36,21 @@ export function listHarnessModelTools(toolRegistry: ToolRegistry, args: AgentHar
|
|
|
34
36
|
...(includeParameters ? { parameters: tool.parameters } : {}),
|
|
35
37
|
}));
|
|
36
38
|
}
|
|
39
|
+
|
|
40
|
+
export function describeHarnessModelTool(toolRegistry: ToolRegistry, args: AgentHarnessModelToolCatalogArgs): Record<string, unknown> | null {
|
|
41
|
+
const query = readString(args.toolName || args.target || args.query).toLowerCase();
|
|
42
|
+
if (!query) return null;
|
|
43
|
+
const tool = toolRegistry.getToolDefinitions()
|
|
44
|
+
.find((candidate) => candidate.name.toLowerCase() === query || candidate.name.toLowerCase().includes(query));
|
|
45
|
+
if (!tool) return null;
|
|
46
|
+
return {
|
|
47
|
+
name: tool.name,
|
|
48
|
+
description: tool.description,
|
|
49
|
+
sideEffects: tool.sideEffects ?? [],
|
|
50
|
+
concurrency: tool.concurrency ?? 'parallel',
|
|
51
|
+
supportsProgress: tool.supportsProgress ?? false,
|
|
52
|
+
supportsStreamingOutput: tool.supportsStreamingOutput ?? false,
|
|
53
|
+
parameters: tool.parameters,
|
|
54
|
+
policy: 'This is a first-class model tool definition. Use the returned JSON schema directly; mutating or external side-effect tools still require the explicit confirmation arguments defined by that tool.',
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -4,7 +4,7 @@ export const AGENT_HARNESS_MODES = [
|
|
|
4
4
|
'shortcuts', 'keybindings', 'keybinding', 'set_keybinding', 'reset_keybinding',
|
|
5
5
|
'commands', 'command', 'run_command', 'settings', 'get_setting', 'set_setting',
|
|
6
6
|
'reset_setting', 'workspace', 'workspace_categories', 'workspace_actions',
|
|
7
|
-
'workspace_action', 'run_workspace_action', 'tools', 'connected_host', 'connected_host_status',
|
|
7
|
+
'workspace_action', 'run_workspace_action', 'tools', 'tool', 'connected_host', 'connected_host_status',
|
|
8
8
|
'connected_host_capability',
|
|
9
9
|
] as const;
|
|
10
10
|
|
|
@@ -23,11 +23,11 @@ export const AGENT_HARNESS_PARAMETER_PROPERTIES = {
|
|
|
23
23
|
},
|
|
24
24
|
query: {
|
|
25
25
|
type: 'string',
|
|
26
|
-
description: 'Search text for command, setting, tool, or UI surface catalogs.',
|
|
26
|
+
description: 'Search text for command, setting, tool, or UI surface catalogs, or a slash-command lookup for mode command.',
|
|
27
27
|
},
|
|
28
28
|
command: {
|
|
29
29
|
type: 'string',
|
|
30
|
-
description: 'Full slash command string for mode run_command, for example "/settings get provider.model". In cli_command mode this may also hold a top-level CLI string such as "goodvibes-agent status --json".',
|
|
30
|
+
description: 'Full slash command string for mode command or run_command, for example "/settings get provider.model". In cli_command mode this may also hold a top-level CLI string such as "goodvibes-agent status --json".',
|
|
31
31
|
},
|
|
32
32
|
cliCommand: {
|
|
33
33
|
type: 'string',
|
|
@@ -90,12 +90,16 @@ export const AGENT_HARNESS_PARAMETER_PROPERTIES = {
|
|
|
90
90
|
},
|
|
91
91
|
target: {
|
|
92
92
|
type: 'string',
|
|
93
|
-
description: 'Optional
|
|
93
|
+
description: 'Optional lookup target, such as a model-picker target, slash command root or invocation, settings key, model tool name, or connected-host capability id.',
|
|
94
94
|
},
|
|
95
95
|
capabilityId: {
|
|
96
96
|
type: 'string',
|
|
97
97
|
description: 'Connected-host allowed or blocked capability id for mode connected_host_capability, such as agent-knowledge-read or connected-host-lifecycle.',
|
|
98
98
|
},
|
|
99
|
+
toolName: {
|
|
100
|
+
type: 'string',
|
|
101
|
+
description: 'First-class model tool name for mode tool, such as agent_harness or agent_local_registry.',
|
|
102
|
+
},
|
|
99
103
|
category: {
|
|
100
104
|
type: 'string',
|
|
101
105
|
description: 'Setting category filter such as provider, behavior, tools, ui, tts, permissions, automation, or surfaces.',
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Tool } from '@pellux/goodvibes-sdk/platform/types';
|
|
2
2
|
import type { ToolRegistry } from '@pellux/goodvibes-sdk/platform/tools';
|
|
3
|
-
import type { CommandContext, CommandRegistry
|
|
3
|
+
import type { CommandContext, CommandRegistry } from '../input/command-registry.ts';
|
|
4
4
|
import { buildAgentWorkspaceCommandEditorSubmission, isAgentWorkspaceCommandEditorKind } from '../input/agent-workspace-command-editor.ts';
|
|
5
5
|
import { createAgentWorkspaceEditor } from '../input/agent-workspace-activation.ts';
|
|
6
6
|
import { AGENT_WORKSPACE_CATEGORIES } from '../input/agent-workspace-categories.ts';
|
|
@@ -18,17 +18,17 @@ import type {
|
|
|
18
18
|
} from '../input/agent-workspace-types.ts';
|
|
19
19
|
import { parseSlashCommand } from '../input/slash-command-parser.ts';
|
|
20
20
|
import { blockedHarnessCliCommandTokens, describeHarnessCliCommand, listHarnessCliCommands, totalHarnessCliCommands } from './agent-harness-cli-metadata.ts';
|
|
21
|
+
import { describeHarnessCommand, listHarnessCommands } from './agent-harness-command-catalog.ts';
|
|
21
22
|
import { describeHarnessKeybinding, listHarnessKeybindings, listHarnessShortcuts, resetHarnessKeybinding, setHarnessKeybinding, totalHarnessKeybindings, totalHarnessShortcuts } from './agent-harness-keybinding-metadata.ts';
|
|
22
23
|
import { describeHarnessPanel, listHarnessPanels, openHarnessPanel, totalHarnessPanels } from './agent-harness-panel-metadata.ts';
|
|
23
24
|
import { connectedHostStatusSummary } from './agent-harness-connected-host-status.ts';
|
|
24
25
|
import { describeLocalWorkspaceModelExecution, runLocalWorkspaceAction, runLocalWorkspaceEditorAction } from './agent-harness-local-operations.ts';
|
|
25
|
-
import { listHarnessModelTools } from './agent-harness-model-tool-catalog.ts';
|
|
26
|
+
import { describeHarnessModelTool, listHarnessModelTools } from './agent-harness-model-tool-catalog.ts';
|
|
26
27
|
import { AGENT_HARNESS_MODES, AGENT_HARNESS_PARAMETER_PROPERTIES } from './agent-harness-tool-schema.ts';
|
|
27
28
|
import { describeHarnessUiSurface, listHarnessUiSurfaces, openHarnessUiSurface, totalHarnessUiSurfaces } from './agent-harness-ui-surface-metadata.ts';
|
|
28
29
|
import {
|
|
29
30
|
connectedHostSummary,
|
|
30
31
|
describeConnectedHostCapability,
|
|
31
|
-
describeCommandPolicy,
|
|
32
32
|
settingsPolicySummary,
|
|
33
33
|
} from './agent-harness-metadata.ts';
|
|
34
34
|
import {
|
|
@@ -60,6 +60,7 @@ interface AgentHarnessToolArgs {
|
|
|
60
60
|
readonly value?: unknown;
|
|
61
61
|
readonly target?: unknown;
|
|
62
62
|
readonly capabilityId?: unknown;
|
|
63
|
+
readonly toolName?: unknown;
|
|
63
64
|
readonly category?: unknown;
|
|
64
65
|
readonly prefix?: unknown;
|
|
65
66
|
readonly includeHidden?: unknown;
|
|
@@ -114,30 +115,6 @@ function output(value: unknown): { readonly success: true; readonly output: stri
|
|
|
114
115
|
|
|
115
116
|
function error(message: string): { readonly success: false; readonly error: string } { return { success: false, error: message }; }
|
|
116
117
|
|
|
117
|
-
function commandMatches(command: SlashCommand, query: string): boolean {
|
|
118
|
-
if (!query) return true;
|
|
119
|
-
const haystack = [
|
|
120
|
-
command.name,
|
|
121
|
-
...(command.aliases ?? []),
|
|
122
|
-
command.description,
|
|
123
|
-
command.usage ?? '',
|
|
124
|
-
command.argsHint ?? '',
|
|
125
|
-
].join('\n').toLowerCase();
|
|
126
|
-
return haystack.includes(query.toLowerCase());
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function describeCommand(command: SlashCommand): Record<string, unknown> {
|
|
130
|
-
return {
|
|
131
|
-
name: command.name,
|
|
132
|
-
slash: `/${command.name}`,
|
|
133
|
-
aliases: command.aliases ?? [],
|
|
134
|
-
description: command.description,
|
|
135
|
-
usage: command.usage ?? '',
|
|
136
|
-
argsHint: command.argsHint ?? command.usage ?? '',
|
|
137
|
-
policy: describeCommandPolicy(command.name),
|
|
138
|
-
};
|
|
139
|
-
}
|
|
140
|
-
|
|
141
118
|
function allWorkspaceActions(): ReadonlyArray<{
|
|
142
119
|
readonly category: AgentWorkspaceCategory;
|
|
143
120
|
readonly action: AgentWorkspaceAction;
|
|
@@ -275,16 +252,6 @@ function findWorkspaceAction(args: AgentHarnessToolArgs): { readonly category: A
|
|
|
275
252
|
}) ?? null;
|
|
276
253
|
}
|
|
277
254
|
|
|
278
|
-
function listCommands(commandRegistry: CommandRegistry, args: AgentHarnessToolArgs): readonly Record<string, unknown>[] {
|
|
279
|
-
const query = readString(args.query);
|
|
280
|
-
const limit = readLimit(args.limit, 200);
|
|
281
|
-
return commandRegistry.list()
|
|
282
|
-
.filter((command) => commandMatches(command, query))
|
|
283
|
-
.sort((a, b) => a.name.localeCompare(b.name))
|
|
284
|
-
.slice(0, limit)
|
|
285
|
-
.map(describeCommand);
|
|
286
|
-
}
|
|
287
|
-
|
|
288
255
|
function requireConfirmedAction(args: AgentHarnessToolArgs, action: string): string | null {
|
|
289
256
|
const explicitUserRequest = readString(args.explicitUserRequest);
|
|
290
257
|
if (!explicitUserRequest) return `${action} requires explicitUserRequest with the user's exact request or a short faithful summary.`;
|
|
@@ -515,7 +482,7 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
515
482
|
name: 'agent_harness',
|
|
516
483
|
description: [
|
|
517
484
|
'Discover and operate the GoodVibes Agent harness from the main conversation.',
|
|
518
|
-
'Use this tool to inspect Agent workspace actions, built-in panels, top-level CLI mirrors, UI surfaces, keybindings, slash commands with policy metadata, model tools, connected-host capabilities or one connected-host capability detail, and Agent settings, or to invoke a workspace action/command through the same in-process command registry the user uses in the TUI.',
|
|
485
|
+
'Use this tool to inspect Agent workspace actions, built-in panels, top-level CLI mirrors, UI surfaces, keybindings, slash commands with policy metadata, model tools or one model tool schema, connected-host capabilities or one connected-host capability detail, and Agent settings, or to invoke a workspace action/command through the same in-process command registry the user uses in the TUI.',
|
|
519
486
|
'Discovery modes are read-only. Setting/keybinding writes, resets, UI routing, slash command invocation, and workspace action invocation require confirm:true plus explicitUserRequest.',
|
|
520
487
|
'This tool preserves Agent product boundaries: connected-host lifecycle and listener posture stay externally owned, connected-host mode reports allowed and blocked route families, and secret-backed settings store raw values through the secret manager while config receives only a secret reference.',
|
|
521
488
|
].join(' '),
|
|
@@ -550,10 +517,10 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
550
517
|
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.',
|
|
551
518
|
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.',
|
|
552
519
|
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.',
|
|
553
|
-
slashCommands: 'Use mode:"commands" and mode:"command" to inspect; use mode:"run_command" with confirm:true plus explicitUserRequest to execute.',
|
|
520
|
+
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.',
|
|
554
521
|
workspace: 'Use mode:"workspace_actions" to list and mode:"workspace_action" for editor schemas; set includeParameters:true on workspace_actions to inline editor schemas.',
|
|
555
522
|
settings: 'Use mode:"settings", mode:"get_setting", mode:"set_setting", and mode:"reset_setting".',
|
|
556
|
-
tools: 'Use mode:"tools"
|
|
523
|
+
tools: 'Use mode:"tools" to list first-class model tools, or mode:"tool" with toolName, target, or query to inspect one schema.',
|
|
557
524
|
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.',
|
|
558
525
|
connectedHostStatus: 'Use mode:"connected_host_status" for live read-only host reachability, SDK compatibility, token posture, and Agent Knowledge route readiness.',
|
|
559
526
|
},
|
|
@@ -622,13 +589,15 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
622
589
|
return output(resetHarnessKeybinding(deps.commandContext, args));
|
|
623
590
|
}
|
|
624
591
|
if (args.mode === 'commands') {
|
|
625
|
-
const commands =
|
|
592
|
+
const commands = listHarnessCommands(deps.commandRegistry, args);
|
|
626
593
|
return output({ commands, returned: commands.length, total: deps.commandRegistry.list().length });
|
|
627
594
|
}
|
|
628
595
|
if (args.mode === 'command') {
|
|
629
|
-
const
|
|
630
|
-
const
|
|
631
|
-
return
|
|
596
|
+
const detail = describeHarnessCommand(deps.commandRegistry, args);
|
|
597
|
+
const query = readString(args.command || args.commandName || args.target || args.query);
|
|
598
|
+
return detail
|
|
599
|
+
? output(detail)
|
|
600
|
+
: error(`Unknown slash command ${query || '<missing>'}. Use mode:"commands" to inspect available commands.`);
|
|
632
601
|
}
|
|
633
602
|
if (args.mode === 'run_command') return runCommand(deps, args);
|
|
634
603
|
if (args.mode === 'settings') {
|
|
@@ -692,6 +661,13 @@ export function createAgentHarnessTool(deps: AgentHarnessToolDeps): Tool {
|
|
|
692
661
|
const tools = listHarnessModelTools(deps.toolRegistry, args);
|
|
693
662
|
return output({ tools, returned: tools.length, total: deps.toolRegistry.getToolDefinitions().length });
|
|
694
663
|
}
|
|
664
|
+
if (args.mode === 'tool') {
|
|
665
|
+
const query = readString(args.toolName || args.target || args.query);
|
|
666
|
+
const tool = describeHarnessModelTool(deps.toolRegistry, args);
|
|
667
|
+
return tool
|
|
668
|
+
? output(tool)
|
|
669
|
+
: error(`Unknown model tool ${query || '<missing>'}. Use mode:"tools" to inspect available model tools.`);
|
|
670
|
+
}
|
|
695
671
|
if (args.mode === 'connected_host') return output(connectedHostSummary(deps.commandContext, deps.toolRegistry));
|
|
696
672
|
if (args.mode === 'connected_host_capability') {
|
|
697
673
|
const query = readString(args.capabilityId || args.target || args.query);
|
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.15';
|
|
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 {
|