@picahq/cli 1.10.0 → 1.11.1
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 +86 -86
- package/dist/index.js +181 -181
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@ import pc3 from "picocolors";
|
|
|
12
12
|
import fs from "fs";
|
|
13
13
|
import path from "path";
|
|
14
14
|
import os from "os";
|
|
15
|
-
var CONFIG_DIR = path.join(os.homedir(), ".
|
|
15
|
+
var CONFIG_DIR = path.join(os.homedir(), ".one");
|
|
16
16
|
var CONFIG_FILE = path.join(CONFIG_DIR, "config.json");
|
|
17
17
|
function getConfigPath() {
|
|
18
18
|
return CONFIG_FILE;
|
|
@@ -37,8 +37,8 @@ function writeConfig(config) {
|
|
|
37
37
|
}
|
|
38
38
|
fs.writeFileSync(CONFIG_FILE, JSON.stringify(config, null, 2), { mode: 384 });
|
|
39
39
|
}
|
|
40
|
-
function
|
|
41
|
-
const rcPath = path.join(process.cwd(), ".
|
|
40
|
+
function readOneRc() {
|
|
41
|
+
const rcPath = path.join(process.cwd(), ".onerc");
|
|
42
42
|
if (!fs.existsSync(rcPath)) return {};
|
|
43
43
|
try {
|
|
44
44
|
const content = fs.readFileSync(rcPath, "utf-8");
|
|
@@ -58,26 +58,26 @@ function readPicaRc() {
|
|
|
58
58
|
}
|
|
59
59
|
}
|
|
60
60
|
function getApiKey() {
|
|
61
|
-
if (process.env.
|
|
62
|
-
const rc =
|
|
63
|
-
if (rc.
|
|
61
|
+
if (process.env.ONE_SECRET) return process.env.ONE_SECRET;
|
|
62
|
+
const rc = readOneRc();
|
|
63
|
+
if (rc.ONE_SECRET) return rc.ONE_SECRET;
|
|
64
64
|
return readConfig()?.apiKey ?? null;
|
|
65
65
|
}
|
|
66
66
|
function getAccessControlFromAllSources() {
|
|
67
|
-
const rc =
|
|
67
|
+
const rc = readOneRc();
|
|
68
68
|
const fileAc = getAccessControl();
|
|
69
69
|
const merged = { ...fileAc };
|
|
70
|
-
if (rc.
|
|
71
|
-
merged.permissions = rc.
|
|
70
|
+
if (rc.ONE_PERMISSIONS) {
|
|
71
|
+
merged.permissions = rc.ONE_PERMISSIONS;
|
|
72
72
|
}
|
|
73
|
-
if (rc.
|
|
74
|
-
merged.connectionKeys = rc.
|
|
73
|
+
if (rc.ONE_CONNECTION_KEYS) {
|
|
74
|
+
merged.connectionKeys = rc.ONE_CONNECTION_KEYS.split(",").map((s) => s.trim()).filter(Boolean);
|
|
75
75
|
}
|
|
76
|
-
if (rc.
|
|
77
|
-
merged.actionIds = rc.
|
|
76
|
+
if (rc.ONE_ACTION_IDS) {
|
|
77
|
+
merged.actionIds = rc.ONE_ACTION_IDS.split(",").map((s) => s.trim()).filter(Boolean);
|
|
78
78
|
}
|
|
79
|
-
if (rc.
|
|
80
|
-
merged.knowledgeAgent = rc.
|
|
79
|
+
if (rc.ONE_KNOWLEDGE_AGENT) {
|
|
80
|
+
merged.knowledgeAgent = rc.ONE_KNOWLEDGE_AGENT === "true";
|
|
81
81
|
}
|
|
82
82
|
return merged;
|
|
83
83
|
}
|
|
@@ -247,20 +247,20 @@ function writeAgentConfig(agent, config, scope = "global") {
|
|
|
247
247
|
}
|
|
248
248
|
function getMcpServerConfig(apiKey, accessControl) {
|
|
249
249
|
const env = {
|
|
250
|
-
|
|
250
|
+
ONE_SECRET: apiKey
|
|
251
251
|
};
|
|
252
252
|
if (accessControl) {
|
|
253
253
|
if (accessControl.permissions && accessControl.permissions !== "admin") {
|
|
254
|
-
env.
|
|
254
|
+
env.ONE_PERMISSIONS = accessControl.permissions;
|
|
255
255
|
}
|
|
256
256
|
if (accessControl.connectionKeys && !(accessControl.connectionKeys.length === 1 && accessControl.connectionKeys[0] === "*")) {
|
|
257
|
-
env.
|
|
257
|
+
env.ONE_CONNECTION_KEYS = accessControl.connectionKeys.join(",");
|
|
258
258
|
}
|
|
259
259
|
if (accessControl.actionIds && !(accessControl.actionIds.length === 1 && accessControl.actionIds[0] === "*")) {
|
|
260
|
-
env.
|
|
260
|
+
env.ONE_ACTION_IDS = accessControl.actionIds.join(",");
|
|
261
261
|
}
|
|
262
262
|
if (accessControl.knowledgeAgent) {
|
|
263
|
-
env.
|
|
263
|
+
env.ONE_KNOWLEDGE_AGENT = "true";
|
|
264
264
|
}
|
|
265
265
|
}
|
|
266
266
|
return {
|
|
@@ -273,7 +273,7 @@ function installMcpConfig(agent, apiKey, scope = "global", accessControl) {
|
|
|
273
273
|
const config = readAgentConfig(agent, scope);
|
|
274
274
|
const configKey = agent.configKey;
|
|
275
275
|
const mcpServers = config[configKey] || {};
|
|
276
|
-
mcpServers["
|
|
276
|
+
mcpServers["one"] = getMcpServerConfig(apiKey, accessControl);
|
|
277
277
|
config[configKey] = mcpServers;
|
|
278
278
|
writeAgentConfig(agent, config, scope);
|
|
279
279
|
}
|
|
@@ -281,7 +281,7 @@ function isMcpInstalled(agent, scope = "global") {
|
|
|
281
281
|
const config = readAgentConfig(agent, scope);
|
|
282
282
|
const configKey = agent.configKey;
|
|
283
283
|
const mcpServers = config[configKey];
|
|
284
|
-
return mcpServers?.["
|
|
284
|
+
return mcpServers?.["one"] !== void 0;
|
|
285
285
|
}
|
|
286
286
|
function getAgentStatuses() {
|
|
287
287
|
return AGENTS.map((agent) => {
|
|
@@ -293,7 +293,7 @@ function getAgentStatuses() {
|
|
|
293
293
|
}
|
|
294
294
|
|
|
295
295
|
// src/lib/api.ts
|
|
296
|
-
var API_BASE = "https://api.
|
|
296
|
+
var API_BASE = "https://api.withone.ai/v1";
|
|
297
297
|
var ApiError = class extends Error {
|
|
298
298
|
constructor(status, message) {
|
|
299
299
|
super(message);
|
|
@@ -301,7 +301,7 @@ var ApiError = class extends Error {
|
|
|
301
301
|
this.name = "ApiError";
|
|
302
302
|
}
|
|
303
303
|
};
|
|
304
|
-
var
|
|
304
|
+
var OneApi = class {
|
|
305
305
|
constructor(apiKey) {
|
|
306
306
|
this.apiKey = apiKey;
|
|
307
307
|
}
|
|
@@ -315,7 +315,7 @@ var PicaApi = class {
|
|
|
315
315
|
url += `?${params.toString()}`;
|
|
316
316
|
}
|
|
317
317
|
const headers = {
|
|
318
|
-
"x-
|
|
318
|
+
"x-one-secret": this.apiKey,
|
|
319
319
|
"Content-Type": "application/json",
|
|
320
320
|
...opts.headers
|
|
321
321
|
};
|
|
@@ -406,9 +406,9 @@ var PicaApi = class {
|
|
|
406
406
|
const method = action.method;
|
|
407
407
|
const contentType = args.isFormData ? "multipart/form-data" : args.isFormUrlEncoded ? "application/x-www-form-urlencoded" : "application/json";
|
|
408
408
|
const requestHeaders = {
|
|
409
|
-
"x-
|
|
410
|
-
"x-
|
|
411
|
-
"x-
|
|
409
|
+
"x-one-secret": this.apiKey,
|
|
410
|
+
"x-one-connection-key": args.connectionKey,
|
|
411
|
+
"x-one-action-id": action._id,
|
|
412
412
|
"Content-Type": contentType,
|
|
413
413
|
...args.headers
|
|
414
414
|
};
|
|
@@ -476,7 +476,7 @@ var PicaApi = class {
|
|
|
476
476
|
method,
|
|
477
477
|
headers: {
|
|
478
478
|
...requestHeaders,
|
|
479
|
-
"x-
|
|
479
|
+
"x-one-secret": "***REDACTED***"
|
|
480
480
|
},
|
|
481
481
|
params: args.queryParams ? Object.fromEntries(
|
|
482
482
|
Object.entries(args.queryParams).map(([k, v]) => [k, String(v)])
|
|
@@ -562,7 +562,7 @@ function isActionAllowed(actionId, allowedActionIds) {
|
|
|
562
562
|
return allowedActionIds.includes("*") || allowedActionIds.includes(actionId);
|
|
563
563
|
}
|
|
564
564
|
function buildActionKnowledgeWithGuidance(knowledge, method, platform, actionId) {
|
|
565
|
-
const baseUrl = "https://api.
|
|
565
|
+
const baseUrl = "https://api.withone.ai";
|
|
566
566
|
return `${knowledge}
|
|
567
567
|
|
|
568
568
|
API REQUEST STRUCTURE
|
|
@@ -579,9 +579,9 @@ Examples:
|
|
|
579
579
|
METHOD: ${method}
|
|
580
580
|
|
|
581
581
|
HEADERS:
|
|
582
|
-
- x-
|
|
583
|
-
- x-
|
|
584
|
-
- x-
|
|
582
|
+
- x-one-secret: {{process.env.ONE_SECRET}}
|
|
583
|
+
- x-one-connection-key: {{process.env.ONE_${platform.toUpperCase()}_CONNECTION_KEY}}
|
|
584
|
+
- x-one-action-id: ${actionId}
|
|
585
585
|
- ... (other headers)
|
|
586
586
|
|
|
587
587
|
BODY: {{BODY}}
|
|
@@ -591,12 +591,12 @@ QUERY PARAMS: {{QUERY_PARAMS}}`;
|
|
|
591
591
|
|
|
592
592
|
// src/lib/browser.ts
|
|
593
593
|
import open from "open";
|
|
594
|
-
var
|
|
594
|
+
var ONE_APP_URL = "https://app.withone.ai";
|
|
595
595
|
function getConnectionUrl(platform) {
|
|
596
|
-
return `${
|
|
596
|
+
return `${ONE_APP_URL}/connections?#open=${platform}`;
|
|
597
597
|
}
|
|
598
598
|
function getApiKeyUrl() {
|
|
599
|
-
return `${
|
|
599
|
+
return `${ONE_APP_URL}/settings/api-keys`;
|
|
600
600
|
}
|
|
601
601
|
async function openConnectionPage(platform) {
|
|
602
602
|
const url = getConnectionUrl(platform);
|
|
@@ -617,7 +617,7 @@ function setAgentMode(value) {
|
|
|
617
617
|
_agentMode = value;
|
|
618
618
|
}
|
|
619
619
|
function isAgentMode() {
|
|
620
|
-
return _agentMode || process.env.
|
|
620
|
+
return _agentMode || process.env.ONE_AGENT === "1";
|
|
621
621
|
}
|
|
622
622
|
function createSpinner() {
|
|
623
623
|
if (isAgentMode()) {
|
|
@@ -655,10 +655,10 @@ async function configCommand() {
|
|
|
655
655
|
}
|
|
656
656
|
const config = readConfig();
|
|
657
657
|
if (!config) {
|
|
658
|
-
p2.log.error(`No
|
|
658
|
+
p2.log.error(`No One config found. Run ${pc.cyan("one init")} first.`);
|
|
659
659
|
return;
|
|
660
660
|
}
|
|
661
|
-
p2.intro(pc.bgCyan(pc.black("
|
|
661
|
+
p2.intro(pc.bgCyan(pc.black(" One Access Control ")));
|
|
662
662
|
const current = getAccessControl();
|
|
663
663
|
console.log();
|
|
664
664
|
console.log(` ${pc.bold("Current Access Control")}`);
|
|
@@ -701,7 +701,7 @@ async function configCommand() {
|
|
|
701
701
|
return;
|
|
702
702
|
}
|
|
703
703
|
if (connectionKeys.length === 0) {
|
|
704
|
-
p2.log.info(`No connections found. Defaulting to all. Use ${pc.cyan("
|
|
704
|
+
p2.log.info(`No connections found. Defaulting to all. Use ${pc.cyan("one add")} to connect platforms.`);
|
|
705
705
|
connectionKeys = void 0;
|
|
706
706
|
}
|
|
707
707
|
}
|
|
@@ -772,7 +772,7 @@ async function selectConnections(apiKey) {
|
|
|
772
772
|
spinner5.start("Fetching connections...");
|
|
773
773
|
let connections;
|
|
774
774
|
try {
|
|
775
|
-
const api = new
|
|
775
|
+
const api = new OneApi(apiKey);
|
|
776
776
|
const rawConnections = await api.listConnections();
|
|
777
777
|
connections = rawConnections.map((c) => ({ platform: c.platform, key: c.key }));
|
|
778
778
|
spinner5.stop(`Found ${connections.length} connection(s)`);
|
|
@@ -855,7 +855,7 @@ async function initCommand(options) {
|
|
|
855
855
|
}
|
|
856
856
|
const existingConfig = readConfig();
|
|
857
857
|
if (existingConfig) {
|
|
858
|
-
p3.intro(pc3.bgCyan(pc3.black("
|
|
858
|
+
p3.intro(pc3.bgCyan(pc3.black(" One ")));
|
|
859
859
|
await handleExistingConfig(existingConfig.apiKey, options);
|
|
860
860
|
return;
|
|
861
861
|
}
|
|
@@ -968,7 +968,7 @@ ${pc3.cyan(getApiKeyUrl())}`, "API Key");
|
|
|
968
968
|
await openApiKeyPage();
|
|
969
969
|
}
|
|
970
970
|
const newKey = await p3.text({
|
|
971
|
-
message: "Enter your new
|
|
971
|
+
message: "Enter your new One API key:",
|
|
972
972
|
placeholder: "sk_live_...",
|
|
973
973
|
validate: (value) => {
|
|
974
974
|
if (!value) return "API key is required";
|
|
@@ -984,7 +984,7 @@ ${pc3.cyan(getApiKeyUrl())}`, "API Key");
|
|
|
984
984
|
}
|
|
985
985
|
const spinner5 = p3.spinner();
|
|
986
986
|
spinner5.start("Validating API key...");
|
|
987
|
-
const api = new
|
|
987
|
+
const api = new OneApi(newKey);
|
|
988
988
|
const isValid = await api.validateApiKey();
|
|
989
989
|
if (!isValid) {
|
|
990
990
|
spinner5.stop("Invalid API key");
|
|
@@ -1021,7 +1021,7 @@ async function handleInstallMore(apiKey, missing) {
|
|
|
1021
1021
|
if (missing.length === 1) {
|
|
1022
1022
|
const agent = missing[0].agent;
|
|
1023
1023
|
const confirm3 = await p3.confirm({
|
|
1024
|
-
message: `Install
|
|
1024
|
+
message: `Install One MCP to ${agent.name}?`,
|
|
1025
1025
|
initialValue: true
|
|
1026
1026
|
});
|
|
1027
1027
|
if (p3.isCancel(confirm3) || !confirm3) {
|
|
@@ -1113,7 +1113,7 @@ ${pc3.cyan(getApiKeyUrl())}`, "API Key");
|
|
|
1113
1113
|
await openApiKeyPage();
|
|
1114
1114
|
}
|
|
1115
1115
|
const apiKey = await p3.text({
|
|
1116
|
-
message: "Enter your
|
|
1116
|
+
message: "Enter your One API key:",
|
|
1117
1117
|
placeholder: "sk_live_...",
|
|
1118
1118
|
validate: (value) => {
|
|
1119
1119
|
if (!value) return "API key is required";
|
|
@@ -1129,7 +1129,7 @@ ${pc3.cyan(getApiKeyUrl())}`, "API Key");
|
|
|
1129
1129
|
}
|
|
1130
1130
|
const spinner5 = p3.spinner();
|
|
1131
1131
|
spinner5.start("Validating API key...");
|
|
1132
|
-
const api = new
|
|
1132
|
+
const api = new OneApi(apiKey);
|
|
1133
1133
|
const isValid = await api.validateApiKey();
|
|
1134
1134
|
if (!isValid) {
|
|
1135
1135
|
spinner5.stop("Invalid API key");
|
|
@@ -1241,7 +1241,7 @@ ${globalPaths}
|
|
|
1241
1241
|
summary += pc3.yellow("Note: Project config files can be committed to share with your team.\n") + pc3.yellow("Team members will need their own API key.");
|
|
1242
1242
|
p3.note(summary, "Setup Complete");
|
|
1243
1243
|
await promptConnectIntegrations(apiKey);
|
|
1244
|
-
p3.outro("Your AI agents now have access to
|
|
1244
|
+
p3.outro("Your AI agents now have access to One integrations!");
|
|
1245
1245
|
return;
|
|
1246
1246
|
}
|
|
1247
1247
|
const installedAgentIds = [];
|
|
@@ -1262,20 +1262,20 @@ ${globalPaths}
|
|
|
1262
1262
|
"Setup Complete"
|
|
1263
1263
|
);
|
|
1264
1264
|
await promptConnectIntegrations(apiKey);
|
|
1265
|
-
p3.outro("Your AI agents now have access to
|
|
1265
|
+
p3.outro("Your AI agents now have access to One integrations!");
|
|
1266
1266
|
}
|
|
1267
1267
|
function printBanner() {
|
|
1268
1268
|
console.log();
|
|
1269
|
-
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588
|
|
1270
|
-
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588
|
|
1271
|
-
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588
|
|
1272
|
-
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588
|
|
1273
|
-
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588
|
|
1274
|
-
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588
|
|
1275
|
-
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588
|
|
1276
|
-
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588
|
|
1277
|
-
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588
|
|
1278
|
-
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588
|
|
1269
|
+
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
|
|
1270
|
+
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
|
|
1271
|
+
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
|
|
1272
|
+
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
|
|
1273
|
+
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 "));
|
|
1274
|
+
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 "));
|
|
1275
|
+
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
|
|
1276
|
+
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
|
|
1277
|
+
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
|
|
1278
|
+
console.log(pc3.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
|
|
1279
1279
|
console.log();
|
|
1280
1280
|
console.log(pc3.dim(" U N I V E R S A L I N T E G R A T I O N S F O R A I"));
|
|
1281
1281
|
console.log();
|
|
@@ -1286,7 +1286,7 @@ var TOP_INTEGRATIONS = [
|
|
|
1286
1286
|
{ value: "notion", label: "Notion", hint: "Access pages, databases, and docs" }
|
|
1287
1287
|
];
|
|
1288
1288
|
async function promptConnectIntegrations(apiKey) {
|
|
1289
|
-
const api = new
|
|
1289
|
+
const api = new OneApi(apiKey);
|
|
1290
1290
|
const connected = [];
|
|
1291
1291
|
try {
|
|
1292
1292
|
const existing = await api.listConnections();
|
|
@@ -1308,7 +1308,7 @@ async function promptConnectIntegrations(apiKey) {
|
|
|
1308
1308
|
hint: i.hint
|
|
1309
1309
|
})),
|
|
1310
1310
|
{ value: "more", label: "Browse all 200+ platforms" },
|
|
1311
|
-
{ value: "skip", label: "Skip for now", hint: "you can always run
|
|
1311
|
+
{ value: "skip", label: "Skip for now", hint: "you can always run one add later" }
|
|
1312
1312
|
];
|
|
1313
1313
|
const message = first ? "Connect your first integration?" : "Connect another?";
|
|
1314
1314
|
const choice = await p3.select({ message, options });
|
|
@@ -1317,12 +1317,12 @@ async function promptConnectIntegrations(apiKey) {
|
|
|
1317
1317
|
}
|
|
1318
1318
|
if (choice === "more") {
|
|
1319
1319
|
try {
|
|
1320
|
-
await open2("https://app.
|
|
1321
|
-
p3.log.info("Opened
|
|
1320
|
+
await open2("https://app.withone.ai/connections");
|
|
1321
|
+
p3.log.info("Opened One dashboard in browser.");
|
|
1322
1322
|
} catch {
|
|
1323
|
-
p3.note("https://app.
|
|
1323
|
+
p3.note("https://app.withone.ai/connections", "Open in browser");
|
|
1324
1324
|
}
|
|
1325
|
-
p3.log.info(`Connect from the dashboard, or use ${pc3.cyan("
|
|
1325
|
+
p3.log.info(`Connect from the dashboard, or use ${pc3.cyan("one add <platform>")}`);
|
|
1326
1326
|
break;
|
|
1327
1327
|
}
|
|
1328
1328
|
const platform = choice;
|
|
@@ -1347,7 +1347,7 @@ async function promptConnectIntegrations(apiKey) {
|
|
|
1347
1347
|
} catch (error2) {
|
|
1348
1348
|
spinner5.stop("Connection timed out");
|
|
1349
1349
|
if (error2 instanceof TimeoutError) {
|
|
1350
|
-
p3.log.warn(`No worries. Connect later with: ${pc3.cyan(`
|
|
1350
|
+
p3.log.warn(`No worries. Connect later with: ${pc3.cyan(`one add ${platform}`)}`);
|
|
1351
1351
|
}
|
|
1352
1352
|
first = false;
|
|
1353
1353
|
}
|
|
@@ -1414,13 +1414,13 @@ async function connectionAddCommand(platformArg) {
|
|
|
1414
1414
|
if (isAgentMode()) {
|
|
1415
1415
|
error("This command requires interactive input. Run without --agent.");
|
|
1416
1416
|
}
|
|
1417
|
-
p4.intro(pc4.bgCyan(pc4.black("
|
|
1417
|
+
p4.intro(pc4.bgCyan(pc4.black(" One ")));
|
|
1418
1418
|
const apiKey = getApiKey();
|
|
1419
1419
|
if (!apiKey) {
|
|
1420
|
-
p4.cancel("Not configured. Run `
|
|
1420
|
+
p4.cancel("Not configured. Run `one init` first.");
|
|
1421
1421
|
process.exit(1);
|
|
1422
1422
|
}
|
|
1423
|
-
const api = new
|
|
1423
|
+
const api = new OneApi(apiKey);
|
|
1424
1424
|
const spinner5 = p4.spinner();
|
|
1425
1425
|
spinner5.start("Loading platforms...");
|
|
1426
1426
|
let platforms;
|
|
@@ -1449,7 +1449,7 @@ async function connectionAddCommand(platformArg) {
|
|
|
1449
1449
|
]
|
|
1450
1450
|
});
|
|
1451
1451
|
if (p4.isCancel(suggestion) || suggestion === "__other__") {
|
|
1452
|
-
p4.note(`Run ${pc4.cyan("
|
|
1452
|
+
p4.note(`Run ${pc4.cyan("one platforms")} to see all available platforms.`);
|
|
1453
1453
|
p4.cancel("Connection cancelled.");
|
|
1454
1454
|
process.exit(0);
|
|
1455
1455
|
}
|
|
@@ -1457,7 +1457,7 @@ async function connectionAddCommand(platformArg) {
|
|
|
1457
1457
|
} else {
|
|
1458
1458
|
p4.cancel(`Unknown platform: ${platformArg}
|
|
1459
1459
|
|
|
1460
|
-
Run ${pc4.cyan("
|
|
1460
|
+
Run ${pc4.cyan("one platforms")} to see available platforms.`);
|
|
1461
1461
|
process.exit(1);
|
|
1462
1462
|
}
|
|
1463
1463
|
}
|
|
@@ -1480,7 +1480,7 @@ Run ${pc4.cyan("pica platforms")} to see available platforms.`);
|
|
|
1480
1480
|
} else {
|
|
1481
1481
|
p4.cancel(`Unknown platform: ${platformInput}
|
|
1482
1482
|
|
|
1483
|
-
Run ${pc4.cyan("
|
|
1483
|
+
Run ${pc4.cyan("one platforms")} to see available platforms.`);
|
|
1484
1484
|
process.exit(1);
|
|
1485
1485
|
}
|
|
1486
1486
|
}
|
|
@@ -1510,7 +1510,7 @@ ${url}`);
|
|
|
1510
1510
|
- Browser popup was blocked
|
|
1511
1511
|
- Wrong account selected
|
|
1512
1512
|
|
|
1513
|
-
Try again with: ${pc4.cyan(`
|
|
1513
|
+
Try again with: ${pc4.cyan(`one connection add ${platform}`)}`,
|
|
1514
1514
|
"Timed Out"
|
|
1515
1515
|
);
|
|
1516
1516
|
} else {
|
|
@@ -1522,9 +1522,9 @@ Try again with: ${pc4.cyan(`pica connection add ${platform}`)}`,
|
|
|
1522
1522
|
async function connectionListCommand() {
|
|
1523
1523
|
const apiKey = getApiKey();
|
|
1524
1524
|
if (!apiKey) {
|
|
1525
|
-
error("Not configured. Run `
|
|
1525
|
+
error("Not configured. Run `one init` first.");
|
|
1526
1526
|
}
|
|
1527
|
-
const api = new
|
|
1527
|
+
const api = new OneApi(apiKey);
|
|
1528
1528
|
const spinner5 = createSpinner();
|
|
1529
1529
|
spinner5.start("Loading connections...");
|
|
1530
1530
|
try {
|
|
@@ -1544,7 +1544,7 @@ async function connectionListCommand() {
|
|
|
1544
1544
|
p4.note(
|
|
1545
1545
|
`No connections yet.
|
|
1546
1546
|
|
|
1547
|
-
Add one with: ${pc4.cyan("
|
|
1547
|
+
Add one with: ${pc4.cyan("one connection add gmail")}`,
|
|
1548
1548
|
"No Connections"
|
|
1549
1549
|
);
|
|
1550
1550
|
return;
|
|
@@ -1566,7 +1566,7 @@ Add one with: ${pc4.cyan("pica connection add gmail")}`,
|
|
|
1566
1566
|
rows
|
|
1567
1567
|
);
|
|
1568
1568
|
console.log();
|
|
1569
|
-
p4.note(`Add more with: ${pc4.cyan("
|
|
1569
|
+
p4.note(`Add more with: ${pc4.cyan("one connection add <platform>")}`, "Tip");
|
|
1570
1570
|
} catch (error2) {
|
|
1571
1571
|
spinner5.stop("Failed to load connections");
|
|
1572
1572
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
@@ -1591,12 +1591,12 @@ import pc5 from "picocolors";
|
|
|
1591
1591
|
async function platformsCommand(options) {
|
|
1592
1592
|
const apiKey = getApiKey();
|
|
1593
1593
|
if (!apiKey) {
|
|
1594
|
-
error("Not configured. Run `
|
|
1594
|
+
error("Not configured. Run `one init` first.");
|
|
1595
1595
|
}
|
|
1596
1596
|
if (isAgentMode()) {
|
|
1597
1597
|
options.json = true;
|
|
1598
1598
|
}
|
|
1599
|
-
const api = new
|
|
1599
|
+
const api = new OneApi(apiKey);
|
|
1600
1600
|
const spinner5 = createSpinner();
|
|
1601
1601
|
spinner5.start("Loading platforms...");
|
|
1602
1602
|
try {
|
|
@@ -1655,7 +1655,7 @@ async function platformsCommand(options) {
|
|
|
1655
1655
|
);
|
|
1656
1656
|
}
|
|
1657
1657
|
console.log();
|
|
1658
|
-
p5.note(`Connect with: ${pc5.cyan("
|
|
1658
|
+
p5.note(`Connect with: ${pc5.cyan("one connection add <platform>")}`, "Tip");
|
|
1659
1659
|
} catch (error2) {
|
|
1660
1660
|
spinner5.stop("Failed to load platforms");
|
|
1661
1661
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
@@ -1668,7 +1668,7 @@ import pc6 from "picocolors";
|
|
|
1668
1668
|
function getConfig() {
|
|
1669
1669
|
const apiKey = getApiKey();
|
|
1670
1670
|
if (!apiKey) {
|
|
1671
|
-
error("Not configured. Run `
|
|
1671
|
+
error("Not configured. Run `one init` first.");
|
|
1672
1672
|
}
|
|
1673
1673
|
const ac = getAccessControlFromAllSources();
|
|
1674
1674
|
const permissions = ac.permissions || "admin";
|
|
@@ -1685,9 +1685,9 @@ function parseJsonArg(value, argName) {
|
|
|
1685
1685
|
}
|
|
1686
1686
|
}
|
|
1687
1687
|
async function actionsSearchCommand(platform, query, options) {
|
|
1688
|
-
intro2(pc6.bgCyan(pc6.black("
|
|
1688
|
+
intro2(pc6.bgCyan(pc6.black(" One ")));
|
|
1689
1689
|
const { apiKey, permissions, actionIds, knowledgeAgent } = getConfig();
|
|
1690
|
-
const api = new
|
|
1690
|
+
const api = new OneApi(apiKey);
|
|
1691
1691
|
const spinner5 = createSpinner();
|
|
1692
1692
|
spinner5.start(`Searching actions on ${pc6.cyan(platform)} for "${query}"...`);
|
|
1693
1693
|
try {
|
|
@@ -1713,7 +1713,7 @@ async function actionsSearchCommand(platform, query, options) {
|
|
|
1713
1713
|
Suggestions:
|
|
1714
1714
|
- Try a more general query (e.g., 'list', 'get', 'search', 'create')
|
|
1715
1715
|
- Verify the platform name is correct
|
|
1716
|
-
- Check available platforms with ${pc6.cyan("
|
|
1716
|
+
- Check available platforms with ${pc6.cyan("one platforms")}
|
|
1717
1717
|
|
|
1718
1718
|
Examples of good queries:
|
|
1719
1719
|
- "search contacts"
|
|
@@ -1745,8 +1745,8 @@ Examples of good queries:
|
|
|
1745
1745
|
);
|
|
1746
1746
|
console.log();
|
|
1747
1747
|
p6.note(
|
|
1748
|
-
`Get details: ${pc6.cyan(`
|
|
1749
|
-
Execute: ${pc6.cyan(`
|
|
1748
|
+
`Get details: ${pc6.cyan(`one actions knowledge ${platform} <actionId>`)}
|
|
1749
|
+
Execute: ${pc6.cyan(`one actions execute ${platform} <actionId> <connectionKey>`)}`,
|
|
1750
1750
|
"Next Steps"
|
|
1751
1751
|
);
|
|
1752
1752
|
} catch (error2) {
|
|
@@ -1757,9 +1757,9 @@ Execute: ${pc6.cyan(`pica actions execute ${platform} <actionId> <connection
|
|
|
1757
1757
|
}
|
|
1758
1758
|
}
|
|
1759
1759
|
async function actionsKnowledgeCommand(platform, actionId) {
|
|
1760
|
-
intro2(pc6.bgCyan(pc6.black("
|
|
1760
|
+
intro2(pc6.bgCyan(pc6.black(" One ")));
|
|
1761
1761
|
const { apiKey, actionIds, connectionKeys } = getConfig();
|
|
1762
|
-
const api = new
|
|
1762
|
+
const api = new OneApi(apiKey);
|
|
1763
1763
|
if (!isActionAllowed(actionId, actionIds)) {
|
|
1764
1764
|
error(`Action "${actionId}" is not in the allowed action list.`);
|
|
1765
1765
|
}
|
|
@@ -1800,7 +1800,7 @@ async function actionsKnowledgeCommand(platform, actionId) {
|
|
|
1800
1800
|
console.log(knowledgeWithGuidance);
|
|
1801
1801
|
console.log();
|
|
1802
1802
|
p6.note(
|
|
1803
|
-
`Execute: ${pc6.cyan(`
|
|
1803
|
+
`Execute: ${pc6.cyan(`one actions execute ${platform} ${actionId} <connectionKey>`)}`,
|
|
1804
1804
|
"Next Step"
|
|
1805
1805
|
);
|
|
1806
1806
|
} catch (error2) {
|
|
@@ -1811,7 +1811,7 @@ async function actionsKnowledgeCommand(platform, actionId) {
|
|
|
1811
1811
|
}
|
|
1812
1812
|
}
|
|
1813
1813
|
async function actionsExecuteCommand(platform, actionId, connectionKey, options) {
|
|
1814
|
-
intro2(pc6.bgCyan(pc6.black("
|
|
1814
|
+
intro2(pc6.bgCyan(pc6.black(" One ")));
|
|
1815
1815
|
const { apiKey, permissions, actionIds, connectionKeys, knowledgeAgent } = getConfig();
|
|
1816
1816
|
if (knowledgeAgent) {
|
|
1817
1817
|
error(
|
|
@@ -1824,7 +1824,7 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
|
|
|
1824
1824
|
if (!connectionKeys.includes("*") && !connectionKeys.includes(connectionKey)) {
|
|
1825
1825
|
error(`Connection key "${connectionKey}" is not allowed.`);
|
|
1826
1826
|
}
|
|
1827
|
-
const api = new
|
|
1827
|
+
const api = new OneApi(apiKey);
|
|
1828
1828
|
const spinner5 = createSpinner();
|
|
1829
1829
|
spinner5.start("Loading action details...");
|
|
1830
1830
|
try {
|
|
@@ -2845,7 +2845,7 @@ import fs5 from "fs";
|
|
|
2845
2845
|
function getConfig2() {
|
|
2846
2846
|
const apiKey = getApiKey();
|
|
2847
2847
|
if (!apiKey) {
|
|
2848
|
-
error("Not configured. Run `
|
|
2848
|
+
error("Not configured. Run `one init` first.");
|
|
2849
2849
|
}
|
|
2850
2850
|
const ac = getAccessControlFromAllSources();
|
|
2851
2851
|
const permissions = ac.permissions || "admin";
|
|
@@ -2892,7 +2892,7 @@ async function autoResolveConnectionInputs(flow2, inputs, api) {
|
|
|
2892
2892
|
return resolved;
|
|
2893
2893
|
}
|
|
2894
2894
|
async function flowCreateCommand(key, options) {
|
|
2895
|
-
intro2(pc7.bgCyan(pc7.black("
|
|
2895
|
+
intro2(pc7.bgCyan(pc7.black(" One Flow ")));
|
|
2896
2896
|
let flow2;
|
|
2897
2897
|
if (options.definition) {
|
|
2898
2898
|
try {
|
|
@@ -2932,13 +2932,13 @@ ${errors.map((e) => ` ${e.path}: ${e.message}`).join("\n")}`);
|
|
|
2932
2932
|
return;
|
|
2933
2933
|
}
|
|
2934
2934
|
note2(`Flow "${flow2.name}" saved to ${flowPath}`, "Created");
|
|
2935
|
-
outro2(`Validate: ${pc7.cyan(`
|
|
2936
|
-
Execute: ${pc7.cyan(`
|
|
2935
|
+
outro2(`Validate: ${pc7.cyan(`one flow validate ${flow2.key}`)}
|
|
2936
|
+
Execute: ${pc7.cyan(`one flow execute ${flow2.key}`)}`);
|
|
2937
2937
|
}
|
|
2938
2938
|
async function flowExecuteCommand(keyOrPath, options) {
|
|
2939
|
-
intro2(pc7.bgCyan(pc7.black("
|
|
2939
|
+
intro2(pc7.bgCyan(pc7.black(" One Flow ")));
|
|
2940
2940
|
const { apiKey, permissions, actionIds } = getConfig2();
|
|
2941
|
-
const api = new
|
|
2941
|
+
const api = new OneApi(apiKey);
|
|
2942
2942
|
const spinner5 = createSpinner();
|
|
2943
2943
|
spinner5.start(`Loading flow "${keyOrPath}"...`);
|
|
2944
2944
|
let flow2;
|
|
@@ -3035,14 +3035,14 @@ ${pc7.yellow("Pausing after current step completes...")} (run ID: ${runId})`);
|
|
|
3035
3035
|
}
|
|
3036
3036
|
}
|
|
3037
3037
|
async function flowListCommand() {
|
|
3038
|
-
intro2(pc7.bgCyan(pc7.black("
|
|
3038
|
+
intro2(pc7.bgCyan(pc7.black(" One Flow ")));
|
|
3039
3039
|
const flows = listFlows();
|
|
3040
3040
|
if (isAgentMode()) {
|
|
3041
3041
|
json({ flows });
|
|
3042
3042
|
return;
|
|
3043
3043
|
}
|
|
3044
3044
|
if (flows.length === 0) {
|
|
3045
|
-
note2("No flows found in .one/flows/\n\nCreate one with:
|
|
3045
|
+
note2("No flows found in .one/flows/\n\nCreate one with: one flow create", "Flows");
|
|
3046
3046
|
return;
|
|
3047
3047
|
}
|
|
3048
3048
|
console.log();
|
|
@@ -3065,7 +3065,7 @@ async function flowListCommand() {
|
|
|
3065
3065
|
console.log();
|
|
3066
3066
|
}
|
|
3067
3067
|
async function flowValidateCommand(keyOrPath) {
|
|
3068
|
-
intro2(pc7.bgCyan(pc7.black("
|
|
3068
|
+
intro2(pc7.bgCyan(pc7.black(" One Flow ")));
|
|
3069
3069
|
const spinner5 = createSpinner();
|
|
3070
3070
|
spinner5.start(`Validating "${keyOrPath}"...`);
|
|
3071
3071
|
let flowData;
|
|
@@ -3099,7 +3099,7 @@ async function flowValidateCommand(keyOrPath) {
|
|
|
3099
3099
|
note2(`Flow "${flowData.key}" passed all validation checks`, "Valid");
|
|
3100
3100
|
}
|
|
3101
3101
|
async function flowResumeCommand(runId) {
|
|
3102
|
-
intro2(pc7.bgCyan(pc7.black("
|
|
3102
|
+
intro2(pc7.bgCyan(pc7.black(" One Flow ")));
|
|
3103
3103
|
const state = FlowRunner.loadRunState(runId);
|
|
3104
3104
|
if (!state) {
|
|
3105
3105
|
error(`Run "${runId}" not found`);
|
|
@@ -3108,7 +3108,7 @@ async function flowResumeCommand(runId) {
|
|
|
3108
3108
|
error(`Run "${runId}" is ${state.status} \u2014 can only resume paused or failed runs`);
|
|
3109
3109
|
}
|
|
3110
3110
|
const { apiKey, permissions, actionIds } = getConfig2();
|
|
3111
|
-
const api = new
|
|
3111
|
+
const api = new OneApi(apiKey);
|
|
3112
3112
|
let flow2;
|
|
3113
3113
|
try {
|
|
3114
3114
|
flow2 = loadFlow(state.flowKey);
|
|
@@ -3150,7 +3150,7 @@ async function flowResumeCommand(runId) {
|
|
|
3150
3150
|
}
|
|
3151
3151
|
}
|
|
3152
3152
|
async function flowRunsCommand(flowKey) {
|
|
3153
|
-
intro2(pc7.bgCyan(pc7.black("
|
|
3153
|
+
intro2(pc7.bgCyan(pc7.black(" One Flow ")));
|
|
3154
3154
|
const runs = FlowRunner.listRuns(flowKey);
|
|
3155
3155
|
if (isAgentMode()) {
|
|
3156
3156
|
json({
|
|
@@ -3208,20 +3208,20 @@ function colorStatus(status) {
|
|
|
3208
3208
|
import pc8 from "picocolors";
|
|
3209
3209
|
|
|
3210
3210
|
// src/lib/guide-content.ts
|
|
3211
|
-
var GUIDE_OVERVIEW = `#
|
|
3211
|
+
var GUIDE_OVERVIEW = `# One CLI \u2014 Agent Guide
|
|
3212
3212
|
|
|
3213
3213
|
## Setup
|
|
3214
3214
|
|
|
3215
|
-
1. Run \`
|
|
3216
|
-
2. Run \`
|
|
3217
|
-
3. Run \`
|
|
3215
|
+
1. Run \`one init\` to configure your API key
|
|
3216
|
+
2. Run \`one add <platform>\` to connect platforms via OAuth
|
|
3217
|
+
3. Run \`one --agent connection list\` to verify connections
|
|
3218
3218
|
|
|
3219
3219
|
## The --agent Flag
|
|
3220
3220
|
|
|
3221
3221
|
Always use \`--agent\` for machine-readable JSON output. It disables colors, spinners, and interactive prompts.
|
|
3222
3222
|
|
|
3223
3223
|
\`\`\`bash
|
|
3224
|
-
|
|
3224
|
+
one --agent <command>
|
|
3225
3225
|
\`\`\`
|
|
3226
3226
|
|
|
3227
3227
|
All commands return JSON. If an \`error\` key is present, the command failed.
|
|
@@ -3236,23 +3236,23 @@ This guide has three sections you can request individually:
|
|
|
3236
3236
|
|
|
3237
3237
|
## Discovery Workflow
|
|
3238
3238
|
|
|
3239
|
-
1. \`
|
|
3240
|
-
2. \`
|
|
3241
|
-
3. \`
|
|
3242
|
-
4. \`
|
|
3239
|
+
1. \`one --agent connection list\` \u2014 See connected platforms and connection keys
|
|
3240
|
+
2. \`one --agent actions search <platform> <query>\` \u2014 Find actions
|
|
3241
|
+
3. \`one --agent actions knowledge <platform> <actionId>\` \u2014 Read full docs (REQUIRED before execute)
|
|
3242
|
+
4. \`one --agent actions execute <platform> <actionId> <connectionKey>\` \u2014 Execute the action
|
|
3243
3243
|
|
|
3244
3244
|
For multi-step workflows, use flows:
|
|
3245
3245
|
1. Discover actions with the workflow above
|
|
3246
3246
|
2. Build a flow JSON definition
|
|
3247
|
-
3. \`
|
|
3248
|
-
4. \`
|
|
3247
|
+
3. \`one --agent flow create <key> --definition '<json>'\`
|
|
3248
|
+
4. \`one --agent flow execute <key> -i param=value\`
|
|
3249
3249
|
|
|
3250
3250
|
Platform names are always kebab-case (e.g., \`hub-spot\`, \`google-calendar\`).
|
|
3251
|
-
Run \`
|
|
3251
|
+
Run \`one platforms\` to browse all 200+ available platforms.
|
|
3252
3252
|
`;
|
|
3253
|
-
var GUIDE_ACTIONS = `#
|
|
3253
|
+
var GUIDE_ACTIONS = `# One Actions CLI Workflow
|
|
3254
3254
|
|
|
3255
|
-
You have access to the
|
|
3255
|
+
You have access to the One CLI which lets you interact with 200+ third-party platforms through their APIs. The CLI handles authentication, request building, and execution through One's passthrough proxy.
|
|
3256
3256
|
|
|
3257
3257
|
## The Workflow
|
|
3258
3258
|
|
|
@@ -3270,7 +3270,7 @@ Never skip the knowledge step before executing \u2014 it contains critical infor
|
|
|
3270
3270
|
### 1. List Connections
|
|
3271
3271
|
|
|
3272
3272
|
\`\`\`bash
|
|
3273
|
-
|
|
3273
|
+
one --agent connection list
|
|
3274
3274
|
\`\`\`
|
|
3275
3275
|
|
|
3276
3276
|
Returns JSON with all connected platforms, their status, and connection keys. You need the **connection key** for executing actions, and the **platform name** (kebab-case) for searching actions.
|
|
@@ -3283,7 +3283,7 @@ Output format:
|
|
|
3283
3283
|
### 2. Search Actions
|
|
3284
3284
|
|
|
3285
3285
|
\`\`\`bash
|
|
3286
|
-
|
|
3286
|
+
one --agent actions search <platform> <query>
|
|
3287
3287
|
\`\`\`
|
|
3288
3288
|
|
|
3289
3289
|
Search for actions on a specific platform using natural language. Returns JSON with up to 5 matching actions including their action IDs, HTTP methods, and paths.
|
|
@@ -3296,7 +3296,7 @@ Options:
|
|
|
3296
3296
|
|
|
3297
3297
|
Example:
|
|
3298
3298
|
\`\`\`bash
|
|
3299
|
-
|
|
3299
|
+
one --agent actions search gmail "send email" -t execute
|
|
3300
3300
|
\`\`\`
|
|
3301
3301
|
|
|
3302
3302
|
Output format:
|
|
@@ -3307,7 +3307,7 @@ Output format:
|
|
|
3307
3307
|
### 3. Get Action Knowledge
|
|
3308
3308
|
|
|
3309
3309
|
\`\`\`bash
|
|
3310
|
-
|
|
3310
|
+
one --agent actions knowledge <platform> <actionId>
|
|
3311
3311
|
\`\`\`
|
|
3312
3312
|
|
|
3313
3313
|
Get comprehensive documentation for an action including parameters, requirements, validation rules, request/response structure, and examples. Returns JSON with the full API knowledge and HTTP method.
|
|
@@ -3316,7 +3316,7 @@ Always call this before executing \u2014 it tells you exactly what parameters ar
|
|
|
3316
3316
|
|
|
3317
3317
|
Example:
|
|
3318
3318
|
\`\`\`bash
|
|
3319
|
-
|
|
3319
|
+
one --agent actions knowledge gmail 67890abcdef
|
|
3320
3320
|
\`\`\`
|
|
3321
3321
|
|
|
3322
3322
|
Output format:
|
|
@@ -3327,14 +3327,14 @@ Output format:
|
|
|
3327
3327
|
### 4. Execute Action
|
|
3328
3328
|
|
|
3329
3329
|
\`\`\`bash
|
|
3330
|
-
|
|
3330
|
+
one --agent actions execute <platform> <actionId> <connectionKey> [options]
|
|
3331
3331
|
\`\`\`
|
|
3332
3332
|
|
|
3333
3333
|
Execute an action on a connected platform. Returns JSON with the request details and response data. You must have retrieved the knowledge for this action first.
|
|
3334
3334
|
|
|
3335
3335
|
- \`<platform>\` \u2014 Platform name in kebab-case
|
|
3336
3336
|
- \`<actionId>\` \u2014 Action ID from the search results
|
|
3337
|
-
- \`<connectionKey>\` \u2014 Connection key from \`
|
|
3337
|
+
- \`<connectionKey>\` \u2014 Connection key from \`one connection list\`
|
|
3338
3338
|
|
|
3339
3339
|
Options:
|
|
3340
3340
|
- \`-d, --data <json>\` \u2014 Request body as JSON string (for POST, PUT, PATCH)
|
|
@@ -3347,14 +3347,14 @@ Options:
|
|
|
3347
3347
|
Examples:
|
|
3348
3348
|
\`\`\`bash
|
|
3349
3349
|
# Simple GET request
|
|
3350
|
-
|
|
3350
|
+
one --agent actions execute shopify <actionId> <connectionKey>
|
|
3351
3351
|
|
|
3352
3352
|
# POST with data
|
|
3353
|
-
|
|
3353
|
+
one --agent actions execute hub-spot <actionId> <connectionKey> \\
|
|
3354
3354
|
-d '{"properties": {"email": "jane@example.com", "firstname": "Jane"}}'
|
|
3355
3355
|
|
|
3356
3356
|
# With path variables and query params
|
|
3357
|
-
|
|
3357
|
+
one --agent actions execute shopify <actionId> <connectionKey> \\
|
|
3358
3358
|
--path-vars '{"order_id": "12345"}' \\
|
|
3359
3359
|
--query-params '{"limit": "10"}'
|
|
3360
3360
|
\`\`\`
|
|
@@ -3381,18 +3381,18 @@ Parse the output as JSON. If the \`error\` key is present, the command failed \u
|
|
|
3381
3381
|
- Always read the knowledge output carefully \u2014 it tells you which parameters are required vs optional, what format they need to be in, and any caveats specific to that API
|
|
3382
3382
|
- JSON values passed to \`-d\`, \`--path-vars\`, \`--query-params\`, and \`--headers\` must be valid JSON strings (use single quotes around the JSON to avoid shell escaping issues)
|
|
3383
3383
|
- If search returns no results, try broader queries (e.g., \`"list"\` instead of \`"list active premium customers"\`)
|
|
3384
|
-
- The execute command respects access control settings configured via \`
|
|
3384
|
+
- The execute command respects access control settings configured via \`one config\` \u2014 if execution is blocked, the user may need to adjust their permissions
|
|
3385
3385
|
`;
|
|
3386
|
-
var GUIDE_FLOWS = `#
|
|
3386
|
+
var GUIDE_FLOWS = `# One Flow \u2014 Multi-Step API Workflows
|
|
3387
3387
|
|
|
3388
|
-
You have access to the
|
|
3388
|
+
You have access to the One CLI's flow engine, which lets you create and execute multi-step API workflows as JSON files. Flows chain actions across platforms \u2014 e.g., look up a Stripe customer, then send them a welcome email via Gmail.
|
|
3389
3389
|
|
|
3390
3390
|
## 1. Overview
|
|
3391
3391
|
|
|
3392
3392
|
- Flows are JSON files stored at \`.one/flows/<key>.flow.json\`
|
|
3393
3393
|
- All dynamic values (including connection keys) are declared as **inputs**
|
|
3394
3394
|
- Each flow has a unique **key** used to reference and execute it
|
|
3395
|
-
- Executed via \`
|
|
3395
|
+
- Executed via \`one --agent flow execute <key> -i name=value\`
|
|
3396
3396
|
|
|
3397
3397
|
## 2. Building a Flow \u2014 Step-by-Step Process
|
|
3398
3398
|
|
|
@@ -3401,7 +3401,7 @@ You have access to the Pica CLI's flow engine, which lets you create and execute
|
|
|
3401
3401
|
### Step 1: Discover connections
|
|
3402
3402
|
|
|
3403
3403
|
\`\`\`bash
|
|
3404
|
-
|
|
3404
|
+
one --agent connection list
|
|
3405
3405
|
\`\`\`
|
|
3406
3406
|
|
|
3407
3407
|
Find out which platforms are connected and get their connection keys.
|
|
@@ -3410,13 +3410,13 @@ Find out which platforms are connected and get their connection keys.
|
|
|
3410
3410
|
|
|
3411
3411
|
\`\`\`bash
|
|
3412
3412
|
# Find the action ID
|
|
3413
|
-
|
|
3413
|
+
one --agent actions search <platform> "<query>" -t execute
|
|
3414
3414
|
|
|
3415
3415
|
# Read the full docs \u2014 REQUIRED before adding to a flow
|
|
3416
|
-
|
|
3416
|
+
one --agent actions knowledge <platform> <actionId>
|
|
3417
3417
|
\`\`\`
|
|
3418
3418
|
|
|
3419
|
-
**CRITICAL:** You MUST call \`
|
|
3419
|
+
**CRITICAL:** You MUST call \`one actions knowledge\` for every action you include in the flow. The knowledge output tells you the exact request body structure, required fields, path variables, and query parameters. Without this, your flow JSON will have incorrect data shapes.
|
|
3420
3420
|
|
|
3421
3421
|
### Step 3: Construct the flow JSON
|
|
3422
3422
|
|
|
@@ -3428,7 +3428,7 @@ Using the knowledge gathered, build the flow JSON with:
|
|
|
3428
3428
|
### Step 4: Write the flow file
|
|
3429
3429
|
|
|
3430
3430
|
\`\`\`bash
|
|
3431
|
-
|
|
3431
|
+
one --agent flow create <key> --definition '<json>'
|
|
3432
3432
|
\`\`\`
|
|
3433
3433
|
|
|
3434
3434
|
Or write directly to \`.one/flows/<key>.flow.json\`.
|
|
@@ -3436,13 +3436,13 @@ Or write directly to \`.one/flows/<key>.flow.json\`.
|
|
|
3436
3436
|
### Step 5: Validate
|
|
3437
3437
|
|
|
3438
3438
|
\`\`\`bash
|
|
3439
|
-
|
|
3439
|
+
one --agent flow validate <key>
|
|
3440
3440
|
\`\`\`
|
|
3441
3441
|
|
|
3442
3442
|
### Step 6: Execute
|
|
3443
3443
|
|
|
3444
3444
|
\`\`\`bash
|
|
3445
|
-
|
|
3445
|
+
one --agent flow execute <key> -i connectionKey=xxx -i param=value
|
|
3446
3446
|
\`\`\`
|
|
3447
3447
|
|
|
3448
3448
|
## 3. Flow JSON Schema Reference
|
|
@@ -3457,13 +3457,13 @@ pica --agent flow execute <key> -i connectionKey=xxx -i param=value
|
|
|
3457
3457
|
"stripeConnectionKey": {
|
|
3458
3458
|
"type": "string",
|
|
3459
3459
|
"required": true,
|
|
3460
|
-
"description": "Stripe connection key from
|
|
3460
|
+
"description": "Stripe connection key from one connection list",
|
|
3461
3461
|
"connection": { "platform": "stripe" }
|
|
3462
3462
|
},
|
|
3463
3463
|
"gmailConnectionKey": {
|
|
3464
3464
|
"type": "string",
|
|
3465
3465
|
"required": true,
|
|
3466
|
-
"description": "Gmail connection key from
|
|
3466
|
+
"description": "Gmail connection key from one connection list",
|
|
3467
3467
|
"connection": { "platform": "gmail" }
|
|
3468
3468
|
},
|
|
3469
3469
|
"customerEmail": {
|
|
@@ -3524,7 +3524,7 @@ pica --agent flow execute <key> -i connectionKey=xxx -i param=value
|
|
|
3524
3524
|
|
|
3525
3525
|
## 5. Step Types Reference
|
|
3526
3526
|
|
|
3527
|
-
### \`action\` \u2014 Execute a
|
|
3527
|
+
### \`action\` \u2014 Execute a One API action
|
|
3528
3528
|
|
|
3529
3529
|
\`\`\`json
|
|
3530
3530
|
{
|
|
@@ -3710,10 +3710,10 @@ To modify an existing flow:
|
|
|
3710
3710
|
|
|
3711
3711
|
1. Read the flow JSON file at \`.one/flows/<key>.flow.json\`
|
|
3712
3712
|
2. Understand its current structure
|
|
3713
|
-
3. Use \`
|
|
3713
|
+
3. Use \`one --agent actions knowledge <platform> <actionId>\` for any new actions
|
|
3714
3714
|
4. Modify the JSON (add/remove/update steps, change data mappings, add inputs)
|
|
3715
3715
|
5. Write back the updated flow file
|
|
3716
|
-
6. Validate: \`
|
|
3716
|
+
6. Validate: \`one --agent flow validate <key>\`
|
|
3717
3717
|
|
|
3718
3718
|
## 8. Complete Examples
|
|
3719
3719
|
|
|
@@ -3932,38 +3932,38 @@ To modify an existing flow:
|
|
|
3932
3932
|
|
|
3933
3933
|
\`\`\`bash
|
|
3934
3934
|
# Create a flow
|
|
3935
|
-
|
|
3935
|
+
one --agent flow create <key> --definition '<json>'
|
|
3936
3936
|
|
|
3937
3937
|
# List all flows
|
|
3938
|
-
|
|
3938
|
+
one --agent flow list
|
|
3939
3939
|
|
|
3940
3940
|
# Validate a flow
|
|
3941
|
-
|
|
3941
|
+
one --agent flow validate <key>
|
|
3942
3942
|
|
|
3943
3943
|
# Execute a flow
|
|
3944
|
-
|
|
3944
|
+
one --agent flow execute <key> -i connectionKey=value -i param=value
|
|
3945
3945
|
|
|
3946
3946
|
# Execute with dry run (validate only)
|
|
3947
|
-
|
|
3947
|
+
one --agent flow execute <key> --dry-run -i connectionKey=value
|
|
3948
3948
|
|
|
3949
3949
|
# Execute with verbose output
|
|
3950
|
-
|
|
3950
|
+
one --agent flow execute <key> -v -i connectionKey=value
|
|
3951
3951
|
|
|
3952
3952
|
# List flow runs
|
|
3953
|
-
|
|
3953
|
+
one --agent flow runs [flowKey]
|
|
3954
3954
|
|
|
3955
3955
|
# Resume a paused/failed run
|
|
3956
|
-
|
|
3956
|
+
one --agent flow resume <runId>
|
|
3957
3957
|
\`\`\`
|
|
3958
3958
|
|
|
3959
3959
|
## Important Notes
|
|
3960
3960
|
|
|
3961
3961
|
- **Always use \`--agent\` flag** for structured JSON output
|
|
3962
|
-
- **Always call \`
|
|
3962
|
+
- **Always call \`one actions knowledge\`** before adding an action step to a flow
|
|
3963
3963
|
- Platform names are **kebab-case** (e.g., \`hub-spot\`, not \`HubSpot\`)
|
|
3964
3964
|
- Connection keys are **inputs**, not hardcoded \u2014 makes flows portable and shareable
|
|
3965
3965
|
- Use \`$.input.*\` for input values, \`$.steps.*\` for step results
|
|
3966
|
-
- Action IDs in examples (like \`STRIPE_SEARCH_CUSTOMERS_ACTION_ID\`) are placeholders \u2014 always use \`
|
|
3966
|
+
- Action IDs in examples (like \`STRIPE_SEARCH_CUSTOMERS_ACTION_ID\`) are placeholders \u2014 always use \`one actions search\` to find the real IDs
|
|
3967
3967
|
`;
|
|
3968
3968
|
var TOPICS = [
|
|
3969
3969
|
{ topic: "overview", description: "Setup, --agent flag, discovery workflow" },
|
|
@@ -3974,14 +3974,14 @@ var TOPICS = [
|
|
|
3974
3974
|
function getGuideContent(topic) {
|
|
3975
3975
|
switch (topic) {
|
|
3976
3976
|
case "overview":
|
|
3977
|
-
return { title: "
|
|
3977
|
+
return { title: "One CLI \u2014 Agent Guide: Overview", content: GUIDE_OVERVIEW };
|
|
3978
3978
|
case "actions":
|
|
3979
|
-
return { title: "
|
|
3979
|
+
return { title: "One CLI \u2014 Agent Guide: Actions", content: GUIDE_ACTIONS };
|
|
3980
3980
|
case "flows":
|
|
3981
|
-
return { title: "
|
|
3981
|
+
return { title: "One CLI \u2014 Agent Guide: Flows", content: GUIDE_FLOWS };
|
|
3982
3982
|
case "all":
|
|
3983
3983
|
return {
|
|
3984
|
-
title: "
|
|
3984
|
+
title: "One CLI \u2014 Agent Guide: Complete",
|
|
3985
3985
|
content: [GUIDE_OVERVIEW, GUIDE_ACTIONS, GUIDE_FLOWS].join("\n---\n\n")
|
|
3986
3986
|
};
|
|
3987
3987
|
}
|
|
@@ -4004,64 +4004,64 @@ async function guideCommand(topic = "all") {
|
|
|
4004
4004
|
json({ topic, title, content, availableTopics });
|
|
4005
4005
|
return;
|
|
4006
4006
|
}
|
|
4007
|
-
intro2(pc8.bgCyan(pc8.black("
|
|
4007
|
+
intro2(pc8.bgCyan(pc8.black(" One Guide ")));
|
|
4008
4008
|
console.log();
|
|
4009
4009
|
console.log(content);
|
|
4010
4010
|
console.log(pc8.dim("\u2500".repeat(60)));
|
|
4011
4011
|
console.log(
|
|
4012
4012
|
pc8.dim("Available topics: ") + availableTopics.map((t) => pc8.cyan(t.topic)).join(", ")
|
|
4013
4013
|
);
|
|
4014
|
-
console.log(pc8.dim(`Run ${pc8.cyan("
|
|
4014
|
+
console.log(pc8.dim(`Run ${pc8.cyan("one guide <topic>")} for a specific section.`));
|
|
4015
4015
|
}
|
|
4016
4016
|
|
|
4017
4017
|
// src/index.ts
|
|
4018
4018
|
var require2 = createRequire(import.meta.url);
|
|
4019
4019
|
var { version } = require2("../package.json");
|
|
4020
4020
|
var program = new Command();
|
|
4021
|
-
program.name("
|
|
4021
|
+
program.name("one").option("--agent", "Machine-readable JSON output (no colors, spinners, or prompts)").description(`One CLI \u2014 Connect AI agents to 200+ platforms through one interface.
|
|
4022
4022
|
|
|
4023
4023
|
Setup:
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4024
|
+
one init Set up API key and install MCP server
|
|
4025
|
+
one add <platform> Connect a platform via OAuth (e.g. gmail, slack, shopify)
|
|
4026
|
+
one config Configure access control (permissions, scoping)
|
|
4027
4027
|
|
|
4028
4028
|
Workflow (use these in order):
|
|
4029
|
-
1.
|
|
4030
|
-
2.
|
|
4031
|
-
3.
|
|
4032
|
-
4.
|
|
4029
|
+
1. one list List your connected platforms and connection keys
|
|
4030
|
+
2. one actions search <platform> <q> Search for actions using natural language
|
|
4031
|
+
3. one actions knowledge <plat> <id> Get full docs for an action (ALWAYS do this before execute)
|
|
4032
|
+
4. one actions execute <p> <id> <key> Execute the action
|
|
4033
4033
|
|
|
4034
4034
|
Guide:
|
|
4035
|
-
|
|
4035
|
+
one guide [topic] Full CLI guide (topics: overview, actions, flows, all)
|
|
4036
4036
|
|
|
4037
4037
|
Flows (multi-step workflows):
|
|
4038
|
-
|
|
4039
|
-
|
|
4040
|
-
|
|
4041
|
-
|
|
4038
|
+
one flow list List saved flows
|
|
4039
|
+
one flow create [key] Create a flow from JSON
|
|
4040
|
+
one flow execute <key> Execute a flow
|
|
4041
|
+
one flow validate <key> Validate a flow
|
|
4042
4042
|
|
|
4043
4043
|
Example \u2014 send an email through Gmail:
|
|
4044
|
-
$
|
|
4044
|
+
$ one list
|
|
4045
4045
|
# Find: gmail operational live::gmail::default::abc123
|
|
4046
4046
|
|
|
4047
|
-
$
|
|
4047
|
+
$ one actions search gmail "send email" -t execute
|
|
4048
4048
|
# Find: POST Send Email conn_mod_def::xxx::yyy
|
|
4049
4049
|
|
|
4050
|
-
$
|
|
4050
|
+
$ one actions knowledge gmail conn_mod_def::xxx::yyy
|
|
4051
4051
|
# Read the docs: required fields are to, subject, body, connectionKey
|
|
4052
4052
|
|
|
4053
|
-
$
|
|
4053
|
+
$ one actions execute gmail conn_mod_def::xxx::yyy live::gmail::default::abc123 \\
|
|
4054
4054
|
-d '{"to":"j@example.com","subject":"Hello","body":"Hi!","connectionKey":"live::gmail::default::abc123"}'
|
|
4055
4055
|
|
|
4056
4056
|
Platform names are always kebab-case (e.g. hub-spot, ship-station, google-calendar).
|
|
4057
|
-
Run '
|
|
4057
|
+
Run 'one platforms' to browse all 200+ available platforms.`).version(version);
|
|
4058
4058
|
program.hook("preAction", (thisCommand) => {
|
|
4059
4059
|
const opts = program.opts();
|
|
4060
4060
|
if (opts.agent) {
|
|
4061
4061
|
setAgentMode(true);
|
|
4062
4062
|
}
|
|
4063
4063
|
});
|
|
4064
|
-
program.command("init").description("Set up
|
|
4064
|
+
program.command("init").description("Set up One and install MCP to your AI agents").option("-y, --yes", "Skip confirmations").option("-g, --global", "Install MCP globally (available in all projects)").option("-p, --project", "Install MCP for this project only (creates .mcp.json)").action(async (options) => {
|
|
4065
4065
|
await initCommand(options);
|
|
4066
4066
|
});
|
|
4067
4067
|
program.command("config").description("Configure MCP access control (permissions, connections, actions)").action(async () => {
|
|
@@ -4078,13 +4078,13 @@ program.command("platforms").alias("p").description("List available platforms").
|
|
|
4078
4078
|
await platformsCommand(options);
|
|
4079
4079
|
});
|
|
4080
4080
|
var actions = program.command("actions").alias("a").description("Search, explore, and execute platform actions (workflow: search \u2192 knowledge \u2192 execute)");
|
|
4081
|
-
actions.command("search <platform> <query>").description('Search for actions on a platform (e.g.
|
|
4081
|
+
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").action(async (platform, query, options) => {
|
|
4082
4082
|
await actionsSearchCommand(platform, query, options);
|
|
4083
4083
|
});
|
|
4084
4084
|
actions.command("knowledge <platform> <actionId>").alias("k").description("Get full docs for an action \u2014 MUST call before execute to know required params").action(async (platform, actionId) => {
|
|
4085
4085
|
await actionsKnowledgeCommand(platform, actionId);
|
|
4086
4086
|
});
|
|
4087
|
-
actions.command("execute <platform> <actionId> <connectionKey>").alias("x").description('Execute an action \u2014 pass connectionKey from "
|
|
4087
|
+
actions.command("execute <platform> <actionId> <connectionKey>").alias("x").description('Execute an action \u2014 pass connectionKey from "one list", actionId from "actions search"').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").action(async (platform, actionId, connectionKey, options) => {
|
|
4088
4088
|
await actionsExecuteCommand(platform, actionId, connectionKey, {
|
|
4089
4089
|
data: options.data,
|
|
4090
4090
|
pathVars: options.pathVars,
|
|
@@ -4095,7 +4095,7 @@ actions.command("execute <platform> <actionId> <connectionKey>").alias("x").desc
|
|
|
4095
4095
|
});
|
|
4096
4096
|
});
|
|
4097
4097
|
var flow = program.command("flow").alias("f").description("Create, execute, and manage multi-step API workflows");
|
|
4098
|
-
flow.command("create [key]").description("Create a new flow from JSON definition").option("--definition <json>", "Flow definition as JSON string").option("-o, --output <path>", "Custom output path (default
|
|
4098
|
+
flow.command("create [key]").description("Create a new flow from JSON definition").option("--definition <json>", "Flow definition as JSON string").option("-o, --output <path>", "Custom output path (default .one/flows/<key>.flow.json)").action(async (key, options) => {
|
|
4099
4099
|
await flowCreateCommand(key, options);
|
|
4100
4100
|
});
|
|
4101
4101
|
flow.command("execute <keyOrPath>").alias("x").description("Execute a flow by key or file path").option("-i, --input <name=value>", "Input parameter (repeatable)", collect, []).option("--dry-run", "Validate and show execution plan without running").option("-v, --verbose", "Show full request/response for each step").action(async (keyOrPath, options) => {
|