@withone/cli 2.9.1 → 2.10.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 +19 -4
- package/bin/cli.js +7 -1
- package/dist/{chunk-UP2L4XJH.js → chunk-5CPQHXTO.js} +17 -1
- package/dist/chunk-FYTWXGPJ.js +79 -0
- package/dist/{flow-runner-K73VDSS3.js → flow-runner-P23IZDWM.js} +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +872 -375
- package/dist/node-check.d.ts +36 -0
- package/dist/node-check.js +18 -0
- package/package.json +2 -2
- package/skills/one/SKILL.md +11 -0
package/README.md
CHANGED
|
@@ -50,10 +50,14 @@ one logout # Clear credentials (with scope picker and confirmation)
|
|
|
50
50
|
|
|
51
51
|
The browser consent page names the key and tags it with where this CLI is installed (scope, project path, machine, OS user, CLI version, chosen harnesses, and the per-install device id unless telemetry is off) so you can find and revoke it from Settings → API keys. The terminal prints exactly what will be sent before the browser opens.
|
|
52
52
|
|
|
53
|
-
Requires Node.js
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
53
|
+
Requires Node.js 22.23.4+, 24.22.1+ or 26.12.1+. Older Node versions trust the
|
|
54
|
+
compromised eMudhra intermediate CA certificates (October 2026), so a network
|
|
55
|
+
attacker could intercept the CLI's traffic and your API key. On them the CLI
|
|
56
|
+
refuses to run and prints the command that updates Node for how you installed
|
|
57
|
+
it. Node 18, 20, 23 and 25 are end-of-life and never got the fix.
|
|
58
|
+
|
|
59
|
+
If you can't update Node yet, `ONE_ALLOW_UNPATCHED_NODE=1` runs the CLI anyway,
|
|
60
|
+
with a security warning on every run. You remain exposed while it is set.
|
|
57
61
|
|
|
58
62
|
## Quick start
|
|
59
63
|
|
|
@@ -523,6 +527,17 @@ What `one skills add connect` does:
|
|
|
523
527
|
|
|
524
528
|
Commit `.agents/skills/one-connect` and the agent links so your team's agents share the skill. Agent mode (`--agent`) returns JSON for every subcommand.
|
|
525
529
|
|
|
530
|
+
### `one connect`
|
|
531
|
+
|
|
532
|
+
Create and update a [One Connect](https://www.npmjs.com/package/@withone/connect) app from `one.connect.ts`, typed by `defineConnectApp` from `@withone/connect/config` (0.19.0 or later).
|
|
533
|
+
|
|
534
|
+
```bash
|
|
535
|
+
one connect types # writes one-connect-env.d.ts: tool slugs and action names autocomplete
|
|
536
|
+
one connect create # approve the app in the browser; re-run to review and apply changes
|
|
537
|
+
```
|
|
538
|
+
|
|
539
|
+
`one connect create` opens a setup page in your signed-in browser, where you review the app (or, on a re-run, its new version) and approve it; nothing is created or changed with your API key. A new app's client secret and connect key are made there and shown once, so they never pass through the terminal. Once you approve, the CLI writes `ONE_CLIENT_ID`, `ONE_PERMISSION_SET` and `ONE_REDIRECT_URI` to `.env.local` (or `.env`). Each tool in `ask` takes `access`: `read-only`, `read-write`, `full-access`, or `custom` with `actions`, named as `one connect types` wrote them or by id from `one actions find <platform> "<what it does>" --no-knowledge`. Options: `--config <file>`, `--env-file <file>`, `--no-open`. Install `@withone/connect` (0.19.0 or later) in the project first. A `.ts` config needs Node 22.18 or later; on older Node use `one.connect.mjs`.
|
|
540
|
+
|
|
526
541
|
### `one guide [topic]`
|
|
527
542
|
|
|
528
543
|
Get the full CLI usage guide, designed for AI agents that only have the binary (no MCP, no IDE skills).
|
package/bin/cli.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import {
|
|
3
|
+
import { requirePatchedNode } from '../dist/node-check.js';
|
|
4
|
+
|
|
5
|
+
// eMudhra CA compromise: refuse to run before any connection opens on a Node
|
|
6
|
+
// that still trusts the leaked intermediates (see src/node-check.ts).
|
|
7
|
+
requirePatchedNode();
|
|
8
|
+
|
|
9
|
+
const { program } = await import('../dist/index.js');
|
|
4
10
|
|
|
5
11
|
program.parse();
|
|
@@ -1120,6 +1120,22 @@ var OneApi = class {
|
|
|
1120
1120
|
};
|
|
1121
1121
|
}
|
|
1122
1122
|
}
|
|
1123
|
+
/** Every action on a platform, page by page, following the server's `pages`. */
|
|
1124
|
+
async listAllAvailableActions(platform) {
|
|
1125
|
+
const all = [];
|
|
1126
|
+
let page = 1;
|
|
1127
|
+
let totalPages = 1;
|
|
1128
|
+
do {
|
|
1129
|
+
const response = await this.requestFull({
|
|
1130
|
+
path: `/available-actions/${encodeURIComponent(platform)}`,
|
|
1131
|
+
queryParams: { page: String(page), limit: "100" }
|
|
1132
|
+
});
|
|
1133
|
+
all.push(...response.rows || []);
|
|
1134
|
+
totalPages = response.pages || 1;
|
|
1135
|
+
page++;
|
|
1136
|
+
} while (page <= totalPages);
|
|
1137
|
+
return all;
|
|
1138
|
+
}
|
|
1123
1139
|
// Webhook Relay methods
|
|
1124
1140
|
async createRelayEndpoint(body) {
|
|
1125
1141
|
return this.requestFull({ path: "/webhooks/relay", method: "POST", body });
|
|
@@ -2961,7 +2977,7 @@ async function executeSubflowStep(step, context, api, permissions, allowedAction
|
|
|
2961
2977
|
if (flowStack.includes(resolvedKey)) {
|
|
2962
2978
|
throw new Error(`Circular flow detected: ${[...flowStack, resolvedKey].join(" \u2192 ")}`);
|
|
2963
2979
|
}
|
|
2964
|
-
const { loadFlowWithMeta: loadFlowWithMeta2 } = await import("./flow-runner-
|
|
2980
|
+
const { loadFlowWithMeta: loadFlowWithMeta2 } = await import("./flow-runner-P23IZDWM.js");
|
|
2965
2981
|
const { flow: subFlow, rootDir: subRootDir } = loadFlowWithMeta2(resolvedKey);
|
|
2966
2982
|
const subContext = await executeFlow(
|
|
2967
2983
|
subFlow,
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// src/node-check.ts
|
|
2
|
+
var FIXED_IN = {
|
|
3
|
+
22: [23, 4],
|
|
4
|
+
24: [22, 1],
|
|
5
|
+
26: [12, 1]
|
|
6
|
+
};
|
|
7
|
+
var FIRST_LINE_WITH_FIX = 27;
|
|
8
|
+
var RECOMMENDED_LINE = 24;
|
|
9
|
+
var REQUIRED_NODE = "22.23.4+, 24.22.1+ or 26.12.1+";
|
|
10
|
+
var REQUIRED_NODE_RANGE = "^22.23.4 || ^24.22.1 || >=26.12.1";
|
|
11
|
+
var ALLOW_UNPATCHED_ENV = "ONE_ALLOW_UNPATCHED_NODE";
|
|
12
|
+
function parseVersion(version) {
|
|
13
|
+
const [major, minor, patch] = version.split(".").map((part) => Number.parseInt(part, 10));
|
|
14
|
+
return [major, minor, patch ?? 0];
|
|
15
|
+
}
|
|
16
|
+
function nodeHasTlsFix(version = process.versions.node) {
|
|
17
|
+
const [major, minor, patch] = parseVersion(version);
|
|
18
|
+
if (!Number.isFinite(major)) return false;
|
|
19
|
+
if (major >= FIRST_LINE_WITH_FIX) return true;
|
|
20
|
+
const fixed = FIXED_IN[major];
|
|
21
|
+
if (!fixed) return false;
|
|
22
|
+
const [fixedMinor, fixedPatch] = fixed;
|
|
23
|
+
return minor > fixedMinor || minor === fixedMinor && patch >= fixedPatch;
|
|
24
|
+
}
|
|
25
|
+
function upgradeCommand(version = process.versions.node, execPath = process.execPath) {
|
|
26
|
+
const [major] = parseVersion(version);
|
|
27
|
+
const line = FIXED_IN[major] ? major : RECOMMENDED_LINE;
|
|
28
|
+
const path = execPath.replace(/\\/g, "/");
|
|
29
|
+
if (/\/\.nvm\/versions\/node\//.test(path)) return `nvm install ${line} && nvm alias default ${line}`;
|
|
30
|
+
if (/\/AppData\/(Roaming|Local)\/nvm\//i.test(path)) return `nvm install ${line} && nvm use ${line}`;
|
|
31
|
+
if (/\/\.?volta\//i.test(path)) return `volta install node@${line}`;
|
|
32
|
+
if (/fnm/i.test(path)) return `fnm install ${line} && fnm default ${line}`;
|
|
33
|
+
const brew = path.match(/\/Cellar\/(node(?:@\d+)?)\//);
|
|
34
|
+
if (brew) {
|
|
35
|
+
const formula = brew[1] === "node" || FIXED_IN[major] ? brew[1] : `node@${line}`;
|
|
36
|
+
return formula === brew[1] ? `brew upgrade ${formula}` : `brew install ${formula}`;
|
|
37
|
+
}
|
|
38
|
+
return `download Node.js ${line} from https://nodejs.org`;
|
|
39
|
+
}
|
|
40
|
+
function unpatchedNodeMessage(version = process.versions.node) {
|
|
41
|
+
return `Node.js v${version} trusts the compromised eMudhra certificates, so a network attacker could intercept One's traffic and your API key. The One CLI requires Node.js ${REQUIRED_NODE} (Node 18, 20, 23 and 25 never got the fix).`;
|
|
42
|
+
}
|
|
43
|
+
function requirePatchedNode() {
|
|
44
|
+
if (nodeHasTlsFix()) return;
|
|
45
|
+
const message = unpatchedNodeMessage();
|
|
46
|
+
const upgrade = upgradeCommand();
|
|
47
|
+
const agent = process.argv.includes("--agent") || process.env.ONE_AGENT === "1";
|
|
48
|
+
if (process.env[ALLOW_UNPATCHED_ENV] === "1") {
|
|
49
|
+
if (!agent) process.stderr.write(`Warning: ${message} Running anyway because ${ALLOW_UNPATCHED_ENV}=1.
|
|
50
|
+
`);
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (agent) {
|
|
54
|
+
const error = {
|
|
55
|
+
error: `${message} Ask the user to update Node.js: ${upgrade}`,
|
|
56
|
+
code: "NODE_UPGRADE_REQUIRED",
|
|
57
|
+
currentNode: process.versions.node,
|
|
58
|
+
requiredNode: REQUIRED_NODE_RANGE,
|
|
59
|
+
upgrade
|
|
60
|
+
};
|
|
61
|
+
process.stdout.write(`${JSON.stringify(error)}
|
|
62
|
+
`);
|
|
63
|
+
} else {
|
|
64
|
+
process.stderr.write(`Error: ${message}
|
|
65
|
+
To update: ${upgrade}
|
|
66
|
+
`);
|
|
67
|
+
}
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export {
|
|
72
|
+
REQUIRED_NODE,
|
|
73
|
+
REQUIRED_NODE_RANGE,
|
|
74
|
+
ALLOW_UNPATCHED_ENV,
|
|
75
|
+
nodeHasTlsFix,
|
|
76
|
+
upgradeCommand,
|
|
77
|
+
unpatchedNodeMessage,
|
|
78
|
+
requirePatchedNode
|
|
79
|
+
};
|