@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 +15 -2
- package/dist/index.js +585 -31
- package/package.json +1 -1
- package/skills/one/SKILL.md +22 -1
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
|
|
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
|
|
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
|
-
|
|
1602
|
-
|
|
1620
|
+
wrapForNote(
|
|
1621
|
+
`The consent page records this on the key, so you can find the install later.
|
|
1603
1622
|
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
"
|
|
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
|
|
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
|
|
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(
|
|
2438
|
-
console.log(
|
|
2439
|
-
console.log(
|
|
2440
|
-
console.log(
|
|
2441
|
-
console.log(
|
|
2442
|
-
console.log(
|
|
2443
|
-
console.log(
|
|
2444
|
-
console.log(
|
|
2445
|
-
console.log(
|
|
2446
|
-
console.log(
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
package/skills/one/SKILL.md
CHANGED
|
@@ -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
|
|
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
|
|