@aiaiai-pt/martha-cli 0.3.0 → 0.4.0

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.
Files changed (2) hide show
  1. package/dist/index.js +123 -32
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1019,7 +1019,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
1019
1019
  this._exitCallback = (err) => {
1020
1020
  if (err.code !== "commander.executeSubCommandAsync") {
1021
1021
  throw err;
1022
- } else {}
1022
+ }
1023
1023
  };
1024
1024
  }
1025
1025
  return this;
@@ -10830,7 +10830,7 @@ function registerDefinitionCommands(program2, config) {
10830
10830
  function isJson() {
10831
10831
  return !!program2.opts().json;
10832
10832
  }
10833
- const listCmd = cmd.command("list").description(`List ${config.typeNamePlural}`).option("--inactive", "Include inactive items").option("--limit <n>", "Max results", "50");
10833
+ const listCmd = cmd.command("list").description(`List ${config.typeNamePlural}`).option("--inactive", "Include inactive items").option("--limit <n>", "Max results per page", "50").option("--search <term>", "Case-insensitive substring filter on name (server-side)").option("--all", "Auto-paginate until every matching item is fetched (server caps at 500/page)");
10834
10834
  if (config.extraListOptions) {
10835
10835
  config.extraListOptions(listCmd);
10836
10836
  }
@@ -10840,17 +10840,65 @@ function registerDefinitionCommands(program2, config) {
10840
10840
  if (isNaN(limitN) || limitN < 1) {
10841
10841
  throw new CLIError("--limit must be a positive integer", 4 /* Validation */);
10842
10842
  }
10843
- const params = {
10844
- limit: String(limitN),
10845
- skip: "0"
10846
- };
10843
+ const baseParams = {};
10847
10844
  if (!opts.inactive)
10848
- params.active_only = "true";
10845
+ baseParams.active_only = "true";
10846
+ if (opts.search)
10847
+ baseParams.name_contains = String(opts.search);
10849
10848
  if (config.buildListParams) {
10850
- Object.assign(params, config.buildListParams(opts));
10849
+ Object.assign(baseParams, config.buildListParams(opts));
10850
+ }
10851
+ let items;
10852
+ let total;
10853
+ if (opts.all) {
10854
+ const pageSize = 500;
10855
+ items = [];
10856
+ let skip = 0;
10857
+ while (true) {
10858
+ const params = {
10859
+ ...baseParams,
10860
+ limit: String(pageSize),
10861
+ skip: String(skip)
10862
+ };
10863
+ const res = await ctx.api.getRaw(config.apiPath, { params });
10864
+ if (!res.ok) {
10865
+ throw new CLIError(`List ${config.typeNamePlural} failed: HTTP ${res.status}`, 1 /* Error */);
10866
+ }
10867
+ const headerTotal = res.headers.get("x-total-count");
10868
+ if (headerTotal !== null && total === undefined) {
10869
+ total = Number(headerTotal);
10870
+ }
10871
+ const body = await res.json();
10872
+ const pageItems = config.extractList(body);
10873
+ items.push(...pageItems);
10874
+ if (pageItems.length < pageSize)
10875
+ break;
10876
+ if (total !== undefined && items.length >= total)
10877
+ break;
10878
+ skip += pageSize;
10879
+ if (skip > 50000) {
10880
+ throw new CLIError(`Aborted --all after fetching ${items.length} ${config.typeNamePlural}; suspected pagination bug`, 1 /* Error */);
10881
+ }
10882
+ }
10883
+ } else {
10884
+ const params = {
10885
+ ...baseParams,
10886
+ limit: String(limitN),
10887
+ skip: "0"
10888
+ };
10889
+ const res = await ctx.api.getRaw(config.apiPath, { params });
10890
+ if (!res.ok) {
10891
+ throw new CLIError(`List ${config.typeNamePlural} failed: HTTP ${res.status}`, 1 /* Error */);
10892
+ }
10893
+ const headerTotal = res.headers.get("x-total-count");
10894
+ if (headerTotal !== null)
10895
+ total = Number(headerTotal);
10896
+ const data = await res.json();
10897
+ items = config.extractList(data);
10898
+ const bodyTotal = config.extractTotal?.(data);
10899
+ if (bodyTotal !== undefined)
10900
+ total = bodyTotal;
10851
10901
  }
10852
- const data = await ctx.api.get(config.apiPath, { params });
10853
- const items = config.extractList(data);
10854
10902
  if (isJson()) {
10855
10903
  console.log(JSON.stringify(items, null, 2));
10856
10904
  return;
@@ -10862,10 +10910,10 @@ function registerDefinitionCommands(program2, config) {
10862
10910
  for (const item of items) {
10863
10911
  console.log(config.listColumns.map((col, i) => col.accessor(item).padEnd(widths[i])).join(" "));
10864
10912
  }
10865
- const total = config.extractTotal?.(data);
10866
10913
  if (total !== undefined && total > items.length) {
10914
+ const hint = opts.search ? `(narrow with --search or use --all)` : `(use --search <term> or --all to load everything)`;
10867
10915
  console.log(source_default.dim(`
10868
- ${items.length} of ${total} ${config.typeNamePlural} (use --limit ${total} to see all)`));
10916
+ ${items.length} of ${total} ${config.typeNamePlural} ${hint}`));
10869
10917
  } else {
10870
10918
  console.log(source_default.dim(`
10871
10919
  ${items.length} ${config.typeNamePlural}`));
@@ -11456,16 +11504,46 @@ Error: ${err instanceof Error ? err.message : String(err)}
11456
11504
  `);
11457
11505
  }
11458
11506
  async function runOneShot(ctx, sessionId, message, isJson, clientId, showTools, timeoutMs) {
11507
+ const toolCalls = [];
11508
+ function recordToolStatus(data) {
11509
+ try {
11510
+ const tools = JSON.parse(data);
11511
+ for (const t of tools) {
11512
+ const name = t.tool_name ?? t.tool_label;
11513
+ if (!name)
11514
+ continue;
11515
+ toolCalls.push({ name, status: t.status });
11516
+ }
11517
+ } catch {}
11518
+ }
11519
+ function recordToolCall(data) {
11520
+ try {
11521
+ const parsed = JSON.parse(data);
11522
+ if (parsed.name)
11523
+ toolCalls.push({ name: parsed.name });
11524
+ } catch {}
11525
+ }
11459
11526
  const { response } = await sendMessage(ctx, sessionId, message, {
11460
11527
  clientId,
11461
11528
  timeoutMs,
11462
- onToolCall: showTools ? (data) => process.stderr.write(formatToolCall(data)) : undefined,
11529
+ onToolStatus: isJson ? recordToolStatus : showTools ? (data) => {
11530
+ recordToolStatus(data);
11531
+ process.stderr.write(formatToolStatus(data));
11532
+ } : undefined,
11533
+ onToolCall: isJson ? recordToolCall : showTools ? (data) => {
11534
+ recordToolCall(data);
11535
+ process.stderr.write(formatToolCall(data));
11536
+ } : undefined,
11463
11537
  onToolResult: showTools ? (data) => process.stderr.write(formatToolResult(data)) : undefined,
11464
11538
  onClear: showTools ? () => process.stderr.write(source_default.dim(` --- tool iteration ---
11465
11539
  `)) : undefined
11466
11540
  });
11467
11541
  if (isJson) {
11468
- console.log(JSON.stringify({ session_id: sessionId, response }));
11542
+ console.log(JSON.stringify({
11543
+ session_id: sessionId,
11544
+ response,
11545
+ tool_calls: toolCalls
11546
+ }));
11469
11547
  } else {
11470
11548
  console.log(response);
11471
11549
  }
@@ -15729,23 +15807,30 @@ async function resolveClientId(ctx, nameOrId) {
15729
15807
  async function resolveDefinitionId(ctx, type, name) {
15730
15808
  if (type === "agent")
15731
15809
  return name;
15732
- const path5 = type === "function" ? `${DEFS_API}/functions` : `${DEFS_API}/workflows`;
15733
- const data = await ctx.api.get(path5, {
15734
- params: { limit: "500", skip: "0" }
15735
- });
15736
- let items;
15737
- if (Array.isArray(data)) {
15738
- items = data;
15739
- } else if (data && typeof data === "object" && "items" in data) {
15740
- items = data.items;
15741
- } else {
15742
- throw new CLIError(`Unexpected response shape from ${type}s list`, 1 /* Error */);
15743
- }
15744
- const match = items.find((d) => String(d.name ?? "").toLowerCase() === name.toLowerCase());
15745
- if (!match) {
15746
- throw new CLIError(`${type} not found: '${name}'`, 3 /* NotFound */, `Run \`martha ${type}s list\` to see available ${type}s.`);
15810
+ const listPath = type === "function" ? `${DEFS_API}/functions` : `${DEFS_API}/workflows`;
15811
+ const exactPath = `${listPath}/${encodeURIComponent(name)}`;
15812
+ try {
15813
+ const exact = await ctx.api.get(exactPath);
15814
+ if (exact && typeof exact === "object" && "id" in exact) {
15815
+ return String(exact.id);
15816
+ }
15817
+ } catch (e) {
15818
+ const code = e?.status ?? e?.statusCode;
15819
+ if (code !== 404)
15820
+ throw e;
15747
15821
  }
15748
- return String(match.id);
15822
+ let suggestion = "";
15823
+ try {
15824
+ const fuzzy = await ctx.api.get(listPath, {
15825
+ params: { name_contains: name, limit: "5", skip: "0" }
15826
+ });
15827
+ const items = Array.isArray(fuzzy) ? fuzzy : fuzzy && typeof fuzzy === "object" && ("items" in fuzzy) ? fuzzy.items : [];
15828
+ const names = items.map((d) => String(d.name ?? "")).filter((n) => n.length > 0).slice(0, 5);
15829
+ if (names.length > 0) {
15830
+ suggestion = `Did you mean: ${names.join(", ")}?`;
15831
+ }
15832
+ } catch {}
15833
+ throw new CLIError(`${type} not found: '${name}'`, 3 /* NotFound */, suggestion || `Run \`martha ${type}s list --search ${name}\` to find it.`);
15749
15834
  }
15750
15835
  function formatDate(val) {
15751
15836
  if (!val)
@@ -16231,7 +16316,11 @@ ${clients.length} client(s)`));
16231
16316
  const result = await ctx.api.get(`${API}/${clientId}`);
16232
16317
  const assetBaseUrl = getEmbedAssetBaseUrl(ctx.profile.api_url);
16233
16318
  if (isJson()) {
16234
- console.log(JSON.stringify({ ...result, asset_base_url: assetBaseUrl, embed_credentials: credentials }, null, 2));
16319
+ console.log(JSON.stringify({
16320
+ ...result,
16321
+ asset_base_url: assetBaseUrl,
16322
+ embed_credentials: credentials
16323
+ }, null, 2));
16235
16324
  return;
16236
16325
  }
16237
16326
  printEmbedSummary(result, assetBaseUrl);
@@ -16331,7 +16420,9 @@ ${clients.length} client(s)`));
16331
16420
  const manifestPath = `/api/embed/manifest/${encodeURIComponent(key)}`;
16332
16421
  const manifest = await ctx.api.get(manifestPath, { headers: { Origin: origin } });
16333
16422
  const deniedUrl = `${deriveMarthaWebOrigin(ctx.profile.api_url)}${manifestPath}`;
16334
- const denied = await fetch(deniedUrl, { headers: { Origin: deniedOrigin } });
16423
+ const denied = await fetch(deniedUrl, {
16424
+ headers: { Origin: deniedOrigin }
16425
+ });
16335
16426
  if (denied.status !== 403) {
16336
16427
  throw new CLIError(`Denied-origin manifest check expected 403, got ${denied.status}`, 1 /* Error */);
16337
16428
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aiaiai-pt/martha-cli",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Terminal-first client for the Martha AI platform",
5
5
  "homepage": "https://docs.martha.nomadriver.co",
6
6
  "repository": {