@lambdacurry/arbor 0.13.8 → 0.13.9

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/arbor.js +70 -19
  2. package/package.json +1 -1
package/dist/arbor.js CHANGED
@@ -18889,7 +18889,7 @@ var ACTION_DEFINITIONS = [
18889
18889
  path: exports_external.string().min(1).max(2048).describe("relative App path beginning with /; may include a query string"),
18890
18890
  method: exports_external.enum(["GET", "HEAD"]).optional().describe("safe read method; default GET")
18891
18891
  },
18892
- surfaces: ["mcp"],
18892
+ surfaces: ["mcp", "cli"],
18893
18893
  toolset: "apps",
18894
18894
  run: forward("app.fetch")
18895
18895
  },
@@ -18901,11 +18901,11 @@ var ACTION_DEFINITIONS = [
18901
18901
  appId: exports_external.string().describe("target App, app_…"),
18902
18902
  path: exports_external.string().min(1).max(2048).describe("relative App path beginning with /; may include a query string"),
18903
18903
  method: exports_external.enum(["POST", "PUT", "PATCH", "DELETE"]).describe("mutating HTTP method"),
18904
- json: exports_external.json().optional().describe("JSON request value; mutually exclusive with body and sets application/json"),
18904
+ json: exports_external.json().optional().describe("JSON request value; mutually exclusive with body and sets application/json. On the CLI, pass serialized JSON after the command as --json '<value>'"),
18905
18905
  body: exports_external.string().optional().describe("UTF-8 request body; mutually exclusive with json"),
18906
18906
  contentType: exports_external.string().max(160).optional().describe("body media type; allowed only with body, default text/plain; charset=utf-8")
18907
18907
  },
18908
- surfaces: ["mcp"],
18908
+ surfaces: ["mcp", "cli"],
18909
18909
  toolset: "apps",
18910
18910
  run: forward("app.request")
18911
18911
  },
@@ -19501,6 +19501,17 @@ function commandWords(action) {
19501
19501
  var CLI_ACTIONS = ACTIONS.filter((a) => a.surfaces.includes("cli") || a.surfaces.includes("computer-cli"));
19502
19502
  var BY_COMMAND = new Map(CLI_ACTIONS.map((a) => [commandWords(a), a]));
19503
19503
  var MAX_WORDS = Math.max(1, ...CLI_ACTIONS.map((a) => commandWords(a).split(" ").length));
19504
+ var POSITIONAL_FIELDS = {
19505
+ app_fetch: ["appId", "path"],
19506
+ app_request: ["appId", "path"]
19507
+ };
19508
+ function positionalSpecs(action) {
19509
+ const fields = POSITIONAL_FIELDS[action.name];
19510
+ if (!fields)
19511
+ return [];
19512
+ const specs = flagsForSchema(action.inputSchema);
19513
+ return fields.map((field) => specs.find((spec) => spec.field === field));
19514
+ }
19504
19515
  var KNOWN_MISREACHES = [
19505
19516
  { tried: "thread list", use: "tree --depth threads", why: "threads are listed by the tree" },
19506
19517
  { tried: "threads", use: "tree --depth threads", why: "threads are listed by the tree" },
@@ -19559,12 +19570,15 @@ function toolNameAlias(action) {
19559
19570
  return action.name.includes("_") ? action.name : "";
19560
19571
  }
19561
19572
  function helpLine(action) {
19562
- const flags = flagsForSchema(action.inputSchema).map((f) => {
19573
+ const positionals = positionalSpecs(action);
19574
+ const positionalFlags = new Set(positionals.map((spec) => spec.flag));
19575
+ const args = positionals.map((spec) => ` <${spec.field}>`).join("");
19576
+ const flags = flagsForSchema(action.inputSchema).filter((spec) => !positionalFlags.has(spec.flag)).map((f) => {
19563
19577
  const token = f.kind === "boolean" ? `--${f.flag}` : `--${f.flag} <>`;
19564
19578
  return f.required ? token : `[${token}]`;
19565
19579
  }).join(" ");
19566
19580
  const alias2 = toolNameAlias(action);
19567
- const head = ` ${commandWords(action)}${alias2 ? ` (${alias2})` : ""}${flags ? ` ${flags}` : ""}`;
19581
+ const head = ` ${commandWords(action)}${alias2 ? ` (${alias2})` : ""}${args}${flags ? ` ${flags}` : ""}`;
19568
19582
  return `${head}
19569
19583
  ${action.description}`;
19570
19584
  }
@@ -19576,12 +19590,15 @@ function commandHelp(positionals) {
19576
19590
  return;
19577
19591
  const { action } = match;
19578
19592
  const specs = flagsForSchema(action.inputSchema);
19579
- const primary = primaryPositionalField(action.inputSchema);
19580
- const usageFlags = specs.map((f) => {
19593
+ const explicitPositionals = positionalSpecs(action);
19594
+ const primary = explicitPositionals.length === 0 ? primaryPositionalField(action.inputSchema) : undefined;
19595
+ const positionalFlags = new Set(explicitPositionals.map((spec) => spec.flag));
19596
+ const usageFlags = specs.filter((spec) => !positionalFlags.has(spec.flag)).map((f) => {
19581
19597
  const token = f.kind === "boolean" ? `--${f.flag}` : `--${f.flag} <${f.kind}>`;
19582
19598
  return f.required ? token : `[${token}]`;
19583
19599
  }).join(" ");
19584
- const usage = `Usage: arbor ${commandWords(action)}${primary ? ` [<${primary.field}>]` : ""}${usageFlags ? ` ${usageFlags}` : ""}`;
19600
+ const explicitArgs = explicitPositionals.map((spec) => ` <${spec.field}>`).join("");
19601
+ const usage = `Usage: arbor ${commandWords(action)}${explicitArgs}${primary ? ` [<${primary.field}>]` : ""}${usageFlags ? ` ${usageFlags}` : ""}`;
19585
19602
  const lines = specs.map((f) => {
19586
19603
  const req = f.required ? "required" : "optional";
19587
19604
  const fileNote = f.kind === "string" ? ` (or --${f.flag}-file <path|->)` : "";
@@ -19594,6 +19611,9 @@ function commandHelp(positionals) {
19594
19611
  const primaryNote = primary ? `
19595
19612
 
19596
19613
  A single bare argument fills --${primary.flag} (e.g. \`arbor ${commandWords(action)} <${primary.field}>\`).` : "";
19614
+ const explicitNote = explicitPositionals.length > 0 ? `
19615
+
19616
+ Bare arguments fill ${explicitPositionals.map((spec) => `--${spec.flag}`).join(" then ")}; the equivalent flags remain accepted.` : "";
19597
19617
  const alias2 = toolNameAlias(action);
19598
19618
  const aliasNote = alias2 ? `
19599
19619
 
@@ -19604,7 +19624,7 @@ Alias: \`arbor ${alias2}\` (the tool-name form) resolves to this same command.`
19604
19624
  ${usage}
19605
19625
 
19606
19626
  ${lines.join(`
19607
- `)}${primaryNote}${aliasNote}
19627
+ `)}${primaryNote}${explicitNote}${aliasNote}
19608
19628
  `;
19609
19629
  }
19610
19630
  function commandCatalog() {
@@ -19630,17 +19650,21 @@ async function runObjectVerb(positionals, flags, ctx) {
19630
19650
  const { action, words } = match;
19631
19651
  const extras = positionals.slice(words);
19632
19652
  if (extras.length > 0) {
19633
- const primary = primaryPositionalField(action.inputSchema);
19634
- if (!primary) {
19653
+ const explicitPositionals = positionalSpecs(action);
19654
+ const positionalTargets = explicitPositionals.length > 0 ? explicitPositionals : [primaryPositionalField(action.inputSchema)].filter((spec) => spec !== undefined);
19655
+ if (positionalTargets.length === 0) {
19635
19656
  throw new UsageError(`unexpected argument: ${extras[0]} (\`${commandWords(action)}\` takes no positional — use flags)`);
19636
19657
  }
19637
- if (extras.length > 1) {
19638
- throw new UsageError(`too many arguments: \`${commandWords(action)}\` takes one positional (--${primary.flag}); pass the rest as flags`);
19658
+ if (extras.length > positionalTargets.length) {
19659
+ throw new UsageError(`too many arguments: \`${commandWords(action)}\` takes ${positionalTargets.length === 1 ? "one positional" : `${positionalTargets.length} positionals`}; pass the rest as flags`);
19639
19660
  }
19640
- if (flags[primary.flag] !== undefined || flags[`${primary.flag}-file`] !== undefined) {
19641
- throw new UsageError(`pass --${primary.flag} either as a flag or as the positional argument, not both`);
19661
+ for (const [index2, value] of extras.entries()) {
19662
+ const target = positionalTargets[index2];
19663
+ if (flags[target.flag] !== undefined || flags[`${target.flag}-file`] !== undefined) {
19664
+ throw new UsageError(`pass --${target.flag} either as a flag or as the positional argument, not both`);
19665
+ }
19666
+ flags[target.flag] = value;
19642
19667
  }
19643
- flags[primary.flag] = extras[0];
19644
19668
  }
19645
19669
  const accepted = acceptedFlags(action.inputSchema);
19646
19670
  const unknown2 = Object.keys(flags).filter((f) => !accepted.has(f) && !RESERVED_FLAGS.has(f));
@@ -19648,7 +19672,27 @@ async function runObjectVerb(positionals, flags, ctx) {
19648
19672
  const hints = unknown2.map((f) => listFileHint(action, f)).filter(Boolean);
19649
19673
  throw new UsageError(`unknown flag${unknown2.length > 1 ? "s" : ""}: ${unknown2.map((f) => `--${f}`).join(", ")}${hints.length > 0 ? ` — ${hints.join("; ")}` : ""}`);
19650
19674
  }
19651
- const input = buildInput(action.inputSchema, flags, commandWords(action));
19675
+ const inputFlags = { ...flags };
19676
+ if (action.name === "app_request" && lastValue(inputFlags.json) === true) {
19677
+ delete inputFlags.json;
19678
+ }
19679
+ const input = buildInput(action.inputSchema, inputFlags, commandWords(action));
19680
+ if (action.name === "app_request" && input.json !== undefined) {
19681
+ if (input.body !== undefined) {
19682
+ throw new UsageError("--json and --body are mutually exclusive", {
19683
+ reason: "validation.invalid_value",
19684
+ field: "body"
19685
+ });
19686
+ }
19687
+ try {
19688
+ input.json = JSON.parse(String(input.json));
19689
+ } catch {
19690
+ throw new UsageError("--json expects a valid serialized JSON value", {
19691
+ reason: "validation.invalid_value",
19692
+ field: "json"
19693
+ });
19694
+ }
19695
+ }
19652
19696
  if (action.name === "agent_register") {
19653
19697
  advise(`Agent registered. Save its apiKey now — it is shown only once:
19654
19698
  `, ctx);
@@ -19761,6 +19805,11 @@ async function login(opts) {
19761
19805
  }
19762
19806
 
19763
19807
  // src/index.ts
19808
+ function resolveCommandOutput(positionals, flags, opts) {
19809
+ const actionName = matchCommand(positionals)?.action.name;
19810
+ const resolved = resolveOutput(flags, opts);
19811
+ return actionName === "app_fetch" || actionName === "app_request" ? { ...resolved, json: true, quiet: true } : resolved;
19812
+ }
19764
19813
  function setFlag(flags, key, value) {
19765
19814
  const prev = flags[key];
19766
19815
  if (prev === undefined || typeof value === "boolean" || typeof prev === "boolean") {
@@ -19777,9 +19826,11 @@ function parseArgs(argv) {
19777
19826
  if (arg.startsWith("--")) {
19778
19827
  const body = arg.slice(2);
19779
19828
  const eq = body.indexOf("=");
19829
+ const appRequestWords = positionals[0] === "app" && positionals[1] === "request" ? 2 : positionals[0] === "app_request" ? 1 : 0;
19830
+ const hasAppRequestTarget = appRequestWords > 0 && (positionals.length >= appRequestWords + 2 || flags["app-id"] !== undefined && flags.path !== undefined);
19780
19831
  if (eq !== -1) {
19781
19832
  setFlag(flags, body.slice(0, eq), body.slice(eq + 1));
19782
- } else if (!GLOBAL_BOOLEAN_FLAGS.has(body) && i + 1 < argv.length && !argv[i + 1].startsWith("--")) {
19833
+ } else if ((!GLOBAL_BOOLEAN_FLAGS.has(body) || body === "json" && hasAppRequestTarget) && i + 1 < argv.length && !argv[i + 1].startsWith("--")) {
19783
19834
  setFlag(flags, body, argv[++i]);
19784
19835
  } else {
19785
19836
  setFlag(flags, body, true);
@@ -19909,7 +19960,7 @@ async function renderHealth(ctx) {
19909
19960
  }
19910
19961
  async function main() {
19911
19962
  const { positionals, flags } = parseArgs(process.argv.slice(2));
19912
- const ctx = resolveOutput(flags);
19963
+ const ctx = resolveCommandOutput(positionals, flags);
19913
19964
  const [cmd] = positionals;
19914
19965
  try {
19915
19966
  if (flags.version !== undefined && positionals.length === 0 || cmd === "version") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lambdacurry/arbor",
3
- "version": "0.13.8",
3
+ "version": "0.13.9",
4
4
  "description": "The Arbor CLI — a shared workspace for people and agents. The human + headless-agent write path over Arbor's guarded operation surface.",
5
5
  "keywords": [
6
6
  "agents",