agentradar-cli 0.2.7 → 0.2.8

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/dist/index.js CHANGED
@@ -89,7 +89,7 @@ async function main() {
89
89
  const call = args[0] === "call";
90
90
  const parsed = parseCallArgs(args.slice(call ? 1 : 2));
91
91
  if (!parsed || (!call && parsed.flags.length)) {
92
- console.error(call ? "Usage: agentradar call <runner-id> <tool> [--<argument> <value> ...] [--args '<json>']" : "Usage: agentradar tool run <runner-id> <tool-key> [--args '<json>']");
92
+ console.error(call ? "Usage: agentradar run <runner-id> <tool> [--<argument> <value> ...] [--args '<json>'] | agentradar run <runner-id> [<tool>] --help" : "Usage: agentradar tool run <runner-id> <tool-key> [--args '<json>']");
93
93
  process.exitCode = 1;
94
94
  return;
95
95
  }
package/dist/tool-run.js CHANGED
@@ -21,6 +21,8 @@ export async function runServiceToolOverCli(runnerId, toolKey, argumentsJson, de
21
21
  }
22
22
  /** `agentradar call <runner-id> <tool> [--<argument> <value> ...] [--args '<json>']`: any AWP tool from a shell, so a just-joined agent works before its harness reloads MCP tools. */
23
23
  export async function callToolOverCli(runnerId, tool, argumentsJson, deps = {}, flags = []) {
24
+ if (flags.some(([flag]) => flag === "help"))
25
+ return await describeTools(runnerId, tool, deps);
24
26
  const parameters = argumentsJson === undefined ? {} : parseArgumentsObject(argumentsJson, deps.logError ?? console.error);
25
27
  if (!parameters)
26
28
  return 1;
@@ -65,6 +67,10 @@ export function parseCallArgs(rest) {
65
67
  positional.push(arg);
66
68
  continue;
67
69
  }
70
+ if (arg === "--help") {
71
+ flags.push(["help", ""]);
72
+ continue;
73
+ }
68
74
  const value = rest[++i];
69
75
  if (value === undefined)
70
76
  return null;
@@ -73,7 +79,37 @@ export function parseCallArgs(rest) {
73
79
  else
74
80
  flags.push([arg.slice(2), value]);
75
81
  }
76
- return positional.length === 2 ? { runnerId: positional[0], tool: positional[1], json, flags } : null;
82
+ const help = flags.some(([flag]) => flag === "help");
83
+ return positional.length === 2 || (help && positional.length === 1)
84
+ ? { runnerId: positional[0], tool: positional[1] ?? "", json, flags } : null;
85
+ }
86
+ async function listedTools(runnerId, deps) {
87
+ const listed = await awpRequest(runnerId, "tools/list", {}, deps);
88
+ return listed ? listed.result?.tools ?? [] : null;
89
+ }
90
+ // An agent that guessed a tool name from memory needs the real list, or it goes looking with commands
91
+ // its harness has not allowed and the session stalls on a permission prompt.
92
+ const unknownTool = (runnerId, tool, tools) => `${tool} is not a tool on this server. Its tools: ${tools.map((entry) => entry.name).join(" ")}. `
93
+ + `\`agentradar run ${runnerId} <tool> --help\` shows a tool's arguments.`;
94
+ /** `agentradar run <runner-id> [<tool>] --help`: the server's own tool list or one tool's arguments. */
95
+ async function describeTools(runnerId, tool, deps) {
96
+ const tools = await listedTools(runnerId, deps);
97
+ if (!tools)
98
+ return 1;
99
+ const log = deps.log ?? console.log;
100
+ if (!tool) {
101
+ log(`Tools: ${tools.map((entry) => entry.name).join(" ")}. \`agentradar run ${runnerId} <tool> --help\` shows a tool's arguments.`);
102
+ return 0;
103
+ }
104
+ const entry = tools.find((candidate) => candidate.name === tool);
105
+ if (!entry) {
106
+ (deps.logError ?? console.error)(unknownTool(runnerId, tool, tools));
107
+ return 1;
108
+ }
109
+ const required = entry.inputSchema?.required ?? [];
110
+ const names = Object.keys(entry.inputSchema?.properties ?? {}).map((name) => `--${name}${required.includes(name) ? " (required)" : ""}`);
111
+ log(`${tool}: ${entry.description ?? ""}\nArguments: ${names.join(" ") || "none"}`);
112
+ return 0;
77
113
  }
78
114
  /**
79
115
  * `--text "hi" --conversation-id X` as the tool's own arguments, typed by the inputSchema the server
@@ -81,10 +117,15 @@ export function parseCallArgs(rest) {
81
117
  */
82
118
  async function flagArguments(runnerId, tool, flags, deps) {
83
119
  const logError = deps.logError ?? console.error;
84
- const listed = await awpRequest(runnerId, "tools/list", {}, deps);
85
- if (!listed)
120
+ const tools = await listedTools(runnerId, deps);
121
+ if (!tools)
122
+ return null;
123
+ const entry = tools.find((candidate) => candidate.name === tool);
124
+ if (!entry) {
125
+ logError(unknownTool(runnerId, tool, tools));
86
126
  return null;
87
- const schema = listed.result?.tools?.find((entry) => entry.name === tool)?.inputSchema?.properties ?? {};
127
+ }
128
+ const schema = entry.inputSchema?.properties ?? {};
88
129
  const out = {};
89
130
  const camel = (flag) => flag.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase());
90
131
  for (let [flag, value] of flags) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentradar-cli",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "engines": {
5
5
  "node": ">=20"
6
6
  },