@withone/cli 1.56.0 → 1.57.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.
package/README.md CHANGED
@@ -24,7 +24,7 @@
24
24
  <a href="https://withone.ai/knowledge"><img src="https://img.shields.io/endpoint?url=https%3A%2F%2Fapi.withone.ai%2Fopen%2Fcount%2Ftools" alt="tools"></a>
25
25
  </p>
26
26
 
27
- One gives your AI agent authenticated access to 600+ platforms - Gmail, Slack, Shopify, HubSpot, Stripe, Notion, and everything else - through a single interface. No API keys to juggle, no OAuth flows to build, no request formats to memorize. Connect a platform once, and your agent can search for actions, read the docs, and execute API calls in seconds.
27
+ One gives your AI agent authenticated access to 750+ platforms - Gmail, Slack, Shopify, HubSpot, Stripe, Notion, and everything else - through a single interface. No API keys to juggle, no OAuth flows to build, no request formats to memorize. Connect a platform once, and your agent can search for actions, read the docs, and execute API calls in seconds.
28
28
 
29
29
  ## Install
30
30
 
@@ -250,7 +250,7 @@ Shows the connection details and asks for confirmation before deleting. Use `--f
250
250
 
251
251
  ### `one platforms`
252
252
 
253
- Browse all 600+ available platforms.
253
+ Browse all 750+ available platforms.
254
254
 
255
255
  ```bash
256
256
  one platforms # all platforms
@@ -280,6 +280,18 @@ one actions knowledge shopify 67890abcdef
280
280
 
281
281
  Always read the knowledge before executing. It tells you exactly what parameters are required, what format they need, and any platform-specific quirks.
282
282
 
283
+ In `--agent` mode the response is a **digest**: request-building sections in full (method/URL, headers, description, enforcement rules, required and optional parameters, sample request, gotchas, error handling) plus a table of contents for the rest. Response shapes, response-field tables, and worked examples — the bulk of every large doc — are loaded on demand:
284
+
285
+ ```bash
286
+ one --agent actions knowledge github <actionId> # digest + sections[] table of contents
287
+ one --agent actions knowledge github <actionId> --section "Response Fields" # one section, by heading or id
288
+ one --agent actions knowledge github <actionId> --section response,examples # several, by alias
289
+ one --agent actions knowledge github <actionId> --full # whole document
290
+ one --agent actions knowledge github <actionId> --toc # every section id, no document
291
+ ```
292
+
293
+ The JSON carries `truncated`, `sections[]` (the omitted sections: id, heading, chars), and `more` (the commands to load the rest); the markdown ends with the same notice so it is never mistaken for the complete doc. Small documents are returned whole. Section requests are served from the local cache. Human (non-agent) output always prints the full document; `--section` works there too.
294
+
283
295
  ### `one actions execute <platform> <actionId> <connectionKey>`
284
296
 
285
297
  Execute an API action on a connected platform.
@@ -354,6 +366,7 @@ Knowledge and search commands also support cache flags:
354
366
  ```bash
355
367
  one actions knowledge gmail <actionId> --no-cache # Skip cache, fetch fresh
356
368
  one actions knowledge gmail <actionId> --cache-status # Check cache status
369
+ one actions knowledge gmail <actionId> --section response # Served from the cached doc, no fetch
357
370
  one actions search gmail "send email" --no-cache # Skip cache for search
358
371
  one actions execute gmail <actionId> <key> --no-cache # Fresh action-details lookup
359
372
  ```
package/dist/index.js CHANGED
@@ -1578,6 +1578,25 @@ function startCallbackServer(expectedState) {
1578
1578
  tryListen();
1579
1579
  });
1580
1580
  }
1581
+ function wrapForNote(text5, width = noteWidth()) {
1582
+ const lines = [];
1583
+ for (const line of text5.split("\n")) {
1584
+ let rest = line;
1585
+ while (rest.length > width) {
1586
+ const space = rest.lastIndexOf(" ", width);
1587
+ const cut = space > 0 ? space : width;
1588
+ lines.push(rest.slice(0, cut));
1589
+ rest = rest.slice(cut).trimStart();
1590
+ }
1591
+ lines.push(rest);
1592
+ }
1593
+ return lines.join("\n");
1594
+ }
1595
+ function noteWidth() {
1596
+ const columns = process.stdout.columns;
1597
+ const usable = (typeof columns === "number" && columns > 0 ? columns : 80) - 8;
1598
+ return Math.max(usable, 40);
1599
+ }
1581
1600
  async function browserLogin(opts) {
1582
1601
  const state = crypto.randomUUID();
1583
1602
  const spin = createSpinner();
@@ -1598,13 +1617,17 @@ ${authUrl}
1598
1617
  `);
1599
1618
  } else {
1600
1619
  note(
1601
- `If the browser doesn't open, visit:
1602
- ${authUrl}
1620
+ wrapForNote(
1621
+ `The consent page records this on the key, so you can find the install later.
1603
1622
 
1604
- The consent page records this on the key so you can find the install later:
1605
- ${describeInstallContext(context)}`,
1606
- "Opening browser for authentication..."
1623
+ ${describeInstallContext(context)}`
1624
+ ),
1625
+ "This install"
1607
1626
  );
1627
+ console.log();
1628
+ console.log(" Opening your browser. If it doesn't open, visit:");
1629
+ console.log(authUrl);
1630
+ console.log();
1608
1631
  }
1609
1632
  try {
1610
1633
  await open2(authUrl);
@@ -1719,7 +1742,7 @@ async function loginCommand() {
1719
1742
  console.log(pc16.cyan(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
1720
1743
  console.log(pc16.cyan(" \u2502"));
1721
1744
  console.log(pc16.cyan(" \u2502 The One CLI (`one`) is now installed on this machine. It"));
1722
- console.log(pc16.cyan(" \u2502 lets you interact with 600+ third-party platforms (Gmail,"));
1745
+ console.log(pc16.cyan(" \u2502 lets you interact with 750+ third-party platforms (Gmail,"));
1723
1746
  console.log(pc16.cyan(" \u2502 Slack, Shopify, HubSpot, Stripe, GitHub, etc.) through"));
1724
1747
  console.log(pc16.cyan(" \u2502 their APIs. Whenever you need to interact with any"));
1725
1748
  console.log(pc16.cyan(" \u2502 third-party platform or external service, use the `one`"));
@@ -2311,7 +2334,7 @@ function printOnboardingPrompt() {
2311
2334
  console.log(pc4.cyan(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
2312
2335
  console.log(pc4.cyan(" \u2502"));
2313
2336
  console.log(pc4.cyan(" \u2502 The One CLI (`one`) is now installed on this machine. It"));
2314
- console.log(pc4.cyan(" \u2502 lets you interact with 600+ third-party platforms (Gmail,"));
2337
+ console.log(pc4.cyan(" \u2502 lets you interact with 750+ third-party platforms (Gmail,"));
2315
2338
  console.log(pc4.cyan(" \u2502 Slack, Shopify, HubSpot, Stripe, GitHub, etc.) through"));
2316
2339
  console.log(pc4.cyan(" \u2502 their APIs. Whenever you need to interact with any"));
2317
2340
  console.log(pc4.cyan(" \u2502 third-party platform or external service, use the `one`"));
@@ -2432,18 +2455,23 @@ ${resolutionHint}`,
2432
2455
  printOnboardingPrompt();
2433
2456
  p3.outro("Done! Paste the prompt above to your AI agent.");
2434
2457
  }
2458
+ function lime(text5) {
2459
+ if (!pc4.isColorSupported) return text5;
2460
+ const truecolor = process.env.COLORTERM === "truecolor" || process.env.COLORTERM === "24bit";
2461
+ return truecolor ? `\x1B[38;2;204;255;0m${text5}\x1B[39m` : pc4.green(text5);
2462
+ }
2435
2463
  function printBanner() {
2436
2464
  console.log();
2437
- console.log(pc4.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
2438
- console.log(pc4.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
2439
- console.log(pc4.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
2440
- console.log(pc4.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
2441
- console.log(pc4.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 "));
2442
- console.log(pc4.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 "));
2443
- console.log(pc4.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
2444
- console.log(pc4.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
2445
- console.log(pc4.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
2446
- console.log(pc4.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
2465
+ console.log(lime(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
2466
+ console.log(lime(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
2467
+ console.log(lime(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
2468
+ console.log(lime(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
2469
+ console.log(lime(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 "));
2470
+ console.log(lime(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 "));
2471
+ console.log(lime(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
2472
+ console.log(lime(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
2473
+ console.log(lime(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
2474
+ console.log(lime(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
2447
2475
  console.log();
2448
2476
  console.log(pc4.dim(" I N F R A S T R U C T U R E F O R A G E N T S"));
2449
2477
  console.log();
@@ -2475,7 +2503,7 @@ async function promptConnectIntegrations(apiKey, connParams) {
2475
2503
  label: i.label,
2476
2504
  hint: i.hint
2477
2505
  })),
2478
- { value: "more", label: "Browse all 600+ platforms" },
2506
+ { value: "more", label: "Browse all 750+ platforms" },
2479
2507
  { value: "skip", label: "Skip for now", hint: "you can always run one add later" }
2480
2508
  ];
2481
2509
  const message = first ? "Connect your first integration?" : "Connect another?";
@@ -3081,6 +3109,391 @@ async function platformsCommand(options) {
3081
3109
  // src/commands/actions.ts
3082
3110
  import * as p6 from "@clack/prompts";
3083
3111
  import pc8 from "picocolors";
3112
+
3113
+ // src/lib/knowledge-sections.ts
3114
+ var DEFAULT_WHOLE_DOC_THRESHOLD = 8e3;
3115
+ var DEFAULT_DIGEST_BUDGET = 8e3;
3116
+ var DEFAULT_SECTION_CAP = 6e3;
3117
+ var HEADING_RE = /^(#{1,6})[ \t]+(.+?)[ \t]*#*[ \t]*$/;
3118
+ var FENCE_RE = /^\s*(```|~~~)/;
3119
+ function slugify(heading) {
3120
+ return heading.toLowerCase().replace(/`/g, "").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "") || "section";
3121
+ }
3122
+ function parseSections(markdown) {
3123
+ const normalized = markdown.replace(/\r\n?/g, "\n");
3124
+ const lines = normalized.split("\n");
3125
+ const prefaceLines = [];
3126
+ const blocks = [];
3127
+ let inFence = false;
3128
+ let fenceMarker = "";
3129
+ for (const line of lines) {
3130
+ const fence = FENCE_RE.exec(line);
3131
+ if (fence) {
3132
+ if (!inFence) {
3133
+ inFence = true;
3134
+ fenceMarker = fence[1];
3135
+ } else if (fence[1] === fenceMarker) {
3136
+ inFence = false;
3137
+ }
3138
+ }
3139
+ const m = !inFence ? HEADING_RE.exec(line) : null;
3140
+ if (m) {
3141
+ blocks.push({ level: m[1].length, heading: m[2].trim(), lines: [line] });
3142
+ continue;
3143
+ }
3144
+ if (blocks.length === 0) prefaceLines.push(line);
3145
+ else blocks[blocks.length - 1].lines.push(line);
3146
+ }
3147
+ const usedIds = /* @__PURE__ */ new Set();
3148
+ const nodes = blocks.map((b) => {
3149
+ const base = slugify(b.heading);
3150
+ let id = base;
3151
+ for (let n = 2; usedIds.has(id); n++) id = `${base}-${n}`;
3152
+ usedIds.add(id);
3153
+ return {
3154
+ id,
3155
+ heading: b.heading,
3156
+ level: b.level,
3157
+ text: b.lines.join("\n"),
3158
+ chars: 0,
3159
+ tier: classifyHeading(b.heading),
3160
+ children: []
3161
+ };
3162
+ });
3163
+ const root = [];
3164
+ const stack = [];
3165
+ let title = "";
3166
+ let titleNode = null;
3167
+ for (const node of nodes) {
3168
+ while (stack.length && stack[stack.length - 1].level >= node.level) stack.pop();
3169
+ if (stack.length) stack[stack.length - 1].children.push(node);
3170
+ else root.push(node);
3171
+ stack.push(node);
3172
+ }
3173
+ if (root.length && nodes[0].level === 1 && root[0] === nodes[0]) {
3174
+ titleNode = root.shift();
3175
+ title = titleNode.heading;
3176
+ root.unshift(...titleNode.children);
3177
+ titleNode.children = [];
3178
+ }
3179
+ let preface = prefaceLines.join("\n").trim();
3180
+ if (titleNode) {
3181
+ const own = titleNode.text.split("\n").slice(1).join("\n").trim();
3182
+ if (own) preface = preface ? `${preface}
3183
+
3184
+ ${own}` : own;
3185
+ }
3186
+ const measure = (n) => {
3187
+ n.chars = n.text.length + n.children.reduce((sum, c) => sum + measure(c), 0);
3188
+ return n.chars;
3189
+ };
3190
+ root.forEach(measure);
3191
+ return { title, preface, sections: root, chars: normalized.length };
3192
+ }
3193
+ function sectionText(section) {
3194
+ const parts = [section.text, ...section.children.map(sectionText)];
3195
+ return parts.join("\n").replace(/\n+$/, "");
3196
+ }
3197
+ function flattenSections(sections) {
3198
+ const out = [];
3199
+ const walk = (list) => {
3200
+ for (const s of list) {
3201
+ out.push(s);
3202
+ walk(s.children);
3203
+ }
3204
+ };
3205
+ walk(sections);
3206
+ return out;
3207
+ }
3208
+ function canonicalHeading(heading) {
3209
+ return heading.toLowerCase().replace(/\s*\([^)]*\)\s*$/, "").replace(/[`*_]/g, "").replace(/\s+/g, " ").trim();
3210
+ }
3211
+ var ESSENTIAL_EXACT = /* @__PURE__ */ new Set([
3212
+ "prerequisites",
3213
+ "method",
3214
+ "url",
3215
+ "endpoint",
3216
+ "headers",
3217
+ "description",
3218
+ "enforcement rules",
3219
+ "valid examples",
3220
+ "invalid examples",
3221
+ "request body",
3222
+ "sample request",
3223
+ "gotchas",
3224
+ "error handling",
3225
+ "graphql operation",
3226
+ "graphql arguments",
3227
+ "request variables",
3228
+ "variables",
3229
+ "path parameters",
3230
+ "query parameters",
3231
+ "parameters",
3232
+ "arguments"
3233
+ ]);
3234
+ var ESSENTIAL_PREFIX = ["required "];
3235
+ function classifyHeading(heading) {
3236
+ const c = canonicalHeading(heading);
3237
+ if (ESSENTIAL_EXACT.has(c)) return "essential";
3238
+ if (ESSENTIAL_PREFIX.some((p10) => c.startsWith(p10))) return "essential";
3239
+ return "deferred";
3240
+ }
3241
+ function deferredPriority(heading) {
3242
+ const c = canonicalHeading(heading);
3243
+ if (c.startsWith("optional ")) return 0;
3244
+ if (c === "behavior" || c === "behaviour") return 1;
3245
+ if (c === "notes") return 2;
3246
+ if (c === "example usage" || c.startsWith("example")) return 3;
3247
+ if (c === "response fields") return 5;
3248
+ if (c === "response" || c.startsWith("success response") || c.startsWith("error response")) return 6;
3249
+ return 4;
3250
+ }
3251
+ function truncateText(text5, cap, id) {
3252
+ const cut = text5.slice(0, cap);
3253
+ const nl = cut.lastIndexOf("\n");
3254
+ const head = nl > cap * 0.5 ? cut.slice(0, nl) : cut;
3255
+ const remaining = text5.length - head.length;
3256
+ return `${head}
3257
+
3258
+ _[truncated \u2014 ${remaining.toLocaleString("en-US")} more chars. Load the full section with --section ${id}]_`;
3259
+ }
3260
+ function buildDigest(doc, opts = {}) {
3261
+ const wholeThreshold = opts.wholeDocThreshold ?? DEFAULT_WHOLE_DOC_THRESHOLD;
3262
+ const budget = opts.budget ?? DEFAULT_DIGEST_BUDGET;
3263
+ const cap = opts.sectionCap ?? DEFAULT_SECTION_CAP;
3264
+ const flat = flattenSections(doc.sections);
3265
+ const whole = () => ({
3266
+ markdown: renderWhole(doc),
3267
+ truncated: false,
3268
+ sections: flat.map((s) => summary(s, true)),
3269
+ omitted: 0,
3270
+ omittedChars: 0
3271
+ });
3272
+ if (flat.length === 0 || doc.chars <= wholeThreshold) return whole();
3273
+ const decisions = /* @__PURE__ */ new Map();
3274
+ let used = doc.title ? doc.title.length + 4 : 0;
3275
+ used += doc.preface.length;
3276
+ const hasEssentialDescendant = (n) => n.children.some((c) => c.tier === "essential" || hasEssentialDescendant(c));
3277
+ const walk = (list) => {
3278
+ for (const node of list) {
3279
+ if (node.tier === "essential" || node.level >= 3 && hasEssentialDescendant(node)) {
3280
+ const own = node.text;
3281
+ if (own.length > cap) {
3282
+ const render = truncateText(own, cap, node.id);
3283
+ decisions.set(node.id, { node, included: "partial", render });
3284
+ used += render.length;
3285
+ } else {
3286
+ decisions.set(node.id, { node, included: true, render: own });
3287
+ used += own.length;
3288
+ }
3289
+ walk(node.children);
3290
+ } else {
3291
+ decisions.set(node.id, { node, included: false, render: "" });
3292
+ for (const c of flattenSections(node.children)) decisions.set(c.id, { node: c, included: false, render: "" });
3293
+ }
3294
+ }
3295
+ };
3296
+ walk(doc.sections);
3297
+ const candidates = flat.filter((s) => decisions.get(s.id)?.included === false).filter((s) => s.level >= 2).filter((s) => {
3298
+ const parent = parentOf(doc.sections, s);
3299
+ return !parent || decisions.get(parent.id)?.included !== false;
3300
+ }).sort((a, b) => deferredPriority(a.heading) - deferredPriority(b.heading) || a.chars - b.chars);
3301
+ for (const s of candidates) {
3302
+ if (used + s.chars > budget) continue;
3303
+ for (const n of [s, ...flattenSections(s.children)]) {
3304
+ decisions.set(n.id, { node: n, included: true, render: n.text });
3305
+ }
3306
+ used += s.chars;
3307
+ }
3308
+ const allIn = flat.every((s) => decisions.get(s.id)?.included === true);
3309
+ if (allIn) return whole();
3310
+ const out = [];
3311
+ if (doc.title) out.push(`# ${doc.title}`);
3312
+ if (doc.preface) out.push(doc.preface);
3313
+ for (const s of flat) {
3314
+ const d = decisions.get(s.id);
3315
+ if (d.included !== false) out.push(d.render.replace(/\n+$/, ""));
3316
+ }
3317
+ const sections = flat.map((s) => summary(s, decisions.get(s.id).included));
3318
+ const topOmitted = flat.filter((s) => {
3319
+ if (decisions.get(s.id).included !== false) return false;
3320
+ const parent = parentOf(doc.sections, s);
3321
+ return !parent || decisions.get(parent.id).included !== false;
3322
+ });
3323
+ const omittedChars = topOmitted.reduce((sum, s) => sum + s.chars, 0) + flat.filter((s) => decisions.get(s.id).included === "partial").reduce((sum, s) => sum + (s.text.length - decisions.get(s.id).render.length), 0);
3324
+ return {
3325
+ markdown: out.join("\n\n"),
3326
+ truncated: true,
3327
+ sections,
3328
+ omitted: topOmitted.length + flat.filter((s) => decisions.get(s.id).included === "partial").length,
3329
+ omittedChars: Math.max(0, omittedChars)
3330
+ };
3331
+ }
3332
+ function summary(s, included) {
3333
+ return { id: s.id, heading: s.heading, level: s.level, chars: s.chars, included };
3334
+ }
3335
+ function parentOf(roots, target) {
3336
+ const find = (list, parent) => {
3337
+ for (const n of list) {
3338
+ if (n === target) return parent;
3339
+ const r = find(n.children, n);
3340
+ if (r !== void 0) return r;
3341
+ }
3342
+ return void 0;
3343
+ };
3344
+ return find(roots, null) ?? null;
3345
+ }
3346
+ function renderWhole(doc) {
3347
+ const out = [];
3348
+ if (doc.title) out.push(`# ${doc.title}`);
3349
+ if (doc.preface) out.push(doc.preface);
3350
+ for (const s of doc.sections) out.push(sectionText(s));
3351
+ return out.join("\n\n");
3352
+ }
3353
+ var DEFAULT_TOC_MAX_ENTRIES = 60;
3354
+ function collapseSections(sections, max = DEFAULT_TOC_MAX_ENTRIES) {
3355
+ if (sections.length <= max) return { sections, collapsed: false };
3356
+ const firstH1 = sections.findIndex((s) => s.level === 1);
3357
+ const canonEnd = firstH1 === -1 ? sections.length : firstH1;
3358
+ for (const depth of [3, 2]) {
3359
+ const keep = (s, i) => i < canonEnd ? s.level <= depth : s.level <= 1;
3360
+ const count = sections.filter(keep).length;
3361
+ if (count > max && depth !== 2) continue;
3362
+ const out = [];
3363
+ let owner = null;
3364
+ sections.forEach((s, i) => {
3365
+ if (keep(s, i)) {
3366
+ owner = { ...s };
3367
+ out.push(owner);
3368
+ } else if (owner) {
3369
+ owner.children = (owner.children ?? 0) + 1;
3370
+ }
3371
+ });
3372
+ return { sections: out, collapsed: true };
3373
+ }
3374
+ return { sections, collapsed: false };
3375
+ }
3376
+ function omittedSections(digest, max = DEFAULT_TOC_MAX_ENTRIES) {
3377
+ return collapseSections(digest.sections.filter((s) => s.included !== true), max);
3378
+ }
3379
+ function renderDigestNotice(digest, platform, actionId) {
3380
+ if (!digest.truncated) return "";
3381
+ const topMost = digest.sections.filter((s, idx) => {
3382
+ if (s.included === true) return false;
3383
+ for (let i = idx - 1; i >= 0; i--) {
3384
+ const prev = digest.sections[i];
3385
+ if (prev.level < s.level) return prev.included !== false;
3386
+ }
3387
+ return true;
3388
+ });
3389
+ const names = topMost.map((s) => {
3390
+ if (s.included === "partial") return `${s.heading} (partial)`;
3391
+ if (s.level === 1) return `${s.heading} (appendix)`;
3392
+ return s.heading;
3393
+ });
3394
+ const base = `one --agent actions knowledge ${platform} ${actionId}`;
3395
+ const MAX_NAMES = 12;
3396
+ const shown = names.slice(0, MAX_NAMES);
3397
+ const rest = names.length - shown.length;
3398
+ const nameList = rest > 0 ? `${shown.join(", ")}, and ${rest} more (see --toc)` : shown.join(", ");
3399
+ return [
3400
+ "---",
3401
+ `**This is a digest, not the full document.** ${topMost.length} section${topMost.length === 1 ? "" : "s"} omitted (${digest.omittedChars.toLocaleString("en-US")} chars): ${nameList}.`,
3402
+ `Load one or more by name or id: ${base} --section "${topMost[0]?.heading ?? "Response"}"`,
3403
+ `Load everything: ${base} --full`
3404
+ ].join("\n");
3405
+ }
3406
+ function renderDigestBanner(digest) {
3407
+ if (!digest.truncated) return "";
3408
+ return `> **Digest.** ${digest.omitted} section${digest.omitted === 1 ? "" : "s"} (${digest.omittedChars.toLocaleString("en-US")} chars) omitted: response shapes, reference schemas, or worked examples. The notice at the end names them and shows how to load them; the JSON \`sections\` array marks them included:false.`;
3409
+ }
3410
+ var ALIASES = {
3411
+ response: (c) => c === "response",
3412
+ responses: (c) => c === "response",
3413
+ "response fields": (c) => c === "response fields",
3414
+ fields: (c) => c === "response fields",
3415
+ optional: (c) => c.startsWith("optional "),
3416
+ required: (c) => c.startsWith("required "),
3417
+ examples: (c) => c === "example usage" || c === "examples",
3418
+ example: (c) => c === "example usage" || c === "examples",
3419
+ errors: (c) => c.startsWith("error response") || c === "error handling",
3420
+ success: (c) => c.startsWith("success response"),
3421
+ body: (c) => c === "request body" || c.endsWith("request body fields"),
3422
+ query: (c) => c.endsWith("query parameters"),
3423
+ path: (c) => c.endsWith("path parameters"),
3424
+ notes: (c) => c === "notes",
3425
+ behavior: (c) => c === "behavior" || c === "behaviour",
3426
+ gotchas: (c) => c === "gotchas"
3427
+ };
3428
+ function normalizeQuery(q) {
3429
+ return q.trim().replace(/^["'`]+|["'`]+$/g, "").toLowerCase().replace(/\s+/g, " ");
3430
+ }
3431
+ function findSections(doc, query) {
3432
+ const flat = flattenSections(doc.sections);
3433
+ const q = normalizeQuery(query);
3434
+ const qSlug = slugify(q);
3435
+ const miss = (reason, candidates) => ({
3436
+ ok: false,
3437
+ reason,
3438
+ query,
3439
+ candidates: candidates.map((s) => summary(s, false))
3440
+ });
3441
+ if (!q) return miss("not-found", flat);
3442
+ const exact = flat.filter(
3443
+ (s) => s.id === qSlug || canonicalHeading(s.heading) === q || s.heading.toLowerCase() === q
3444
+ );
3445
+ if (exact.length) return { ok: true, sections: exact };
3446
+ const alias = ALIASES[q];
3447
+ if (alias) {
3448
+ const hits = flat.filter((s) => alias(canonicalHeading(s.heading)));
3449
+ if (hits.length) return { ok: true, sections: dropNested(hits) };
3450
+ }
3451
+ const byPrefix = flat.filter(
3452
+ (s) => s.id.startsWith(qSlug) || canonicalHeading(s.heading).startsWith(q)
3453
+ );
3454
+ if (byPrefix.length === 1) return { ok: true, sections: byPrefix };
3455
+ if (byPrefix.length > 1) {
3456
+ const sameCanon = new Set(byPrefix.map((s) => canonicalHeading(s.heading).replace(/\s*\d.*$/, "")));
3457
+ if (sameCanon.size === 1) return { ok: true, sections: dropNested(byPrefix) };
3458
+ return miss("ambiguous", byPrefix);
3459
+ }
3460
+ const bySubstring = flat.filter(
3461
+ (s) => s.id.includes(qSlug) || canonicalHeading(s.heading).includes(q)
3462
+ );
3463
+ if (bySubstring.length === 1) return { ok: true, sections: bySubstring };
3464
+ if (bySubstring.length > 1) return miss("ambiguous", bySubstring);
3465
+ return miss("not-found", flat);
3466
+ }
3467
+ function dropNested(hits) {
3468
+ const inside = /* @__PURE__ */ new Set();
3469
+ for (const h of hits) for (const c of flattenSections(h.children)) inside.add(c.id);
3470
+ return hits.filter((h) => !inside.has(h.id));
3471
+ }
3472
+ function selectSections(doc, names) {
3473
+ const picked = [];
3474
+ const seen = /* @__PURE__ */ new Set();
3475
+ for (const name of names) {
3476
+ const r = findSections(doc, name);
3477
+ if (!r.ok) return r;
3478
+ for (const s of dropNested(r.sections)) {
3479
+ if (!seen.has(s.id)) {
3480
+ seen.add(s.id);
3481
+ picked.push(s);
3482
+ }
3483
+ }
3484
+ }
3485
+ const order = new Map(flattenSections(doc.sections).map((s, i) => [s.id, i]));
3486
+ const final = dropNested(picked).sort((a, b) => order.get(a.id) - order.get(b.id));
3487
+ const parts = [doc.title ? `# ${doc.title}` : "", ...final.map(sectionText)].filter(Boolean);
3488
+ return { ok: true, sections: final, markdown: parts.join("\n\n") };
3489
+ }
3490
+ function parseSectionFlag(value) {
3491
+ if (!value) return [];
3492
+ const raw = Array.isArray(value) ? value : [value];
3493
+ return raw.flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
3494
+ }
3495
+
3496
+ // src/commands/actions.ts
3084
3497
  function getConfig() {
3085
3498
  const apiKey = getApiKey();
3086
3499
  if (!apiKey) {
@@ -3278,8 +3691,90 @@ async function actionsKnowledgeCommand(platform, actionId, options) {
3278
3691
  knowledge: details.knowledge || "No knowledge was found",
3279
3692
  method: details.method || "No method was found"
3280
3693
  };
3694
+ const doc = parseSections(knowledgeData.knowledge);
3695
+ const sectionNames = parseSectionFlag(options.section);
3696
+ const wantFull = options.full === true || sectionNames.some((n) => n.toLowerCase() === "all");
3697
+ const base = `one --agent actions knowledge ${platform} ${actionId}`;
3698
+ const fullToc = flattenSections(doc.sections).map((s) => ({ id: s.id, heading: s.heading, level: s.level, chars: s.chars }));
3699
+ if (options.toc) {
3700
+ if (isAgentMode()) {
3701
+ json({
3702
+ title: doc.title,
3703
+ method: knowledgeData.method,
3704
+ chars: doc.chars,
3705
+ sections: fullToc,
3706
+ more: { section: `${base} --section <id or heading>[,<id or heading>...]`, full: `${base} --full` },
3707
+ _cache: buildCacheMeta(entry, cacheHit)
3708
+ });
3709
+ return;
3710
+ }
3711
+ spinner4.stop("Sections");
3712
+ console.log();
3713
+ for (const t of fullToc) console.log(`${" ".repeat(Math.max(0, t.level - 1))}${t.heading} ${pc8.dim(`[${t.id}] ${t.chars} chars`)}`);
3714
+ console.log();
3715
+ return;
3716
+ }
3717
+ if (sectionNames.length > 0 && !wantFull) {
3718
+ const picked = selectSections(doc, sectionNames);
3719
+ if (!picked.ok) {
3720
+ const toc = collapseSections(picked.candidates);
3721
+ const list = toc.sections.map((c) => `${" ".repeat(Math.max(0, c.level - 2))}${c.heading} [${c.id}] (${c.chars} chars${c.children ? `, +${c.children} nested` : ""})`).join("\n");
3722
+ if (isAgentMode()) {
3723
+ json({
3724
+ error: picked.reason === "ambiguous" ? `Section "${picked.query}" matches several sections; pick one by id or full heading.` : `No section named "${picked.query}". Use one of the ids or headings below, or --full.`,
3725
+ query: picked.query,
3726
+ reason: picked.reason,
3727
+ sections: toc.sections.map(({ id, heading, level, chars, children }) => children ? { id, heading, level, chars, children } : { id, heading, level, chars }),
3728
+ ...toc.collapsed ? { sectionsCollapsed: true, sectionCount: picked.candidates.length } : {},
3729
+ hint: `${base} --section <id or heading>`,
3730
+ toc: `${base} --toc`
3731
+ });
3732
+ process.exit(1);
3733
+ }
3734
+ spinner4.stop("Section not found");
3735
+ error(`${picked.reason === "ambiguous" ? "Ambiguous" : "Unknown"} section "${picked.query}". Available:
3736
+ ${list}`);
3737
+ }
3738
+ if (isAgentMode()) {
3739
+ json({
3740
+ knowledge: picked.markdown,
3741
+ method: knowledgeData.method,
3742
+ title: doc.title,
3743
+ // The requested sections are returned whole; nothing here was cut.
3744
+ truncated: false,
3745
+ requested: sectionNames,
3746
+ // What each name matched — fuzzy and alias matches are visible here.
3747
+ resolved: picked.sections.map((s) => ({ id: s.id, heading: s.heading, chars: s.chars })),
3748
+ sectionCount: fullToc.length,
3749
+ more: {
3750
+ note: "Only the requested sections are included. The digest call listed the others; `--toc` lists all of them.",
3751
+ section: `${base} --section <id or heading>[,<id or heading>...]`,
3752
+ toc: `${base} --toc`,
3753
+ full: `${base} --full`
3754
+ },
3755
+ _cache: buildCacheMeta(entry, cacheHit)
3756
+ });
3757
+ return;
3758
+ }
3759
+ spinner4.stop("Sections loaded");
3760
+ console.log();
3761
+ console.log(picked.markdown);
3762
+ console.log();
3763
+ return;
3764
+ }
3765
+ const digest = buildDigest(
3766
+ doc,
3767
+ isAgentMode() && !wantFull ? {} : { wholeDocThreshold: Number.POSITIVE_INFINITY }
3768
+ );
3769
+ const body = doc.sections.length === 0 ? knowledgeData.knowledge : digest.markdown;
3770
+ const notice = renderDigestNotice(digest, platform, actionId);
3771
+ const banner = renderDigestBanner(digest);
3281
3772
  const knowledgeWithGuidance = buildActionKnowledgeWithGuidance(
3282
- knowledgeData.knowledge,
3773
+ notice ? `${banner}
3774
+
3775
+ ${body}
3776
+
3777
+ ${notice}` : body,
3283
3778
  knowledgeData.method,
3284
3779
  platform,
3285
3780
  actionId
@@ -3288,8 +3783,26 @@ async function actionsKnowledgeCommand(platform, actionId, options) {
3288
3783
  const response = {
3289
3784
  knowledge: knowledgeWithGuidance,
3290
3785
  method: knowledgeData.method,
3786
+ title: doc.title || void 0,
3787
+ truncated: digest.truncated,
3291
3788
  _cache: buildCacheMeta(entry, cacheHit)
3292
3789
  };
3790
+ if (digest.truncated) {
3791
+ const toc = omittedSections(digest);
3792
+ response.omitted = digest.omitted;
3793
+ response.omittedChars = digest.omittedChars;
3794
+ response.sections = toc.sections;
3795
+ if (toc.collapsed) {
3796
+ response.sectionsCollapsed = true;
3797
+ response.sectionCount = digest.sections.length;
3798
+ }
3799
+ response.more = {
3800
+ note: toc.collapsed ? `This is a digest. \`sections\` lists what was omitted, collapsed to ${toc.sections.length} entries (\`children\` counts nested ones); request any by id or heading, or --toc for all ${digest.sections.length} headings.` : "This is a digest. `sections` lists what was omitted; request any by id or heading.",
3801
+ section: `${base} --section <id or heading>[,<id or heading>...]`,
3802
+ toc: `${base} --toc`,
3803
+ full: `${base} --full`
3804
+ };
3805
+ }
3293
3806
  json(response);
3294
3807
  return;
3295
3808
  }
@@ -10660,7 +11173,7 @@ Before using any feature, read its guide section first: \`one guide actions\`, \
10660
11173
 
10661
11174
  ## Features
10662
11175
 
10663
- ### 1. Actions \u2014 Execute API calls on 600+ platforms
11176
+ ### 1. Actions \u2014 Execute API calls on 750+ platforms
10664
11177
  Search for actions, read their docs, and execute them. This is the core workflow.
10665
11178
 
10666
11179
  **Quick start:**
@@ -10805,7 +11318,43 @@ one --agent actions search <platform> "<query>" -t execute
10805
11318
  one --agent actions knowledge <platform> <actionId>
10806
11319
  \`\`\`
10807
11320
 
10808
- Returns full API docs: required fields, validation rules, request structure. **REQUIRED before execute.** The output includes a CLI PARAMETER MAPPING section showing which flags to use.
11321
+ Returns the API docs: required fields, validation rules, request structure. **REQUIRED before execute.** The output includes a CLI PARAMETER MAPPING section showing which flags to use.
11322
+
11323
+ **In \`--agent\` mode this is a digest, not the whole document.** Large docs (most of their size is response shapes and optional-field tables) are trimmed to the sections needed to build a correct request: method/URL, headers, description, enforcement rules, required and optional parameters, sample request, gotchas, error handling. Everything else is listed in a table of contents so you can pull it on demand:
11324
+
11325
+ \`\`\`json
11326
+ {
11327
+ "knowledge": "...digest markdown, ends with a notice naming the omitted sections...",
11328
+ "method": "POST",
11329
+ "title": "Create an Issue",
11330
+ "truncated": true,
11331
+ "sections": [
11332
+ { "id": "response", "heading": "Response", "level": 2, "chars": 16483, "included": false },
11333
+ { "id": "response-fields", "heading": "Response Fields", "level": 2, "chars": 3353, "included": false }
11334
+ ],
11335
+ "omitted": 2,
11336
+ "omittedChars": 19836,
11337
+ "more": { "section": "one --agent actions knowledge <platform> <actionId> --section <id>[,<id>...]", "full": "..." }
11338
+ }
11339
+ \`\`\`
11340
+
11341
+ - \`truncated: false\` means you have the whole document \u2014 small docs are never trimmed, and no \`sections\` list is sent.
11342
+ - \`sections\` lists only what was omitted. \`included\` is \`false\` or \`"partial"\` (an oversized essential section was cut; its text ends with a truncation marker). Included sections are simply the headings in the markdown.
11343
+ - Load more by heading, id, or alias \u2014 several at once, comma-separated or repeated:
11344
+
11345
+ \`\`\`bash
11346
+ one --agent actions knowledge <platform> <actionId> --section "Response Fields"
11347
+ one --agent actions knowledge <platform> <actionId> --section response,optional
11348
+ one --agent actions knowledge <platform> <actionId> --full
11349
+ \`\`\`
11350
+
11351
+ Aliases: \`response\`, \`fields\`, \`optional\`, \`required\`, \`examples\`, \`errors\`, \`success\`, \`body\`, \`query\`, \`path\`, \`notes\`, \`behavior\`, \`gotchas\`. A parent section brings its subsections. Section requests are served from the local cache \u2014 no network call. An unknown name returns an error that lists every available section, so retry with one of those ids.
11352
+
11353
+ A \`--section\` response carries \`requested\`, \`resolved\` (the ids each name matched \u2014 alias and prefix matches are visible here), and \`truncated: false\` (the requested sections are whole). It does not repeat the table of contents. On scraped mega-docs with hundreds of headings the digest's \`sections\` list is collapsed to the top levels (\`sectionsCollapsed: true\`, each entry's \`children\` counts the hidden ones); \`--toc\` returns the complete list without the document:
11354
+
11355
+ \`\`\`bash
11356
+ one --agent actions knowledge <platform> <actionId> --toc
11357
+ \`\`\`
10809
11358
 
10810
11359
  ### 4. Execute
10811
11360
 
@@ -11010,6 +11559,8 @@ In \`--agent\` mode, knowledge and search responses include a \`_cache\` field:
11010
11559
  {
11011
11560
  "knowledge": "...",
11012
11561
  "method": "POST",
11562
+ "truncated": true,
11563
+ "sections": [ ... ],
11013
11564
  "_cache": {
11014
11565
  "hit": true,
11015
11566
  "age": 1423,
@@ -11029,6 +11580,9 @@ one --agent actions knowledge <platform> <actionId> --no-cache
11029
11580
  # Check cache status without fetching
11030
11581
  one --agent actions knowledge <platform> <actionId> --cache-status
11031
11582
 
11583
+ # Sections and --full are served from the cache once the doc is cached
11584
+ one --agent actions knowledge <platform> <actionId> --section "Response Fields"
11585
+
11032
11586
  # Same for search
11033
11587
  one --agent actions search <platform> "<query>" --no-cache
11034
11588
 
@@ -11885,7 +12439,7 @@ function buildStep1() {
11885
12439
  nextCommand: "one onboard --step 2",
11886
12440
  message: `# One CLI \u2014 Agent Onboarding
11887
12441
 
11888
- You now have access to the One CLI. It connects you to 600+ platforms
12442
+ You now have access to the One CLI. It connects you to 750+ platforms
11889
12443
  (Gmail, Slack, Stripe, Notion, etc.) \u2014 you'll learn the details shortly.
11890
12444
 
11891
12445
  IMPORTANT: Your only task right now is to send the message below to the
@@ -11895,7 +12449,7 @@ Do not offer demos yet. Just send this message and wait for their reply:
11895
12449
  ---
11896
12450
 
11897
12451
  I just got access to the One CLI \u2014 it connects me to your platforms like
11898
- Gmail, Slack, Stripe, and 600+ others so I can work with them directly.
12452
+ Gmail, Slack, Stripe, and 750+ others so I can work with them directly.
11899
12453
  I'll show you what I can do in a moment.
11900
12454
 
11901
12455
  First, one quick setup step: right now only this conversation knows about
@@ -11924,7 +12478,7 @@ If they declined, skip this section.
11924
12478
  ## One CLI \u2014 Platform Integrations
11925
12479
 
11926
12480
  The One CLI (\`one\`) is installed and configured on this machine. It is a
11927
- command-line tool that gives AI agents the ability to interact with 600+
12481
+ command-line tool that gives AI agents the ability to interact with 750+
11928
12482
  third-party platforms (Gmail, Slack, Shopify, HubSpot, Stripe, GitHub,
11929
12483
  Notion, Salesforce, etc.) through a single, unified interface.
11930
12484
 
@@ -11945,7 +12499,7 @@ common mistakes to avoid. Never guess \u2014 read the skill, then act.
11945
12499
  ### Quick reference:
11946
12500
  - \`one --agent list\` \u2014 See connected platforms and connection keys
11947
12501
  - \`one --agent actions search <platform> "<query>"\` \u2014 Find actions
11948
- - \`one --agent actions knowledge <platform> <actionId>\` \u2014 Read docs (REQUIRED before execute)
12502
+ - \`one --agent actions knowledge <platform> <actionId>\` \u2014 Read docs (REQUIRED before execute; a digest \u2014 add \`--section <name>\` or \`--full\` for more)
11949
12503
  - \`one --agent actions execute <platform> <actionId> <connectionKey>\` \u2014 Execute action
11950
12504
  - \`one --agent flow create\` \u2014 Build multi-step workflows
11951
12505
  - \`one --agent relay create\` \u2014 Set up webhook relay (receive events, forward to other platforms)
@@ -12019,7 +12573,7 @@ function buildStep3(connections) {
12019
12573
  The user can connect any of these popular platforms:
12020
12574
  Gmail, Google Calendar, Slack, Notion, Shopify, Stripe, HubSpot, GitHub,
12021
12575
  Salesforce, QuickBooks, Asana, Jira, Linear, Intercom, Zendesk, Twilio,
12022
- and 600+ more. Run \`one platforms\` for the full list.`);
12576
+ and 750+ more. Run \`one platforms\` for the full list.`);
12023
12577
  sections.push("## Onboarding complete!\n\nYou're all set. Use `one --agent guide` any time you need the full reference.");
12024
12578
  return {
12025
12579
  step: 3,
@@ -12050,7 +12604,7 @@ platform before you can start using actions. Suggest they run:
12050
12604
  one add slack
12051
12605
  one add <any-platform>
12052
12606
 
12053
- Run \`one platforms\` to see all 600+ available platforms.`;
12607
+ Run \`one platforms\` to see all 750+ available platforms.`;
12054
12608
  }
12055
12609
  const header = `## Current State
12056
12610
 
@@ -12234,7 +12788,7 @@ silenceWarningsInAgentMode();
12234
12788
  var require4 = createRequire3(import.meta.url);
12235
12789
  var { version } = require4("../package.json");
12236
12790
  var program = new Command();
12237
- program.name("one").option("--agent", "Machine-readable JSON output (no colors, spinners, or prompts)").description(`One CLI \u2014 Connect AI agents to 600+ platforms through one interface.
12791
+ program.name("one").option("--agent", "Machine-readable JSON output (no colors, spinners, or prompts)").description(`One CLI \u2014 Connect AI agents to 750+ platforms through one interface.
12238
12792
 
12239
12793
  Setup:
12240
12794
  one login Authenticate via browser; the consent page records where this CLI is installed
@@ -12248,7 +12802,7 @@ program.name("one").option("--agent", "Machine-readable JSON output (no colors,
12248
12802
  Workflow (use these in order):
12249
12803
  1. one list List connected platforms, keys, and your access on each
12250
12804
  2. one actions search <platform> <q> Search for actions using natural language
12251
- 3. one actions knowledge <plat> <id> Get full docs for an action (ALWAYS do this before execute)
12805
+ 3. one actions knowledge <plat> <id> Get docs for an action (ALWAYS do this before execute; --section/--full for more)
12252
12806
  4. one actions execute <p> <id> <key> Execute the action
12253
12807
 
12254
12808
  Guide:
@@ -12306,7 +12860,7 @@ program.name("one").option("--agent", "Machine-readable JSON output (no colors,
12306
12860
  -d '{"to":"j@example.com","subject":"Hello","body":"Hi!","connectionKey":"live::gmail::default::abc123"}'
12307
12861
 
12308
12862
  Platform names are lowercase; multi-word names use dashes (e.g. hubspot, ship-station, google-calendar).
12309
- Run 'one platforms' to browse all 600+ available platforms.`).version(version);
12863
+ Run 'one platforms' to browse all 750+ available platforms.`).version(version);
12310
12864
  var updateCheckPromise;
12311
12865
  program.hook("preAction", (thisCommand, actionCommand) => {
12312
12866
  const opts = program.opts();
@@ -12518,7 +13072,7 @@ var actions = program.command("actions").alias("a").description("Search, explore
12518
13072
  actions.command("search <platform> <query>").description('Search for actions on a platform (e.g. one actions search gmail "send email")').option("-t, --type <type>", "execute (to run it) or knowledge (to learn about it). Default: knowledge").option("--no-cache", "Bypass the cache and re-fetch from the API (the fresh response still refreshes the cache)").action(async (platform, query, options) => {
12519
13073
  await actionsSearchCommand(platform, query, options);
12520
13074
  });
12521
- actions.command("knowledge <platform> <actionId>").alias("k").description("Get full docs for an action \u2014 MUST call before execute to know required params").option("--no-cache", "Bypass the cache and re-fetch from the API (the fresh response still refreshes the cache)").option("--cache-status", "Print cache metadata without fetching").action(async (platform, actionId, options) => {
13075
+ actions.command("knowledge <platform> <actionId>").alias("k").description("Get docs for an action \u2014 MUST call before execute to know required params. In --agent mode returns a digest (request-building sections + a table of contents); load the rest with --section or --full").option("--section <name>", 'Return only the named section(s) \u2014 by heading, id, or alias (e.g. "Response Fields", response, optional). Repeatable or comma-separated', collect, []).option("--full", "Return the whole document instead of the digest").option("--toc", "List every section (id, heading, size) without the document").option("--no-cache", "Bypass the cache and re-fetch from the API (the fresh response still refreshes the cache)").option("--cache-status", "Print cache metadata without fetching").action(async (platform, actionId, options) => {
12522
13076
  await actionsKnowledgeCommand(platform, actionId, options);
12523
13077
  });
12524
13078
  actions.command("execute [platform] [actionId] [connectionKey]").alias("x").allowUnknownOption(true).allowExcessArguments(true).description("Execute an action (or multiple with --parallel, separated by --)").option("-d, --data <json>", "Request body as JSON").option("--path-vars <json>", "Path variables as JSON").option("--query-params <json>", "Query parameters as JSON").option("--headers <json>", "Additional headers as JSON").option("--form-data", "Send as multipart/form-data").option("--form-url-encoded", "Send as application/x-www-form-urlencoded").option("--dry-run", "Show request that would be sent without executing").option("--mock", "Return example response without making an API call").option("--skip-validation", "Skip input validation against the action schema").option("--no-cache", "Bypass the cached action details and re-fetch them (the fresh details still refresh the cache; execution itself is never cached)").option("--output <path>", "Save binary response to a file (for non-JSON responses like file downloads)").option("--parallel", "Execute multiple actions concurrently (separate actions with --)").option("--max-concurrency <n>", "Max concurrent actions when using --parallel (default: 5)", "5").action(async (platform, actionId, connectionKey, options) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@withone/cli",
3
- "version": "1.56.0",
3
+ "version": "1.57.0",
4
4
  "description": "CLI for managing One",
5
5
  "type": "module",
6
6
  "files": [
@@ -20,7 +20,7 @@ description: |
20
20
 
21
21
  # One CLI
22
22
 
23
- You have access to the One CLI which lets you interact with 600+ third-party platforms through their APIs. Always include the `--agent` flag right after `one` for structured JSON output.
23
+ You have access to the One CLI which lets you interact with 750+ third-party platforms through their APIs. Always include the `--agent` flag right after `one` for structured JSON output.
24
24
 
25
25
  If the user wants a separate API key / connections for a specific project (vs. their default), walk them through running `one init` from that project folder and picking the "project" scope — see `references/scoping.md`. For monorepo subprojects (where a parent already has `.git`/`package.json`), have them `mkdir .one` in the subproject first so the config is keyed to that dir, not the monorepo root.
26
26
 
@@ -89,6 +89,26 @@ one --agent actions knowledge <platform> <actionId>
89
89
 
90
90
  This tells you exactly what parameters are required, how to structure the request, and which flags to use. Never skip this step — without it you'll guess wrong on parameters.
91
91
 
92
+ **You get a digest, not always the whole document.** Large docs are trimmed to the request-building sections (method/URL, headers, description, rules, required + optional parameters, sample request, gotchas, error handling). The response tells you what was left out:
93
+
94
+ - `truncated: true` — some sections are omitted. `truncated: false` — you have everything (and no `sections` list is sent).
95
+ - `sections[]` — the omitted sections only, each with `id`, `heading`, `chars`, and `included` (`false` / `"partial"`). Included sections are the headings you can see in the markdown.
96
+ - The markdown itself ends with a notice naming the omitted sections and the exact commands to load them.
97
+
98
+ Load more only when you need it (response shapes, response fields, worked examples). Served from the local cache, no network:
99
+
100
+ ```bash
101
+ one --agent actions knowledge <platform> <actionId> --section "Response Fields" # by heading
102
+ one --agent actions knowledge <platform> <actionId> --section response,optional # by alias, several at once
103
+ one --agent actions knowledge <platform> <actionId> --full # whole document
104
+ ```
105
+
106
+ Aliases: `response`, `fields`, `optional`, `required`, `examples`, `errors`, `success`, `body`, `query`, `path`, `notes`, `behavior`, `gotchas`. An unknown name returns an error listing every available section — retry with one of those ids.
107
+
108
+ - A `--section` response has `truncated: false` (you got the whole section) and `resolved` (which ids your names matched). It does not repeat the table of contents.
109
+ - If the digest says `sectionsCollapsed: true`, the doc has hundreds of headings and `sections` shows only the top omitted levels (`children` = hidden count). `--toc` lists every heading without the document.
110
+ - Sections named `(appendix)` in the notice are appended reference chunks or companion endpoints, not the action doc itself.
111
+
92
112
  ### 4. Execute
93
113
 
94
114
  ```bash
@@ -164,6 +184,7 @@ Knowledge and search responses are cached locally (`~/.one/cache/`). Subsequent
164
184
  - In `--agent` mode, responses include a `_cache` field: `{"hit": true, "age": 1423, "fresh": true}`; execute responses include `"_preflight": {"cache": "hit"|"miss"}`
165
185
  - Use `--no-cache` to force a fresh fetch: works on `knowledge`, `search`, and `execute` (refreshes execute's action-details lookup)
166
186
  - Use `--cache-status` to check cache state without fetching
187
+ - `knowledge --section <name>` and `--full` read from the cached document — no extra API call once the doc is cached
167
188
  - Manage cache: `one cache list`, `one cache clear`, `one cache update-all`
168
189
  - Execution responses are NEVER cached — the action always runs live; only action metadata (docs, method, path, schema) is cached
169
190