@withone/cli 1.34.0 → 1.35.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 +8 -1
- package/dist/index.js +763 -340
- package/package.json +1 -1
- package/skills/one/SKILL.md +9 -0
package/dist/index.js
CHANGED
|
@@ -27,7 +27,7 @@ import path16 from "path";
|
|
|
27
27
|
import { Command } from "commander";
|
|
28
28
|
|
|
29
29
|
// src/commands/init.ts
|
|
30
|
-
import * as
|
|
30
|
+
import * as p4 from "@clack/prompts";
|
|
31
31
|
import pc2 from "picocolors";
|
|
32
32
|
import fs4 from "fs";
|
|
33
33
|
import path4 from "path";
|
|
@@ -265,11 +265,11 @@ import fs2 from "fs";
|
|
|
265
265
|
import path2 from "path";
|
|
266
266
|
import os2 from "os";
|
|
267
267
|
import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
|
|
268
|
-
function expandPath(
|
|
269
|
-
if (
|
|
270
|
-
return path2.join(os2.homedir(),
|
|
268
|
+
function expandPath(p10) {
|
|
269
|
+
if (p10.startsWith("~/")) {
|
|
270
|
+
return path2.join(os2.homedir(), p10.slice(2));
|
|
271
271
|
}
|
|
272
|
-
return
|
|
272
|
+
return p10;
|
|
273
273
|
}
|
|
274
274
|
function getClaudeDesktopConfigPath() {
|
|
275
275
|
switch (process.platform) {
|
|
@@ -459,6 +459,13 @@ async function openConnectionPage(platform, params) {
|
|
|
459
459
|
async function openApiKeyPage() {
|
|
460
460
|
await open(getApiKeyUrl());
|
|
461
461
|
}
|
|
462
|
+
function getCliAuthUrl(port, state) {
|
|
463
|
+
return `${ONE_APP_URL}/cli/auth?port=${port}&state=${encodeURIComponent(state)}`;
|
|
464
|
+
}
|
|
465
|
+
async function openCliAuthPage(port, state) {
|
|
466
|
+
const url = getCliAuthUrl(port, state);
|
|
467
|
+
await open(url);
|
|
468
|
+
}
|
|
462
469
|
|
|
463
470
|
// src/commands/config.ts
|
|
464
471
|
import * as p2 from "@clack/prompts";
|
|
@@ -649,24 +656,24 @@ async function configCommand() {
|
|
|
649
656
|
p2.outro("No changes made.");
|
|
650
657
|
return;
|
|
651
658
|
}
|
|
652
|
-
const
|
|
653
|
-
|
|
659
|
+
const spinner6 = p2.spinner();
|
|
660
|
+
spinner6.start("Validating API key...");
|
|
654
661
|
let isValid = false;
|
|
655
662
|
try {
|
|
656
663
|
const api = new OneApi(apiKey, `${normalized}/v1`);
|
|
657
664
|
isValid = await api.validateApiKey();
|
|
658
665
|
} catch (err) {
|
|
659
|
-
|
|
666
|
+
spinner6.stop("Connection failed");
|
|
660
667
|
const msg = err instanceof Error ? err.message : String(err);
|
|
661
668
|
p2.log.error(`Could not reach ${pc.cyan(normalized)}: ${msg}`);
|
|
662
669
|
return;
|
|
663
670
|
}
|
|
664
671
|
if (!isValid) {
|
|
665
|
-
|
|
672
|
+
spinner6.stop("Invalid API key");
|
|
666
673
|
p2.log.error(`Invalid API key for ${pc.cyan(normalized)}.`);
|
|
667
674
|
return;
|
|
668
675
|
}
|
|
669
|
-
|
|
676
|
+
spinner6.stop("API key validated");
|
|
670
677
|
updateApiBase(normalized);
|
|
671
678
|
newApiKey = apiKey;
|
|
672
679
|
} else if (isCustomBase) {
|
|
@@ -685,24 +692,24 @@ async function configCommand() {
|
|
|
685
692
|
p2.outro("No changes made.");
|
|
686
693
|
return;
|
|
687
694
|
}
|
|
688
|
-
const
|
|
689
|
-
|
|
695
|
+
const spinner6 = p2.spinner();
|
|
696
|
+
spinner6.start("Validating API key...");
|
|
690
697
|
let isValid = false;
|
|
691
698
|
try {
|
|
692
699
|
const api = new OneApi(apiKey, "https://api.withone.ai/v1");
|
|
693
700
|
isValid = await api.validateApiKey();
|
|
694
701
|
} catch (err) {
|
|
695
|
-
|
|
702
|
+
spinner6.stop("Connection failed");
|
|
696
703
|
const msg = err instanceof Error ? err.message : String(err);
|
|
697
704
|
p2.log.error(`Could not reach ${pc.cyan("https://api.withone.ai")}: ${msg}`);
|
|
698
705
|
return;
|
|
699
706
|
}
|
|
700
707
|
if (!isValid) {
|
|
701
|
-
|
|
708
|
+
spinner6.stop("Invalid API key");
|
|
702
709
|
p2.log.error(`Invalid API key. Get a valid key at ${getApiKeyUrl()}`);
|
|
703
710
|
return;
|
|
704
711
|
}
|
|
705
|
-
|
|
712
|
+
spinner6.stop("API key validated");
|
|
706
713
|
updateApiBase(null);
|
|
707
714
|
newApiKey = apiKey;
|
|
708
715
|
}
|
|
@@ -738,16 +745,16 @@ async function configCommand() {
|
|
|
738
745
|
p2.outro("Configuration updated.");
|
|
739
746
|
}
|
|
740
747
|
async function selectConnections(apiKey) {
|
|
741
|
-
const
|
|
742
|
-
|
|
748
|
+
const spinner6 = p2.spinner();
|
|
749
|
+
spinner6.start("Fetching connections...");
|
|
743
750
|
let connections;
|
|
744
751
|
try {
|
|
745
752
|
const api = new OneApi(apiKey, getApiBase());
|
|
746
753
|
const rawConnections = await api.listConnections();
|
|
747
754
|
connections = rawConnections.map((c) => ({ platform: c.platform, key: c.key }));
|
|
748
|
-
|
|
755
|
+
spinner6.stop(`Found ${connections.length} connection(s)`);
|
|
749
756
|
} catch {
|
|
750
|
-
|
|
757
|
+
spinner6.stop("Could not fetch connections");
|
|
751
758
|
const manual = await p2.text({
|
|
752
759
|
message: "Enter connection keys manually (comma-separated):",
|
|
753
760
|
placeholder: "conn_key_1, conn_key_2",
|
|
@@ -996,6 +1003,224 @@ function getSkillStatus() {
|
|
|
996
1003
|
};
|
|
997
1004
|
}
|
|
998
1005
|
|
|
1006
|
+
// src/commands/login.ts
|
|
1007
|
+
import http from "http";
|
|
1008
|
+
import crypto from "crypto";
|
|
1009
|
+
import * as p3 from "@clack/prompts";
|
|
1010
|
+
var LOGIN_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
1011
|
+
var PORT_RANGE_START = 49152;
|
|
1012
|
+
var PORT_RANGE_END = 65535;
|
|
1013
|
+
var MAX_PORT_ATTEMPTS = 5;
|
|
1014
|
+
var SUCCESS_HTML = `<!DOCTYPE html>
|
|
1015
|
+
<html><head><title>One CLI</title></head>
|
|
1016
|
+
<body style="font-family:system-ui;display:flex;justify-content:center;align-items:center;height:100vh;margin:0;background:#0a0a0a;color:#fafafa">
|
|
1017
|
+
<div style="text-align:center">
|
|
1018
|
+
<div style="width:48px;height:48px;border-radius:50%;background:rgba(34,197,94,0.1);display:flex;align-items:center;justify-content:center;margin:0 auto 16px">
|
|
1019
|
+
<svg width="24" height="24" fill="none" stroke="#22c55e" stroke-width="2" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" d="M5 13l4 4L19 7"/></svg>
|
|
1020
|
+
</div>
|
|
1021
|
+
<h1 style="font-size:20px;margin:0 0 8px">You're all set!</h1>
|
|
1022
|
+
<p style="color:#a1a1aa;font-size:14px">Return to your terminal. You can close this tab.</p>
|
|
1023
|
+
</div></body></html>`;
|
|
1024
|
+
function randomPort() {
|
|
1025
|
+
return PORT_RANGE_START + Math.floor(Math.random() * (PORT_RANGE_END - PORT_RANGE_START));
|
|
1026
|
+
}
|
|
1027
|
+
function startCallbackServer(expectedState) {
|
|
1028
|
+
return new Promise((resolveSetup, rejectSetup) => {
|
|
1029
|
+
let attempts = 0;
|
|
1030
|
+
function tryListen() {
|
|
1031
|
+
const port = randomPort();
|
|
1032
|
+
attempts++;
|
|
1033
|
+
let resolveResult;
|
|
1034
|
+
const result = new Promise((res) => {
|
|
1035
|
+
resolveResult = res;
|
|
1036
|
+
});
|
|
1037
|
+
const server = http.createServer((req, res) => {
|
|
1038
|
+
const url = new URL(req.url || "/", `http://localhost:${port}`);
|
|
1039
|
+
if (url.pathname !== "/callback") {
|
|
1040
|
+
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
1041
|
+
res.end("Not found");
|
|
1042
|
+
return;
|
|
1043
|
+
}
|
|
1044
|
+
const encodedKey = url.searchParams.get("s");
|
|
1045
|
+
const state = url.searchParams.get("state");
|
|
1046
|
+
const apiKey = encodedKey ? Buffer.from(encodedKey, "base64").toString("utf-8") : null;
|
|
1047
|
+
if (!apiKey || !state) {
|
|
1048
|
+
res.writeHead(400, { "Content-Type": "text/plain" });
|
|
1049
|
+
res.end("Missing required parameters");
|
|
1050
|
+
return;
|
|
1051
|
+
}
|
|
1052
|
+
if (state !== expectedState) {
|
|
1053
|
+
res.writeHead(403, { "Content-Type": "text/plain" });
|
|
1054
|
+
res.end("State mismatch");
|
|
1055
|
+
return;
|
|
1056
|
+
}
|
|
1057
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
1058
|
+
res.end(SUCCESS_HTML);
|
|
1059
|
+
resolveResult({ apiKey, state });
|
|
1060
|
+
});
|
|
1061
|
+
server.on("error", (err) => {
|
|
1062
|
+
if (err.code === "EADDRINUSE" && attempts < MAX_PORT_ATTEMPTS) {
|
|
1063
|
+
tryListen();
|
|
1064
|
+
return;
|
|
1065
|
+
}
|
|
1066
|
+
rejectSetup(err);
|
|
1067
|
+
});
|
|
1068
|
+
server.listen(port, "127.0.0.1", () => {
|
|
1069
|
+
resolveSetup({ server, port, result });
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
tryListen();
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
async function browserLogin() {
|
|
1076
|
+
const state = crypto.randomUUID();
|
|
1077
|
+
const spin = p3.spinner();
|
|
1078
|
+
let server;
|
|
1079
|
+
let port;
|
|
1080
|
+
let resultPromise;
|
|
1081
|
+
try {
|
|
1082
|
+
({ server, port, result: resultPromise } = await startCallbackServer(state));
|
|
1083
|
+
} catch {
|
|
1084
|
+
error("Could not start local server. Try: one init");
|
|
1085
|
+
return null;
|
|
1086
|
+
}
|
|
1087
|
+
const authUrl = getCliAuthUrl(port, state);
|
|
1088
|
+
p3.note(
|
|
1089
|
+
`If the browser doesn't open, visit:
|
|
1090
|
+
${authUrl}`,
|
|
1091
|
+
"Opening browser for authentication..."
|
|
1092
|
+
);
|
|
1093
|
+
try {
|
|
1094
|
+
await openCliAuthPage(port, state);
|
|
1095
|
+
} catch {
|
|
1096
|
+
}
|
|
1097
|
+
spin.start("Waiting for authentication... (timeout: 5 min)");
|
|
1098
|
+
const timeout = new Promise((_, reject) => {
|
|
1099
|
+
const timer = setTimeout(() => {
|
|
1100
|
+
reject(new Error("timeout"));
|
|
1101
|
+
}, LOGIN_TIMEOUT_MS);
|
|
1102
|
+
timer.unref();
|
|
1103
|
+
});
|
|
1104
|
+
try {
|
|
1105
|
+
const payload = await Promise.race([resultPromise, timeout]);
|
|
1106
|
+
spin.stop("Authentication received!");
|
|
1107
|
+
const apiBase = getApiBase();
|
|
1108
|
+
const api = new OneApi(payload.apiKey, apiBase);
|
|
1109
|
+
const whoami = await api.whoami();
|
|
1110
|
+
return { apiKey: payload.apiKey, whoami };
|
|
1111
|
+
} catch (err) {
|
|
1112
|
+
spin.stop("Authentication failed.");
|
|
1113
|
+
if (err instanceof Error && err.message === "timeout") {
|
|
1114
|
+
error("Authentication timed out (5 min). Try again with: one login");
|
|
1115
|
+
} else if (err instanceof ApiError) {
|
|
1116
|
+
error(`Authentication failed: ${err.message}`);
|
|
1117
|
+
} else {
|
|
1118
|
+
error("Authentication failed. Try: one init");
|
|
1119
|
+
}
|
|
1120
|
+
return null;
|
|
1121
|
+
} finally {
|
|
1122
|
+
server.closeAllConnections();
|
|
1123
|
+
server.close();
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
function saveCredentials(apiKey, scope) {
|
|
1127
|
+
const existing = scope === "project" ? readProjectConfig() : readGlobalConfig();
|
|
1128
|
+
writeConfig({
|
|
1129
|
+
apiKey,
|
|
1130
|
+
installedAgents: existing?.installedAgents ?? [],
|
|
1131
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1132
|
+
accessControl: existing?.accessControl,
|
|
1133
|
+
cacheTtl: existing?.cacheTtl,
|
|
1134
|
+
apiBase: existing?.apiBase
|
|
1135
|
+
}, scope);
|
|
1136
|
+
}
|
|
1137
|
+
async function loginCommand() {
|
|
1138
|
+
if (isAgentMode()) {
|
|
1139
|
+
json({ error: "Browser login not available in agent mode. Use: one init" });
|
|
1140
|
+
return;
|
|
1141
|
+
}
|
|
1142
|
+
let targetScope = "global";
|
|
1143
|
+
const existingKey = getApiKey();
|
|
1144
|
+
if (existingKey) {
|
|
1145
|
+
const pc13 = (await import("picocolors")).default;
|
|
1146
|
+
const resolved2 = resolveConfig();
|
|
1147
|
+
const whoami2 = resolved2.config?.whoami;
|
|
1148
|
+
const env2 = getEnvFromApiKey(existingKey);
|
|
1149
|
+
const envLabel2 = env2 === "test" ? pc13.yellow("test") : pc13.green("live");
|
|
1150
|
+
const currentScope = resolved2.scope === "project" ? pc13.cyan("local config") : pc13.magenta("global config");
|
|
1151
|
+
const lines = ["You are already logged in.", ""];
|
|
1152
|
+
if (whoami2) {
|
|
1153
|
+
const contextParts2 = [];
|
|
1154
|
+
if (whoami2.organization) contextParts2.push(whoami2.organization.name);
|
|
1155
|
+
if (whoami2.project) contextParts2.push(whoami2.project.name);
|
|
1156
|
+
const scopeDisplay2 = contextParts2.length > 0 ? contextParts2.join(" / ") : "Personal";
|
|
1157
|
+
lines.push(`${pc13.bold(scopeDisplay2)} ${pc13.dim("\xB7")} ${envLabel2}`);
|
|
1158
|
+
lines.push(`${whoami2.user.name} ${pc13.dim(`(${whoami2.user.email})`)}`);
|
|
1159
|
+
if (whoami2.organization) lines.push(`${pc13.dim("Org:")} ${whoami2.organization.name}`);
|
|
1160
|
+
if (whoami2.project) lines.push(`${pc13.dim("Project:")} ${whoami2.project.name}`);
|
|
1161
|
+
}
|
|
1162
|
+
lines.push("");
|
|
1163
|
+
lines.push(`${pc13.dim("Stored in")} ${currentScope}`);
|
|
1164
|
+
p3.note(lines.join("\n"));
|
|
1165
|
+
const scopeChoice = await p3.select({
|
|
1166
|
+
message: "Where would you like to log in?",
|
|
1167
|
+
options: [
|
|
1168
|
+
{ value: "global", label: "Globally", hint: "applies everywhere" },
|
|
1169
|
+
{ value: "project", label: "This directory", hint: "only this project" }
|
|
1170
|
+
]
|
|
1171
|
+
});
|
|
1172
|
+
if (p3.isCancel(scopeChoice)) {
|
|
1173
|
+
p3.cancel("Login cancelled.");
|
|
1174
|
+
return;
|
|
1175
|
+
}
|
|
1176
|
+
targetScope = scopeChoice;
|
|
1177
|
+
}
|
|
1178
|
+
const result = await browserLogin();
|
|
1179
|
+
if (!result) return;
|
|
1180
|
+
const { apiKey, whoami } = result;
|
|
1181
|
+
saveCredentials(apiKey, targetScope);
|
|
1182
|
+
const resolved = resolveConfig();
|
|
1183
|
+
if (resolved.config) {
|
|
1184
|
+
writeConfig({ ...resolved.config, whoami }, targetScope);
|
|
1185
|
+
}
|
|
1186
|
+
const pc12 = (await import("picocolors")).default;
|
|
1187
|
+
const env = getEnvFromApiKey(apiKey);
|
|
1188
|
+
const contextParts = [];
|
|
1189
|
+
if (whoami.organization) contextParts.push(whoami.organization.name);
|
|
1190
|
+
if (whoami.project) contextParts.push(whoami.project.name);
|
|
1191
|
+
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
1192
|
+
const envLabel = env === "test" ? pc12.yellow("test") : pc12.green("live");
|
|
1193
|
+
const configLabel = targetScope === "project" ? pc12.cyan("local config") : pc12.magenta("global config");
|
|
1194
|
+
const infoLines = [
|
|
1195
|
+
`${pc12.bold(scopeDisplay)} ${pc12.dim("\xB7")} ${envLabel}`,
|
|
1196
|
+
`${whoami.user.name} ${pc12.dim(`(${whoami.user.email})`)}`
|
|
1197
|
+
];
|
|
1198
|
+
if (whoami.organization) infoLines.push(`${pc12.dim("Org:")} ${whoami.organization.name}`);
|
|
1199
|
+
if (whoami.project) infoLines.push(`${pc12.dim("Project:")} ${whoami.project.name}`);
|
|
1200
|
+
infoLines.push("");
|
|
1201
|
+
infoLines.push(`${pc12.dim("Stored in")} ${configLabel}`);
|
|
1202
|
+
p3.note(infoLines.join("\n"), "Logged in");
|
|
1203
|
+
console.log();
|
|
1204
|
+
console.log(` ${pc12.dim("Next steps:")}`);
|
|
1205
|
+
console.log(` ${pc12.cyan("one add <platform>")} ${pc12.dim("\u2014")} Connect a platform (e.g. gmail, slack, stripe)`);
|
|
1206
|
+
console.log();
|
|
1207
|
+
console.log(pc12.bold(" Copy-paste this to your AI agent:"));
|
|
1208
|
+
console.log();
|
|
1209
|
+
console.log(pc12.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"));
|
|
1210
|
+
console.log(pc12.cyan(" \u2502"));
|
|
1211
|
+
console.log(pc12.cyan(" \u2502 The One CLI (`one`) is now installed on this machine. It"));
|
|
1212
|
+
console.log(pc12.cyan(" \u2502 lets you interact with 250+ third-party platforms (Gmail,"));
|
|
1213
|
+
console.log(pc12.cyan(" \u2502 Slack, Shopify, HubSpot, Stripe, GitHub, etc.) through"));
|
|
1214
|
+
console.log(pc12.cyan(" \u2502 their APIs. Whenever you need to interact with any"));
|
|
1215
|
+
console.log(pc12.cyan(" \u2502 third-party platform or external service, use the `one`"));
|
|
1216
|
+
console.log(pc12.cyan(" \u2502 skill. Please save this to your project instructions or"));
|
|
1217
|
+
console.log(pc12.cyan(" \u2502 memory so you remember it in future conversations."));
|
|
1218
|
+
console.log(pc12.cyan(" \u2502"));
|
|
1219
|
+
console.log(pc12.cyan(" \u2514\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"));
|
|
1220
|
+
console.log();
|
|
1221
|
+
p3.outro("Happy building!");
|
|
1222
|
+
}
|
|
1223
|
+
|
|
999
1224
|
// src/commands/init.ts
|
|
1000
1225
|
async function initCommand(options) {
|
|
1001
1226
|
if (isAgentMode()) {
|
|
@@ -1004,7 +1229,7 @@ async function initCommand(options) {
|
|
|
1004
1229
|
printBanner();
|
|
1005
1230
|
const scope = await chooseConfigScope(options);
|
|
1006
1231
|
if (scope === null) {
|
|
1007
|
-
|
|
1232
|
+
p4.cancel("Setup cancelled.");
|
|
1008
1233
|
return;
|
|
1009
1234
|
}
|
|
1010
1235
|
const existingConfig = scope === "project" ? readProjectConfig() : readGlobalConfig();
|
|
@@ -1030,7 +1255,7 @@ async function chooseConfigScope(options) {
|
|
|
1030
1255
|
console.log(` ${pc2.bold("Active config:")} ${pc2.cyan("project")} ${pc2.dim("\xB7 " + homeProject)}`);
|
|
1031
1256
|
console.log();
|
|
1032
1257
|
if (hasGlobal) {
|
|
1033
|
-
const which2 = await
|
|
1258
|
+
const which2 = await p4.select({
|
|
1034
1259
|
message: "Which config do you want to edit?",
|
|
1035
1260
|
options: [
|
|
1036
1261
|
{ value: "project", label: `This project (${projectName})`, hint: homeProject },
|
|
@@ -1038,7 +1263,7 @@ async function chooseConfigScope(options) {
|
|
|
1038
1263
|
],
|
|
1039
1264
|
initialValue: "project"
|
|
1040
1265
|
});
|
|
1041
|
-
if (
|
|
1266
|
+
if (p4.isCancel(which2)) return null;
|
|
1042
1267
|
return which2;
|
|
1043
1268
|
}
|
|
1044
1269
|
return "project";
|
|
@@ -1052,8 +1277,8 @@ async function chooseConfigScope(options) {
|
|
|
1052
1277
|
console.log();
|
|
1053
1278
|
const defaultScope = hasGlobal ? "project" : "global";
|
|
1054
1279
|
const hint = hasGlobal ? "Your global config stays as-is. This folder gets its own setup." : "No global config yet \u2014 this becomes your default for every folder.";
|
|
1055
|
-
|
|
1056
|
-
const which = await
|
|
1280
|
+
p4.note(hint, defaultScope === "project" ? "Recommended: project" : "Recommended: global");
|
|
1281
|
+
const which = await p4.select({
|
|
1057
1282
|
message: "Where should this setup live?",
|
|
1058
1283
|
options: [
|
|
1059
1284
|
{
|
|
@@ -1069,7 +1294,7 @@ async function chooseConfigScope(options) {
|
|
|
1069
1294
|
],
|
|
1070
1295
|
initialValue: defaultScope
|
|
1071
1296
|
});
|
|
1072
|
-
if (
|
|
1297
|
+
if (p4.isCancel(which)) return null;
|
|
1073
1298
|
return which;
|
|
1074
1299
|
}
|
|
1075
1300
|
function tildify(filePath) {
|
|
@@ -1133,12 +1358,12 @@ async function handleExistingConfig(apiKey, scope, options) {
|
|
|
1133
1358
|
value: "start-fresh",
|
|
1134
1359
|
label: "Start fresh (reconfigure everything)"
|
|
1135
1360
|
});
|
|
1136
|
-
const action = await
|
|
1361
|
+
const action = await p4.select({
|
|
1137
1362
|
message: scopedMessage(scope, "What would you like to do?"),
|
|
1138
1363
|
options: actionOptions
|
|
1139
1364
|
});
|
|
1140
|
-
if (
|
|
1141
|
-
|
|
1365
|
+
if (p4.isCancel(action)) {
|
|
1366
|
+
p4.outro("No changes made.");
|
|
1142
1367
|
return;
|
|
1143
1368
|
}
|
|
1144
1369
|
switch (action) {
|
|
@@ -1146,15 +1371,15 @@ async function handleExistingConfig(apiKey, scope, options) {
|
|
|
1146
1371
|
const success = await promptSkillInstall();
|
|
1147
1372
|
if (success) {
|
|
1148
1373
|
printOnboardingPrompt();
|
|
1149
|
-
|
|
1374
|
+
p4.outro("Skill installed. Paste the prompt above to your AI agent.");
|
|
1150
1375
|
} else {
|
|
1151
|
-
|
|
1376
|
+
p4.outro("Done.");
|
|
1152
1377
|
}
|
|
1153
1378
|
break;
|
|
1154
1379
|
}
|
|
1155
1380
|
case "show-prompt":
|
|
1156
1381
|
printOnboardingPrompt();
|
|
1157
|
-
|
|
1382
|
+
p4.outro("Paste the prompt above to your AI agent.");
|
|
1158
1383
|
break;
|
|
1159
1384
|
case "add-connection": {
|
|
1160
1385
|
const whoamiCached = getWhoAmI();
|
|
@@ -1164,7 +1389,7 @@ async function handleExistingConfig(apiKey, scope, options) {
|
|
|
1164
1389
|
...whoamiCached?.project && { projectId: whoamiCached.project.id }
|
|
1165
1390
|
};
|
|
1166
1391
|
await promptConnectIntegrations(apiKey, addConnParams);
|
|
1167
|
-
|
|
1392
|
+
p4.outro("Done.");
|
|
1168
1393
|
break;
|
|
1169
1394
|
}
|
|
1170
1395
|
case "update-key":
|
|
@@ -1179,51 +1404,76 @@ async function handleExistingConfig(apiKey, scope, options) {
|
|
|
1179
1404
|
}
|
|
1180
1405
|
}
|
|
1181
1406
|
async function handleUpdateKey(statuses, scope) {
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1407
|
+
const authMethod = await p4.select({
|
|
1408
|
+
message: scopedMessage(scope, "How would you like to authenticate?"),
|
|
1409
|
+
options: [
|
|
1410
|
+
{ value: "browser", label: "Browser login", hint: "recommended \u2014 opens app.withone.ai" },
|
|
1411
|
+
{ value: "manual", label: "Paste API key manually" }
|
|
1412
|
+
]
|
|
1187
1413
|
});
|
|
1188
|
-
if (
|
|
1189
|
-
|
|
1414
|
+
if (p4.isCancel(authMethod)) {
|
|
1415
|
+
p4.cancel("Cancelled.");
|
|
1190
1416
|
process.exit(0);
|
|
1191
1417
|
}
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1418
|
+
let newKey;
|
|
1419
|
+
let whoamiResult;
|
|
1420
|
+
if (authMethod === "browser") {
|
|
1421
|
+
const result = await browserLogin();
|
|
1422
|
+
if (!result) {
|
|
1423
|
+
p4.cancel("Browser login did not complete.");
|
|
1424
|
+
process.exit(1);
|
|
1425
|
+
}
|
|
1426
|
+
newKey = result.apiKey;
|
|
1427
|
+
whoamiResult = result.whoami;
|
|
1428
|
+
} else {
|
|
1429
|
+
p4.note(`Get your API key at:
|
|
1430
|
+
${pc2.cyan(getApiKeyUrl())}`, `API Key ${scopeLabel(scope)}`);
|
|
1431
|
+
const openBrowser = await p4.confirm({
|
|
1432
|
+
message: scopedMessage(scope, "Open browser to get API key?"),
|
|
1433
|
+
initialValue: true
|
|
1434
|
+
});
|
|
1435
|
+
if (p4.isCancel(openBrowser)) {
|
|
1436
|
+
p4.cancel("Cancelled.");
|
|
1437
|
+
process.exit(0);
|
|
1438
|
+
}
|
|
1439
|
+
if (openBrowser) {
|
|
1440
|
+
await openApiKeyPage();
|
|
1441
|
+
}
|
|
1442
|
+
const inputKey = await p4.text({
|
|
1443
|
+
message: scopedMessage(scope, "Enter your new One API key:"),
|
|
1444
|
+
placeholder: "sk_live_...",
|
|
1445
|
+
validate: (value) => {
|
|
1446
|
+
if (!value) return "API key is required";
|
|
1447
|
+
if (!value.startsWith("sk_live_") && !value.startsWith("sk_test_")) {
|
|
1448
|
+
return "API key should start with sk_live_ or sk_test_";
|
|
1449
|
+
}
|
|
1450
|
+
return void 0;
|
|
1202
1451
|
}
|
|
1203
|
-
|
|
1452
|
+
});
|
|
1453
|
+
if (p4.isCancel(inputKey)) {
|
|
1454
|
+
p4.cancel("Cancelled.");
|
|
1455
|
+
process.exit(0);
|
|
1204
1456
|
}
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
process.exit(1);
|
|
1457
|
+
newKey = inputKey;
|
|
1458
|
+
const spinner6 = p4.spinner();
|
|
1459
|
+
spinner6.start("Validating API key...");
|
|
1460
|
+
const api = new OneApi(newKey, getApiBase());
|
|
1461
|
+
const validated = await api.validateApiKey();
|
|
1462
|
+
if (!validated) {
|
|
1463
|
+
spinner6.stop("Invalid API key");
|
|
1464
|
+
p4.cancel(`Invalid API key. Get a valid key at ${getApiKeyUrl()}`);
|
|
1465
|
+
process.exit(1);
|
|
1466
|
+
}
|
|
1467
|
+
spinner6.stop("API key validated");
|
|
1468
|
+
whoamiResult = validated;
|
|
1218
1469
|
}
|
|
1219
|
-
spinner5.stop("API key validated");
|
|
1220
1470
|
const env = getEnvFromApiKey(newKey);
|
|
1221
1471
|
const contextParts = [];
|
|
1222
1472
|
if (whoamiResult.organization) contextParts.push(whoamiResult.organization.name);
|
|
1223
1473
|
if (whoamiResult.project) contextParts.push(whoamiResult.project.name);
|
|
1224
1474
|
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
1225
1475
|
const envLabel = env === "test" ? pc2.yellow("test") : pc2.green("live");
|
|
1226
|
-
|
|
1476
|
+
p4.note(
|
|
1227
1477
|
`${scopeDisplay} ${pc2.dim("\xB7")} ${envLabel}
|
|
1228
1478
|
${whoamiResult.user.name} ${pc2.dim(`(${whoamiResult.user.email})`)}`,
|
|
1229
1479
|
"Account"
|
|
@@ -1254,9 +1504,9 @@ ${whoamiResult.user.name} ${pc2.dim(`(${whoamiResult.user.email})`)}`,
|
|
|
1254
1504
|
scope
|
|
1255
1505
|
);
|
|
1256
1506
|
if (reinstalled.length > 0) {
|
|
1257
|
-
|
|
1507
|
+
p4.log.success(`Updated MCP configs: ${reinstalled.join(", ")}`);
|
|
1258
1508
|
}
|
|
1259
|
-
|
|
1509
|
+
p4.outro("API key updated.");
|
|
1260
1510
|
}
|
|
1261
1511
|
var SKILL_AGENTS = [
|
|
1262
1512
|
{ id: "claude-code", name: "Claude Code", skillDir: ".claude/skills", primary: true },
|
|
@@ -1359,18 +1609,18 @@ async function promptSkillInstall() {
|
|
|
1359
1609
|
hint: otherAgents.map((a) => a.name).join(", ")
|
|
1360
1610
|
}
|
|
1361
1611
|
];
|
|
1362
|
-
const choice = await
|
|
1612
|
+
const choice = await p4.multiselect({
|
|
1363
1613
|
message: "Install the One skill to:",
|
|
1364
1614
|
options,
|
|
1365
1615
|
initialValues: primaryAgents.map((a) => a.id)
|
|
1366
1616
|
});
|
|
1367
|
-
if (
|
|
1617
|
+
if (p4.isCancel(choice)) {
|
|
1368
1618
|
return false;
|
|
1369
1619
|
}
|
|
1370
1620
|
let selectedIds = choice;
|
|
1371
1621
|
if (selectedIds.includes("_other")) {
|
|
1372
1622
|
selectedIds = selectedIds.filter((id) => id !== "_other");
|
|
1373
|
-
const otherChoice = await
|
|
1623
|
+
const otherChoice = await p4.multiselect({
|
|
1374
1624
|
message: "Select additional agents:",
|
|
1375
1625
|
options: otherAgents.map((a) => ({
|
|
1376
1626
|
value: a.id,
|
|
@@ -1378,23 +1628,23 @@ async function promptSkillInstall() {
|
|
|
1378
1628
|
hint: isSkillInstalledForAgent(a) ? pc2.green("installed") : void 0
|
|
1379
1629
|
}))
|
|
1380
1630
|
});
|
|
1381
|
-
if (!
|
|
1631
|
+
if (!p4.isCancel(otherChoice)) {
|
|
1382
1632
|
selectedIds.push(...otherChoice);
|
|
1383
1633
|
}
|
|
1384
1634
|
}
|
|
1385
1635
|
if (selectedIds.length === 0) {
|
|
1386
|
-
|
|
1636
|
+
p4.log.info("No agents selected.");
|
|
1387
1637
|
return false;
|
|
1388
1638
|
}
|
|
1389
|
-
const
|
|
1390
|
-
|
|
1639
|
+
const spinner6 = p4.spinner();
|
|
1640
|
+
spinner6.start("Installing skill...");
|
|
1391
1641
|
const { installed, failed } = installSkillForAgents(selectedIds);
|
|
1392
|
-
|
|
1642
|
+
spinner6.stop(installed.length > 0 ? "Skill installed" : "Installation failed");
|
|
1393
1643
|
for (const name of installed) {
|
|
1394
|
-
|
|
1644
|
+
p4.log.success(`${name}: ${pc2.green("\u2713")} skill installed`);
|
|
1395
1645
|
}
|
|
1396
1646
|
for (const name of failed) {
|
|
1397
|
-
|
|
1647
|
+
p4.log.warn(`${name}: failed to install`);
|
|
1398
1648
|
}
|
|
1399
1649
|
return installed.length > 0;
|
|
1400
1650
|
}
|
|
@@ -1416,75 +1666,119 @@ function printOnboardingPrompt() {
|
|
|
1416
1666
|
console.log();
|
|
1417
1667
|
}
|
|
1418
1668
|
async function freshSetup(scope, options) {
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1669
|
+
const authMethod = await p4.select({
|
|
1670
|
+
message: scopedMessage(scope, "How would you like to authenticate?"),
|
|
1671
|
+
options: [
|
|
1672
|
+
{ value: "browser", label: "Browser login", hint: "recommended \u2014 opens app.withone.ai" },
|
|
1673
|
+
{ value: "manual", label: "Paste API key manually" }
|
|
1674
|
+
]
|
|
1424
1675
|
});
|
|
1425
|
-
if (
|
|
1426
|
-
|
|
1676
|
+
if (p4.isCancel(authMethod)) {
|
|
1677
|
+
p4.cancel("Setup cancelled.");
|
|
1427
1678
|
process.exit(0);
|
|
1428
1679
|
}
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1680
|
+
let apiKey;
|
|
1681
|
+
if (authMethod === "browser") {
|
|
1682
|
+
const result = await browserLogin();
|
|
1683
|
+
if (!result) {
|
|
1684
|
+
p4.cancel("Browser login did not complete. Try: one init");
|
|
1685
|
+
process.exit(1);
|
|
1686
|
+
}
|
|
1687
|
+
apiKey = result.apiKey;
|
|
1688
|
+
const env2 = getEnvFromApiKey(apiKey);
|
|
1689
|
+
const contextParts = [];
|
|
1690
|
+
if (result.whoami.organization) contextParts.push(result.whoami.organization.name);
|
|
1691
|
+
if (result.whoami.project) contextParts.push(result.whoami.project.name);
|
|
1692
|
+
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
1693
|
+
const envLabel = env2 === "test" ? pc2.yellow("test") : pc2.green("live");
|
|
1694
|
+
p4.note(
|
|
1695
|
+
`${scopeDisplay} ${pc2.dim("\xB7")} ${envLabel}
|
|
1696
|
+
${result.whoami.user.name} ${pc2.dim(`(${result.whoami.user.email})`)}`,
|
|
1697
|
+
"Account"
|
|
1698
|
+
);
|
|
1699
|
+
writeConfig(
|
|
1700
|
+
{
|
|
1701
|
+
apiKey,
|
|
1702
|
+
installedAgents: [],
|
|
1703
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1704
|
+
whoami: result.whoami
|
|
1705
|
+
},
|
|
1706
|
+
scope
|
|
1707
|
+
);
|
|
1708
|
+
} else {
|
|
1709
|
+
p4.note(`Get your API key at:
|
|
1710
|
+
${pc2.cyan(getApiKeyUrl())}`, `API Key ${scopeLabel(scope)}`);
|
|
1711
|
+
const openBrowser = await p4.confirm({
|
|
1712
|
+
message: scopedMessage(scope, "Open browser to get API key?"),
|
|
1713
|
+
initialValue: true
|
|
1714
|
+
});
|
|
1715
|
+
if (p4.isCancel(openBrowser)) {
|
|
1716
|
+
p4.cancel("Setup cancelled.");
|
|
1717
|
+
process.exit(0);
|
|
1718
|
+
}
|
|
1719
|
+
if (openBrowser) {
|
|
1720
|
+
await openApiKeyPage();
|
|
1721
|
+
}
|
|
1722
|
+
const inputKey = await p4.text({
|
|
1723
|
+
message: scopedMessage(scope, "Enter your One API key:"),
|
|
1724
|
+
placeholder: "sk_live_...",
|
|
1725
|
+
validate: (value) => {
|
|
1726
|
+
if (!value) return "API key is required";
|
|
1727
|
+
if (!value.startsWith("sk_live_") && !value.startsWith("sk_test_")) {
|
|
1728
|
+
return "API key should start with sk_live_ or sk_test_";
|
|
1729
|
+
}
|
|
1730
|
+
return void 0;
|
|
1439
1731
|
}
|
|
1440
|
-
|
|
1732
|
+
});
|
|
1733
|
+
if (p4.isCancel(inputKey)) {
|
|
1734
|
+
p4.cancel("Setup cancelled.");
|
|
1735
|
+
process.exit(0);
|
|
1441
1736
|
}
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
const scope_label = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
1462
|
-
const envLabel = env === "test" ? pc2.yellow("test") : pc2.green("live");
|
|
1463
|
-
p3.note(
|
|
1464
|
-
`${scope_label} ${pc2.dim("\xB7")} ${envLabel}
|
|
1737
|
+
apiKey = inputKey;
|
|
1738
|
+
const spinner6 = p4.spinner();
|
|
1739
|
+
spinner6.start("Validating API key...");
|
|
1740
|
+
const api = new OneApi(apiKey, getApiBase());
|
|
1741
|
+
const whoami = await api.validateApiKey();
|
|
1742
|
+
if (!whoami) {
|
|
1743
|
+
spinner6.stop("Invalid API key");
|
|
1744
|
+
p4.cancel(`Invalid API key. Get a valid key at ${getApiKeyUrl()}`);
|
|
1745
|
+
process.exit(1);
|
|
1746
|
+
}
|
|
1747
|
+
spinner6.stop("API key validated");
|
|
1748
|
+
const env2 = getEnvFromApiKey(apiKey);
|
|
1749
|
+
const contextParts = [];
|
|
1750
|
+
if (whoami.organization) contextParts.push(whoami.organization.name);
|
|
1751
|
+
if (whoami.project) contextParts.push(whoami.project.name);
|
|
1752
|
+
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
1753
|
+
const envLabel = env2 === "test" ? pc2.yellow("test") : pc2.green("live");
|
|
1754
|
+
p4.note(
|
|
1755
|
+
`${scopeDisplay} ${pc2.dim("\xB7")} ${envLabel}
|
|
1465
1756
|
${whoami.user.name} ${pc2.dim(`(${whoami.user.email})`)}`,
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1757
|
+
"Account"
|
|
1758
|
+
);
|
|
1759
|
+
writeConfig(
|
|
1760
|
+
{
|
|
1761
|
+
apiKey,
|
|
1762
|
+
installedAgents: [],
|
|
1763
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1764
|
+
whoami
|
|
1765
|
+
},
|
|
1766
|
+
scope
|
|
1767
|
+
);
|
|
1768
|
+
}
|
|
1477
1769
|
await promptSkillInstall();
|
|
1770
|
+
const env = getEnvFromApiKey(apiKey);
|
|
1771
|
+
const savedConfig = readConfig();
|
|
1478
1772
|
const connParams = {
|
|
1479
1773
|
env,
|
|
1480
|
-
...whoami
|
|
1481
|
-
...whoami
|
|
1774
|
+
...savedConfig?.whoami?.organization && { orgId: savedConfig.whoami.organization.id },
|
|
1775
|
+
...savedConfig?.whoami?.project && { projectId: savedConfig.whoami.project.id }
|
|
1482
1776
|
};
|
|
1483
1777
|
await promptConnectIntegrations(apiKey, connParams);
|
|
1484
1778
|
const savedPath = scope === "project" ? getProjectConfigPath() : getGlobalConfigPath();
|
|
1485
1779
|
const resolutionHint = scope === "project" ? `When you run ${pc2.cyan("one")} from ${pc2.bold(path4.basename(getProjectRoot()))}, it uses this project config.
|
|
1486
1780
|
From anywhere else, it falls back to your global config.` : `This config applies to every folder unless a project config is set.`;
|
|
1487
|
-
|
|
1781
|
+
p4.note(
|
|
1488
1782
|
`${scopeLabel(scope)} Config saved to:
|
|
1489
1783
|
${pc2.dim(tildify(savedPath))}
|
|
1490
1784
|
|
|
@@ -1492,7 +1786,7 @@ ${resolutionHint}`,
|
|
|
1492
1786
|
"Setup Complete"
|
|
1493
1787
|
);
|
|
1494
1788
|
printOnboardingPrompt();
|
|
1495
|
-
|
|
1789
|
+
p4.outro("Done! Paste the prompt above to your AI agent.");
|
|
1496
1790
|
}
|
|
1497
1791
|
function printBanner() {
|
|
1498
1792
|
console.log();
|
|
@@ -1541,48 +1835,48 @@ async function promptConnectIntegrations(apiKey, connParams) {
|
|
|
1541
1835
|
{ value: "skip", label: "Skip for now", hint: "you can always run one add later" }
|
|
1542
1836
|
];
|
|
1543
1837
|
const message = first ? "Connect your first integration?" : "Connect another?";
|
|
1544
|
-
const choice = await
|
|
1545
|
-
if (
|
|
1838
|
+
const choice = await p4.select({ message, options });
|
|
1839
|
+
if (p4.isCancel(choice) || choice === "skip") {
|
|
1546
1840
|
break;
|
|
1547
1841
|
}
|
|
1548
1842
|
if (choice === "more") {
|
|
1549
1843
|
try {
|
|
1550
1844
|
await open2("https://app.withone.ai/connections");
|
|
1551
|
-
|
|
1845
|
+
p4.log.info("Opened One dashboard in browser.");
|
|
1552
1846
|
} catch {
|
|
1553
|
-
|
|
1847
|
+
p4.note("https://app.withone.ai/connections", "Open in browser");
|
|
1554
1848
|
}
|
|
1555
|
-
|
|
1849
|
+
p4.log.info(`Connect from the dashboard, or use ${pc2.cyan("one add <platform>")}`);
|
|
1556
1850
|
break;
|
|
1557
1851
|
}
|
|
1558
1852
|
const platform = choice;
|
|
1559
1853
|
const integration = TOP_INTEGRATIONS.find((i) => i.value === platform);
|
|
1560
1854
|
const label = integration?.label ?? platform;
|
|
1561
|
-
|
|
1855
|
+
p4.log.info(`Opening browser to connect ${pc2.cyan(label)}...`);
|
|
1562
1856
|
try {
|
|
1563
1857
|
await openConnectionPage(platform, connParams);
|
|
1564
1858
|
} catch {
|
|
1565
1859
|
const url = getConnectionUrl(platform, connParams);
|
|
1566
|
-
|
|
1567
|
-
|
|
1860
|
+
p4.log.warn("Could not open browser automatically.");
|
|
1861
|
+
p4.note(url, "Open manually");
|
|
1568
1862
|
}
|
|
1569
|
-
const
|
|
1570
|
-
|
|
1863
|
+
const spinner6 = p4.spinner();
|
|
1864
|
+
spinner6.start("Waiting for connection... (complete auth in browser)");
|
|
1571
1865
|
try {
|
|
1572
1866
|
await api.waitForConnection(platform, 5 * 60 * 1e3, 5e3);
|
|
1573
|
-
|
|
1574
|
-
|
|
1867
|
+
spinner6.stop(`${label} connected!`);
|
|
1868
|
+
p4.log.success(`${pc2.green("\u2713")} ${label} is now available to your AI agents`);
|
|
1575
1869
|
connected.push(platform);
|
|
1576
1870
|
first = false;
|
|
1577
1871
|
} catch (error2) {
|
|
1578
|
-
|
|
1872
|
+
spinner6.stop("Connection timed out");
|
|
1579
1873
|
if (error2 instanceof TimeoutError) {
|
|
1580
|
-
|
|
1874
|
+
p4.log.warn(`No worries. Connect later with: ${pc2.cyan(`one add ${platform}`)}`);
|
|
1581
1875
|
}
|
|
1582
1876
|
first = false;
|
|
1583
1877
|
}
|
|
1584
1878
|
if (TOP_INTEGRATIONS.every((i) => connected.includes(i.value))) {
|
|
1585
|
-
|
|
1879
|
+
p4.log.success("All top integrations connected!");
|
|
1586
1880
|
break;
|
|
1587
1881
|
}
|
|
1588
1882
|
}
|
|
@@ -1593,23 +1887,23 @@ function maskApiKey(key) {
|
|
|
1593
1887
|
}
|
|
1594
1888
|
|
|
1595
1889
|
// src/commands/connection.ts
|
|
1596
|
-
import * as
|
|
1890
|
+
import * as p5 from "@clack/prompts";
|
|
1597
1891
|
import pc4 from "picocolors";
|
|
1598
1892
|
|
|
1599
1893
|
// src/lib/platforms.ts
|
|
1600
1894
|
function findPlatform(platforms, query) {
|
|
1601
1895
|
const normalizedQuery = query.toLowerCase().trim();
|
|
1602
1896
|
const exact = platforms.find(
|
|
1603
|
-
(
|
|
1897
|
+
(p10) => p10.platform.toLowerCase() === normalizedQuery || p10.name.toLowerCase() === normalizedQuery
|
|
1604
1898
|
);
|
|
1605
1899
|
if (exact) return exact;
|
|
1606
1900
|
return null;
|
|
1607
1901
|
}
|
|
1608
1902
|
function findSimilarPlatforms(platforms, query, limit = 3) {
|
|
1609
1903
|
const normalizedQuery = query.toLowerCase().trim();
|
|
1610
|
-
const scored = platforms.map((
|
|
1611
|
-
const name =
|
|
1612
|
-
const slug =
|
|
1904
|
+
const scored = platforms.map((p10) => {
|
|
1905
|
+
const name = p10.name.toLowerCase();
|
|
1906
|
+
const slug = p10.platform.toLowerCase();
|
|
1613
1907
|
let score = 0;
|
|
1614
1908
|
if (name.includes(normalizedQuery) || slug.includes(normalizedQuery)) {
|
|
1615
1909
|
score = 10;
|
|
@@ -1618,7 +1912,7 @@ function findSimilarPlatforms(platforms, query, limit = 3) {
|
|
|
1618
1912
|
} else {
|
|
1619
1913
|
score = countMatchingChars(normalizedQuery, slug);
|
|
1620
1914
|
}
|
|
1621
|
-
return { platform:
|
|
1915
|
+
return { platform: p10, score };
|
|
1622
1916
|
}).filter((item) => item.score > 0).sort((a, b) => b.score - a.score).slice(0, limit);
|
|
1623
1917
|
return scored.map((item) => item.platform);
|
|
1624
1918
|
}
|
|
@@ -1672,22 +1966,22 @@ async function connectionAddCommand(platformArg) {
|
|
|
1672
1966
|
if (isAgentMode()) {
|
|
1673
1967
|
error("This command requires interactive input. Run without --agent.");
|
|
1674
1968
|
}
|
|
1675
|
-
|
|
1969
|
+
p5.intro(pc4.bgCyan(pc4.black(" One ")));
|
|
1676
1970
|
const apiKey = getApiKey();
|
|
1677
1971
|
if (!apiKey) {
|
|
1678
|
-
|
|
1972
|
+
p5.cancel("Not configured. Run `one init` first.");
|
|
1679
1973
|
process.exit(1);
|
|
1680
1974
|
}
|
|
1681
1975
|
const api = new OneApi(apiKey, getApiBase());
|
|
1682
|
-
const
|
|
1683
|
-
|
|
1976
|
+
const spinner6 = p5.spinner();
|
|
1977
|
+
spinner6.start("Loading platforms...");
|
|
1684
1978
|
let platforms;
|
|
1685
1979
|
try {
|
|
1686
1980
|
platforms = await api.listPlatforms();
|
|
1687
|
-
|
|
1981
|
+
spinner6.stop(`${platforms.length} platforms available`);
|
|
1688
1982
|
} catch (error2) {
|
|
1689
|
-
|
|
1690
|
-
|
|
1983
|
+
spinner6.stop("Failed to load platforms");
|
|
1984
|
+
p5.cancel(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
1691
1985
|
process.exit(1);
|
|
1692
1986
|
}
|
|
1693
1987
|
let platform;
|
|
@@ -1698,29 +1992,29 @@ async function connectionAddCommand(platformArg) {
|
|
|
1698
1992
|
} else {
|
|
1699
1993
|
const similar = findSimilarPlatforms(platforms, platformArg);
|
|
1700
1994
|
if (similar.length > 0) {
|
|
1701
|
-
|
|
1702
|
-
const suggestion = await
|
|
1995
|
+
p5.log.warn(`Unknown platform: ${platformArg}`);
|
|
1996
|
+
const suggestion = await p5.select({
|
|
1703
1997
|
message: "Did you mean:",
|
|
1704
1998
|
options: [
|
|
1705
1999
|
...similar.map((s) => ({ value: s.platform, label: `${s.name} (${s.platform})` })),
|
|
1706
2000
|
{ value: "__other__", label: "None of these" }
|
|
1707
2001
|
]
|
|
1708
2002
|
});
|
|
1709
|
-
if (
|
|
1710
|
-
|
|
1711
|
-
|
|
2003
|
+
if (p5.isCancel(suggestion) || suggestion === "__other__") {
|
|
2004
|
+
p5.note(`Run ${pc4.cyan("one platforms")} to see all available platforms.`);
|
|
2005
|
+
p5.cancel("Connection cancelled.");
|
|
1712
2006
|
process.exit(0);
|
|
1713
2007
|
}
|
|
1714
2008
|
platform = suggestion;
|
|
1715
2009
|
} else {
|
|
1716
|
-
|
|
2010
|
+
p5.cancel(`Unknown platform: ${platformArg}
|
|
1717
2011
|
|
|
1718
2012
|
Run ${pc4.cyan("one platforms")} to see available platforms.`);
|
|
1719
2013
|
process.exit(1);
|
|
1720
2014
|
}
|
|
1721
2015
|
}
|
|
1722
2016
|
} else {
|
|
1723
|
-
const platformInput = await
|
|
2017
|
+
const platformInput = await p5.text({
|
|
1724
2018
|
message: "Which platform do you want to connect?",
|
|
1725
2019
|
placeholder: "gmail, slack, hubspot...",
|
|
1726
2020
|
validate: (value) => {
|
|
@@ -1728,15 +2022,15 @@ Run ${pc4.cyan("one platforms")} to see available platforms.`);
|
|
|
1728
2022
|
return void 0;
|
|
1729
2023
|
}
|
|
1730
2024
|
});
|
|
1731
|
-
if (
|
|
1732
|
-
|
|
2025
|
+
if (p5.isCancel(platformInput)) {
|
|
2026
|
+
p5.cancel("Connection cancelled.");
|
|
1733
2027
|
process.exit(0);
|
|
1734
2028
|
}
|
|
1735
2029
|
const found = findPlatform(platforms, platformInput);
|
|
1736
2030
|
if (found) {
|
|
1737
2031
|
platform = found.platform;
|
|
1738
2032
|
} else {
|
|
1739
|
-
|
|
2033
|
+
p5.cancel(`Unknown platform: ${platformInput}
|
|
1740
2034
|
|
|
1741
2035
|
Run ${pc4.cyan("one platforms")} to see available platforms.`);
|
|
1742
2036
|
process.exit(1);
|
|
@@ -1749,26 +2043,26 @@ Run ${pc4.cyan("one platforms")} to see available platforms.`);
|
|
|
1749
2043
|
...whoami?.project && { projectId: whoami.project.id }
|
|
1750
2044
|
};
|
|
1751
2045
|
const url = getConnectionUrl(platform, connParams);
|
|
1752
|
-
|
|
1753
|
-
|
|
2046
|
+
p5.log.info(`Opening browser to connect ${pc4.cyan(platform)}...`);
|
|
2047
|
+
p5.note(pc4.dim(url), "URL");
|
|
1754
2048
|
try {
|
|
1755
2049
|
await openConnectionPage(platform, connParams);
|
|
1756
2050
|
} catch {
|
|
1757
|
-
|
|
1758
|
-
|
|
2051
|
+
p5.log.warn("Could not open browser automatically.");
|
|
2052
|
+
p5.note(`Open this URL manually:
|
|
1759
2053
|
${url}`);
|
|
1760
2054
|
}
|
|
1761
|
-
const pollSpinner =
|
|
2055
|
+
const pollSpinner = p5.spinner();
|
|
1762
2056
|
pollSpinner.start("Waiting for connection... (complete auth in browser)");
|
|
1763
2057
|
try {
|
|
1764
2058
|
const connection2 = await api.waitForConnection(platform, 5 * 60 * 1e3, 5e3);
|
|
1765
2059
|
pollSpinner.stop(`${platform} connected!`);
|
|
1766
|
-
|
|
1767
|
-
|
|
2060
|
+
p5.log.success(`${pc4.green("\u2713")} ${connection2.platform} is now available to your AI agents.`);
|
|
2061
|
+
p5.outro("Connection complete!");
|
|
1768
2062
|
} catch (error2) {
|
|
1769
2063
|
pollSpinner.stop("Connection timed out");
|
|
1770
2064
|
if (error2 instanceof TimeoutError) {
|
|
1771
|
-
|
|
2065
|
+
p5.note(
|
|
1772
2066
|
`Possible issues:
|
|
1773
2067
|
- OAuth flow was not completed in the browser
|
|
1774
2068
|
- Browser popup was blocked
|
|
@@ -1778,7 +2072,7 @@ Try again with: ${pc4.cyan(`one connection add ${platform}`)}`,
|
|
|
1778
2072
|
"Timed Out"
|
|
1779
2073
|
);
|
|
1780
2074
|
} else {
|
|
1781
|
-
|
|
2075
|
+
p5.log.error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
1782
2076
|
}
|
|
1783
2077
|
process.exit(1);
|
|
1784
2078
|
}
|
|
@@ -1789,8 +2083,8 @@ async function connectionListCommand(options) {
|
|
|
1789
2083
|
error("Not configured. Run `one init` first.");
|
|
1790
2084
|
}
|
|
1791
2085
|
const api = new OneApi(apiKey, getApiBase());
|
|
1792
|
-
const
|
|
1793
|
-
|
|
2086
|
+
const spinner6 = createSpinner();
|
|
2087
|
+
spinner6.start("Loading connections...");
|
|
1794
2088
|
try {
|
|
1795
2089
|
const allConnections = await api.listConnections();
|
|
1796
2090
|
const ac = getAccessControlFromAllSources();
|
|
@@ -1818,17 +2112,17 @@ async function connectionListCommand(options) {
|
|
|
1818
2112
|
});
|
|
1819
2113
|
return;
|
|
1820
2114
|
}
|
|
1821
|
-
|
|
2115
|
+
spinner6.stop(`${filtered.length} connection${filtered.length === 1 ? "" : "s"} found`);
|
|
1822
2116
|
if (filtered.length === 0) {
|
|
1823
2117
|
if (searchQuery) {
|
|
1824
|
-
|
|
2118
|
+
p5.note(
|
|
1825
2119
|
`No connections matching "${searchQuery}".
|
|
1826
2120
|
|
|
1827
2121
|
Try: ${pc4.cyan("one connection list")} to see all connections.`,
|
|
1828
2122
|
"No Results"
|
|
1829
2123
|
);
|
|
1830
2124
|
} else {
|
|
1831
|
-
|
|
2125
|
+
p5.note(
|
|
1832
2126
|
`No connections yet.
|
|
1833
2127
|
|
|
1834
2128
|
Add one with: ${pc4.cyan("one connection add gmail")}`,
|
|
@@ -1857,9 +2151,9 @@ Add one with: ${pc4.cyan("one connection add gmail")}`,
|
|
|
1857
2151
|
rows
|
|
1858
2152
|
);
|
|
1859
2153
|
console.log();
|
|
1860
|
-
|
|
2154
|
+
p5.note(`Add more with: ${pc4.cyan("one connection add <platform>")}`, "Tip");
|
|
1861
2155
|
} catch (error2) {
|
|
1862
|
-
|
|
2156
|
+
spinner6.stop("Failed to load connections");
|
|
1863
2157
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
1864
2158
|
}
|
|
1865
2159
|
}
|
|
@@ -1869,13 +2163,13 @@ async function connectionDeleteCommand(connectionKey, options) {
|
|
|
1869
2163
|
error("Not configured. Run `one init` first.");
|
|
1870
2164
|
}
|
|
1871
2165
|
const api = new OneApi(apiKey, getApiBase());
|
|
1872
|
-
const
|
|
1873
|
-
|
|
2166
|
+
const spinner6 = createSpinner();
|
|
2167
|
+
spinner6.start("Finding connection...");
|
|
1874
2168
|
let allConnections;
|
|
1875
2169
|
try {
|
|
1876
2170
|
allConnections = await api.listConnections();
|
|
1877
2171
|
} catch (error2) {
|
|
1878
|
-
|
|
2172
|
+
spinner6.stop("Failed to load connections");
|
|
1879
2173
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
1880
2174
|
return;
|
|
1881
2175
|
}
|
|
@@ -1884,22 +2178,22 @@ async function connectionDeleteCommand(connectionKey, options) {
|
|
|
1884
2178
|
const connections = allowedKeys.includes("*") ? allConnections : allConnections.filter((conn) => allowedKeys.includes(conn.key));
|
|
1885
2179
|
const match = connections.find((conn) => conn.key === connectionKey);
|
|
1886
2180
|
if (!match) {
|
|
1887
|
-
|
|
2181
|
+
spinner6.stop("Connection not found");
|
|
1888
2182
|
error(`No connection found with key: ${connectionKey}`);
|
|
1889
2183
|
return;
|
|
1890
2184
|
}
|
|
1891
2185
|
const connection2 = match;
|
|
1892
|
-
|
|
2186
|
+
spinner6.stop(`Found ${connection2.platform} (${connection2.state})`);
|
|
1893
2187
|
if (!isAgentMode() && !options?.force) {
|
|
1894
2188
|
console.log();
|
|
1895
2189
|
console.log(` ${getStatusIndicator(connection2.state)} ${connection2.platform} ${pc4.dim(connection2.key)}`);
|
|
1896
2190
|
console.log();
|
|
1897
|
-
const confirmed = await
|
|
2191
|
+
const confirmed = await p5.confirm({
|
|
1898
2192
|
message: "Are you sure you want to delete this connection?",
|
|
1899
2193
|
initialValue: false
|
|
1900
2194
|
});
|
|
1901
|
-
if (
|
|
1902
|
-
|
|
2195
|
+
if (p5.isCancel(confirmed) || !confirmed) {
|
|
2196
|
+
p5.cancel("Deletion cancelled.");
|
|
1903
2197
|
process.exit(0);
|
|
1904
2198
|
}
|
|
1905
2199
|
}
|
|
@@ -1916,7 +2210,7 @@ async function connectionDeleteCommand(connectionKey, options) {
|
|
|
1916
2210
|
});
|
|
1917
2211
|
return;
|
|
1918
2212
|
}
|
|
1919
|
-
|
|
2213
|
+
p5.log.success(`${pc4.green("\u2713")} ${connection2.platform} connection removed.`);
|
|
1920
2214
|
} catch (error2) {
|
|
1921
2215
|
deleteSpinner.stop("Failed to delete connection");
|
|
1922
2216
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
@@ -1936,7 +2230,7 @@ function getStatusIndicator(state) {
|
|
|
1936
2230
|
}
|
|
1937
2231
|
|
|
1938
2232
|
// src/commands/platforms.ts
|
|
1939
|
-
import * as
|
|
2233
|
+
import * as p6 from "@clack/prompts";
|
|
1940
2234
|
import pc5 from "picocolors";
|
|
1941
2235
|
async function platformsCommand(options) {
|
|
1942
2236
|
const apiKey = getApiKey();
|
|
@@ -1947,11 +2241,11 @@ async function platformsCommand(options) {
|
|
|
1947
2241
|
options.json = true;
|
|
1948
2242
|
}
|
|
1949
2243
|
const api = new OneApi(apiKey, getApiBase());
|
|
1950
|
-
const
|
|
1951
|
-
|
|
2244
|
+
const spinner6 = createSpinner();
|
|
2245
|
+
spinner6.start("Loading platforms...");
|
|
1952
2246
|
try {
|
|
1953
2247
|
const platforms = await api.listPlatforms();
|
|
1954
|
-
|
|
2248
|
+
spinner6.stop(`${platforms.length} platforms available`);
|
|
1955
2249
|
let filtered = platforms;
|
|
1956
2250
|
if (options.category) {
|
|
1957
2251
|
filtered = platforms.filter((plat) => (plat.category || "Other") === options.category);
|
|
@@ -1961,7 +2255,7 @@ async function platformsCommand(options) {
|
|
|
1961
2255
|
json({ error: `Unknown category "${options.category}"`, availableCategories: categories });
|
|
1962
2256
|
process.exit(1);
|
|
1963
2257
|
}
|
|
1964
|
-
|
|
2258
|
+
p6.note(`Available categories:
|
|
1965
2259
|
${categories.join(", ")}`, "Unknown Category");
|
|
1966
2260
|
process.exit(1);
|
|
1967
2261
|
}
|
|
@@ -2003,15 +2297,15 @@ async function platformsCommand(options) {
|
|
|
2003
2297
|
);
|
|
2004
2298
|
}
|
|
2005
2299
|
console.log();
|
|
2006
|
-
|
|
2300
|
+
p6.note(`Connect with: ${pc5.cyan("one connection add <platform>")}`, "Tip");
|
|
2007
2301
|
} catch (error2) {
|
|
2008
|
-
|
|
2302
|
+
spinner6.stop("Failed to load platforms");
|
|
2009
2303
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
2010
2304
|
}
|
|
2011
2305
|
}
|
|
2012
2306
|
|
|
2013
2307
|
// src/commands/actions.ts
|
|
2014
|
-
import * as
|
|
2308
|
+
import * as p7 from "@clack/prompts";
|
|
2015
2309
|
import pc6 from "picocolors";
|
|
2016
2310
|
|
|
2017
2311
|
// src/lib/cache.ts
|
|
@@ -2153,8 +2447,8 @@ async function actionsSearchCommand(platform, query, options) {
|
|
|
2153
2447
|
intro2(pc6.bgCyan(pc6.black(" One ")));
|
|
2154
2448
|
const { apiKey, permissions, actionIds, knowledgeAgent } = getConfig();
|
|
2155
2449
|
const api = new OneApi(apiKey, getApiBase());
|
|
2156
|
-
const
|
|
2157
|
-
|
|
2450
|
+
const spinner6 = createSpinner();
|
|
2451
|
+
spinner6.start(`Searching actions on ${pc6.cyan(platform)} for "${query}"...`);
|
|
2158
2452
|
try {
|
|
2159
2453
|
const agentType = knowledgeAgent ? "knowledge" : options.type || "execute";
|
|
2160
2454
|
const useCache = options.cache !== false;
|
|
@@ -2219,8 +2513,8 @@ async function actionsSearchCommand(platform, query, options) {
|
|
|
2219
2513
|
return;
|
|
2220
2514
|
}
|
|
2221
2515
|
if (cleanedActions.length === 0) {
|
|
2222
|
-
|
|
2223
|
-
|
|
2516
|
+
spinner6.stop("No actions found");
|
|
2517
|
+
p7.note(
|
|
2224
2518
|
`No actions found for platform '${platform}' matching query '${query}'.
|
|
2225
2519
|
|
|
2226
2520
|
Suggestions:
|
|
@@ -2237,7 +2531,7 @@ Examples of good queries:
|
|
|
2237
2531
|
);
|
|
2238
2532
|
return;
|
|
2239
2533
|
}
|
|
2240
|
-
|
|
2534
|
+
spinner6.stop(
|
|
2241
2535
|
`Found ${cleanedActions.length} action(s) for '${platform}' matching '${query}'`
|
|
2242
2536
|
);
|
|
2243
2537
|
console.log();
|
|
@@ -2257,13 +2551,13 @@ Examples of good queries:
|
|
|
2257
2551
|
rows
|
|
2258
2552
|
);
|
|
2259
2553
|
console.log();
|
|
2260
|
-
|
|
2554
|
+
p7.note(
|
|
2261
2555
|
`Get details: ${pc6.cyan(`one actions knowledge ${platform} <actionId>`)}
|
|
2262
2556
|
Execute: ${pc6.cyan(`one actions execute ${platform} <actionId> <connectionKey>`)}`,
|
|
2263
2557
|
"Next Steps"
|
|
2264
2558
|
);
|
|
2265
2559
|
} catch (error2) {
|
|
2266
|
-
|
|
2560
|
+
spinner6.stop("Search failed");
|
|
2267
2561
|
error(
|
|
2268
2562
|
`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`
|
|
2269
2563
|
);
|
|
@@ -2299,25 +2593,25 @@ async function actionsKnowledgeCommand(platform, actionId, options) {
|
|
|
2299
2593
|
error(`Action "${actionId}" is not in the allowed action list.`);
|
|
2300
2594
|
}
|
|
2301
2595
|
if (!connectionKeys.includes("*")) {
|
|
2302
|
-
const
|
|
2303
|
-
|
|
2596
|
+
const spinner7 = createSpinner();
|
|
2597
|
+
spinner7.start("Checking connections...");
|
|
2304
2598
|
try {
|
|
2305
2599
|
const connections = await api.listConnections();
|
|
2306
2600
|
const connectedPlatforms = connections.map((c) => c.platform);
|
|
2307
2601
|
if (!connectedPlatforms.includes(platform)) {
|
|
2308
|
-
|
|
2602
|
+
spinner7.stop("Platform not connected");
|
|
2309
2603
|
error(`Platform "${platform}" has no allowed connections.`);
|
|
2310
2604
|
}
|
|
2311
|
-
|
|
2605
|
+
spinner7.stop("Connection verified");
|
|
2312
2606
|
} catch (error2) {
|
|
2313
|
-
|
|
2607
|
+
spinner7.stop("Failed to check connections");
|
|
2314
2608
|
error(
|
|
2315
2609
|
`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`
|
|
2316
2610
|
);
|
|
2317
2611
|
}
|
|
2318
2612
|
}
|
|
2319
|
-
const
|
|
2320
|
-
|
|
2613
|
+
const spinner6 = createSpinner();
|
|
2614
|
+
spinner6.start(`Loading knowledge for action ${pc6.dim(actionId)}...`);
|
|
2321
2615
|
try {
|
|
2322
2616
|
const useCache = options.cache !== false;
|
|
2323
2617
|
const cached2 = useCache ? readCache2(cachePath) : null;
|
|
@@ -2372,16 +2666,16 @@ async function actionsKnowledgeCommand(platform, actionId, options) {
|
|
|
2372
2666
|
json(response);
|
|
2373
2667
|
return;
|
|
2374
2668
|
}
|
|
2375
|
-
|
|
2669
|
+
spinner6.stop("Knowledge loaded");
|
|
2376
2670
|
console.log();
|
|
2377
2671
|
console.log(knowledgeWithGuidance);
|
|
2378
2672
|
console.log();
|
|
2379
|
-
|
|
2673
|
+
p7.note(
|
|
2380
2674
|
`Execute: ${pc6.cyan(`one actions execute ${platform} ${actionId} <connectionKey>`)}`,
|
|
2381
2675
|
"Next Step"
|
|
2382
2676
|
);
|
|
2383
2677
|
} catch (error2) {
|
|
2384
|
-
|
|
2678
|
+
spinner6.stop("Failed to load knowledge");
|
|
2385
2679
|
error(
|
|
2386
2680
|
`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`
|
|
2387
2681
|
);
|
|
@@ -2402,17 +2696,17 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
|
|
|
2402
2696
|
error(`Connection key "${connectionKey}" is not allowed.`);
|
|
2403
2697
|
}
|
|
2404
2698
|
const api = new OneApi(apiKey, getApiBase());
|
|
2405
|
-
const
|
|
2406
|
-
|
|
2699
|
+
const spinner6 = createSpinner();
|
|
2700
|
+
spinner6.start("Loading action details...");
|
|
2407
2701
|
try {
|
|
2408
2702
|
const actionDetails = await api.getActionDetails(actionId);
|
|
2409
2703
|
if (!isMethodAllowed(actionDetails.method, permissions)) {
|
|
2410
|
-
|
|
2704
|
+
spinner6.stop("Permission denied");
|
|
2411
2705
|
error(
|
|
2412
2706
|
`Method "${actionDetails.method}" is not allowed under "${permissions}" permission level.`
|
|
2413
2707
|
);
|
|
2414
2708
|
}
|
|
2415
|
-
|
|
2709
|
+
spinner6.stop(`Action: ${actionDetails.title} [${actionDetails.method}]`);
|
|
2416
2710
|
const data = options.data ? parseJsonArg(options.data, "--data") : void 0;
|
|
2417
2711
|
const pathVariables = options.pathVars ? parseJsonArg(options.pathVars, "--path-vars") : void 0;
|
|
2418
2712
|
const queryParams = options.queryParams ? parseJsonArg(options.queryParams, "--query-params") : void 0;
|
|
@@ -2420,7 +2714,7 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
|
|
|
2420
2714
|
if (!options.skipValidation) {
|
|
2421
2715
|
const validation = validateActionInput(actionDetails, { data, pathVariables, queryParams });
|
|
2422
2716
|
if (!validation.valid) {
|
|
2423
|
-
|
|
2717
|
+
spinner6.stop("Validation failed");
|
|
2424
2718
|
if (isAgentMode()) {
|
|
2425
2719
|
json({
|
|
2426
2720
|
error: "Validation failed: missing required parameters",
|
|
@@ -2441,7 +2735,7 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
|
|
|
2441
2735
|
}
|
|
2442
2736
|
}
|
|
2443
2737
|
if (options.mock) {
|
|
2444
|
-
|
|
2738
|
+
spinner6.stop("Mock \u2014 returning example response");
|
|
2445
2739
|
const mockResponse = actionDetails.ioSchema?.ioExample?.output ?? null;
|
|
2446
2740
|
if (isAgentMode()) {
|
|
2447
2741
|
json({
|
|
@@ -2516,7 +2810,7 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
|
|
|
2516
2810
|
console.log(JSON.stringify(result.responseData, null, 2));
|
|
2517
2811
|
}
|
|
2518
2812
|
} catch (error2) {
|
|
2519
|
-
|
|
2813
|
+
spinner6.stop("Execution failed");
|
|
2520
2814
|
error(
|
|
2521
2815
|
`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`
|
|
2522
2816
|
);
|
|
@@ -3495,8 +3789,8 @@ async function flowExecuteCommand(keyOrPath, options) {
|
|
|
3495
3789
|
intro2(pc7.bgCyan(pc7.black(" One Workflow ")));
|
|
3496
3790
|
const { apiKey, permissions, actionIds } = getConfig2();
|
|
3497
3791
|
const api = new OneApi(apiKey, getApiBase());
|
|
3498
|
-
const
|
|
3499
|
-
|
|
3792
|
+
const spinner6 = createSpinner();
|
|
3793
|
+
spinner6.start(`Loading workflow "${keyOrPath}"...`);
|
|
3500
3794
|
let flow2;
|
|
3501
3795
|
let rootDir;
|
|
3502
3796
|
let flowFilePath;
|
|
@@ -3506,11 +3800,11 @@ async function flowExecuteCommand(keyOrPath, options) {
|
|
|
3506
3800
|
rootDir = loaded.rootDir;
|
|
3507
3801
|
flowFilePath = loaded.filePath;
|
|
3508
3802
|
} catch (err) {
|
|
3509
|
-
|
|
3803
|
+
spinner6.stop("Workflow not found");
|
|
3510
3804
|
error(err instanceof Error ? err.message : String(err));
|
|
3511
3805
|
return;
|
|
3512
3806
|
}
|
|
3513
|
-
|
|
3807
|
+
spinner6.stop(`Workflow: ${flow2.name} (${flow2.steps.length} steps)`);
|
|
3514
3808
|
const preflightErrors = validateFlow(flow2, rootDir);
|
|
3515
3809
|
if (preflightErrors.length > 0) {
|
|
3516
3810
|
if (isAgentMode()) {
|
|
@@ -3658,8 +3952,8 @@ async function flowListCommand() {
|
|
|
3658
3952
|
}
|
|
3659
3953
|
async function flowValidateCommand(keyOrPath) {
|
|
3660
3954
|
intro2(pc7.bgCyan(pc7.black(" One Workflow ")));
|
|
3661
|
-
const
|
|
3662
|
-
|
|
3955
|
+
const spinner6 = createSpinner();
|
|
3956
|
+
spinner6.start(`Validating "${keyOrPath}"...`);
|
|
3663
3957
|
let flowData;
|
|
3664
3958
|
let rootDir;
|
|
3665
3959
|
try {
|
|
@@ -3674,12 +3968,12 @@ async function flowValidateCommand(keyOrPath) {
|
|
|
3674
3968
|
rootDir = path7.dirname(flowPath);
|
|
3675
3969
|
}
|
|
3676
3970
|
} catch (err) {
|
|
3677
|
-
|
|
3971
|
+
spinner6.stop("Validation failed");
|
|
3678
3972
|
error(`Could not read workflow: ${err instanceof Error ? err.message : String(err)}`);
|
|
3679
3973
|
}
|
|
3680
3974
|
const errors = validateFlow(flowData, rootDir);
|
|
3681
3975
|
if (errors.length > 0) {
|
|
3682
|
-
|
|
3976
|
+
spinner6.stop("Validation failed");
|
|
3683
3977
|
if (isAgentMode()) {
|
|
3684
3978
|
json({ valid: false, errors });
|
|
3685
3979
|
process.exit(1);
|
|
@@ -3691,7 +3985,7 @@ async function flowValidateCommand(keyOrPath) {
|
|
|
3691
3985
|
console.log();
|
|
3692
3986
|
error(`${errors.length} validation error(s) found`);
|
|
3693
3987
|
}
|
|
3694
|
-
|
|
3988
|
+
spinner6.stop("Workflow is valid");
|
|
3695
3989
|
if (isAgentMode()) {
|
|
3696
3990
|
json({ valid: true, key: flowData.key });
|
|
3697
3991
|
return;
|
|
@@ -3725,11 +4019,11 @@ async function flowResumeCommand(runId) {
|
|
|
3725
4019
|
json(event);
|
|
3726
4020
|
}
|
|
3727
4021
|
};
|
|
3728
|
-
const
|
|
3729
|
-
|
|
4022
|
+
const spinner6 = createSpinner();
|
|
4023
|
+
spinner6.start(`Resuming run ${runId} (${state.completedSteps.length} steps already completed)...`);
|
|
3730
4024
|
try {
|
|
3731
4025
|
const context = await runner.resume(flow2, api, permissions, actionIds, { onEvent, rootDir });
|
|
3732
|
-
|
|
4026
|
+
spinner6.stop("Workflow completed");
|
|
3733
4027
|
if (isAgentMode()) {
|
|
3734
4028
|
json({
|
|
3735
4029
|
event: "workflow:result",
|
|
@@ -3743,7 +4037,7 @@ async function flowResumeCommand(runId) {
|
|
|
3743
4037
|
console.log(` ${pc7.green("\u2713")} Resumed and completed successfully`);
|
|
3744
4038
|
console.log(` ${pc7.dim(`Log: ${runner.getLogPath()}`)}`);
|
|
3745
4039
|
} catch (error2) {
|
|
3746
|
-
|
|
4040
|
+
spinner6.stop("Resume failed");
|
|
3747
4041
|
const errorMsg = error2 instanceof Error ? error2.message : String(error2);
|
|
3748
4042
|
if (isAgentMode()) {
|
|
3749
4043
|
json({ event: "workflow:result", runId, status: "failed", error: errorMsg });
|
|
@@ -4030,8 +4324,8 @@ async function relayCreateCommand(options) {
|
|
|
4030
4324
|
error(`Connection key "${options.connectionKey}" is not allowed.`);
|
|
4031
4325
|
}
|
|
4032
4326
|
const api = new OneApi(apiKey, getApiBase());
|
|
4033
|
-
const
|
|
4034
|
-
|
|
4327
|
+
const spinner6 = createSpinner();
|
|
4328
|
+
spinner6.start("Creating relay endpoint...");
|
|
4035
4329
|
try {
|
|
4036
4330
|
const body = {
|
|
4037
4331
|
connectionKey: options.connectionKey
|
|
@@ -4045,7 +4339,7 @@ async function relayCreateCommand(options) {
|
|
|
4045
4339
|
json(result);
|
|
4046
4340
|
return;
|
|
4047
4341
|
}
|
|
4048
|
-
|
|
4342
|
+
spinner6.stop("Relay endpoint created");
|
|
4049
4343
|
console.log();
|
|
4050
4344
|
console.log(` ${pc8.dim("ID:")} ${result.id}`);
|
|
4051
4345
|
console.log(` ${pc8.dim("URL:")} ${result.url}`);
|
|
@@ -4055,15 +4349,15 @@ async function relayCreateCommand(options) {
|
|
|
4055
4349
|
if (result.webhookPayload?.id) console.log(` ${pc8.dim("Webhook ID:")} ${result.webhookPayload.id}`);
|
|
4056
4350
|
console.log();
|
|
4057
4351
|
} catch (error2) {
|
|
4058
|
-
|
|
4352
|
+
spinner6.stop("Failed to create relay endpoint");
|
|
4059
4353
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
4060
4354
|
}
|
|
4061
4355
|
}
|
|
4062
4356
|
async function relayListCommand(options) {
|
|
4063
4357
|
const { apiKey } = getConfig3();
|
|
4064
4358
|
const api = new OneApi(apiKey, getApiBase());
|
|
4065
|
-
const
|
|
4066
|
-
|
|
4359
|
+
const spinner6 = createSpinner();
|
|
4360
|
+
spinner6.start("Loading relay endpoints...");
|
|
4067
4361
|
try {
|
|
4068
4362
|
const query = {};
|
|
4069
4363
|
if (options.limit) query.limit = options.limit;
|
|
@@ -4086,7 +4380,7 @@ async function relayListCommand(options) {
|
|
|
4086
4380
|
});
|
|
4087
4381
|
return;
|
|
4088
4382
|
}
|
|
4089
|
-
|
|
4383
|
+
spinner6.stop(`${endpoints.length} relay endpoint${endpoints.length === 1 ? "" : "s"} found`);
|
|
4090
4384
|
if (endpoints.length === 0) {
|
|
4091
4385
|
console.log("\n No relay endpoints yet.\n");
|
|
4092
4386
|
return;
|
|
@@ -4108,22 +4402,22 @@ async function relayListCommand(options) {
|
|
|
4108
4402
|
}))
|
|
4109
4403
|
);
|
|
4110
4404
|
} catch (error2) {
|
|
4111
|
-
|
|
4405
|
+
spinner6.stop("Failed to list relay endpoints");
|
|
4112
4406
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
4113
4407
|
}
|
|
4114
4408
|
}
|
|
4115
4409
|
async function relayGetCommand(id) {
|
|
4116
4410
|
const { apiKey } = getConfig3();
|
|
4117
4411
|
const api = new OneApi(apiKey, getApiBase());
|
|
4118
|
-
const
|
|
4119
|
-
|
|
4412
|
+
const spinner6 = createSpinner();
|
|
4413
|
+
spinner6.start("Loading relay endpoint...");
|
|
4120
4414
|
try {
|
|
4121
4415
|
const result = await api.getRelayEndpoint(id);
|
|
4122
4416
|
if (isAgentMode()) {
|
|
4123
4417
|
json(result);
|
|
4124
4418
|
return;
|
|
4125
4419
|
}
|
|
4126
|
-
|
|
4420
|
+
spinner6.stop("Relay endpoint loaded");
|
|
4127
4421
|
console.log();
|
|
4128
4422
|
console.log(` ${pc8.dim("ID:")} ${result.id}`);
|
|
4129
4423
|
console.log(` ${pc8.dim("URL:")} ${result.url}`);
|
|
@@ -4139,15 +4433,15 @@ async function relayGetCommand(id) {
|
|
|
4139
4433
|
console.log(` ${pc8.dim("Created:")} ${result.createdAt}`);
|
|
4140
4434
|
console.log();
|
|
4141
4435
|
} catch (error2) {
|
|
4142
|
-
|
|
4436
|
+
spinner6.stop("Failed to load relay endpoint");
|
|
4143
4437
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
4144
4438
|
}
|
|
4145
4439
|
}
|
|
4146
4440
|
async function relayUpdateCommand(id, options) {
|
|
4147
4441
|
const { apiKey } = getConfig3();
|
|
4148
4442
|
const api = new OneApi(apiKey, getApiBase());
|
|
4149
|
-
const
|
|
4150
|
-
|
|
4443
|
+
const spinner6 = createSpinner();
|
|
4444
|
+
spinner6.start("Updating relay endpoint...");
|
|
4151
4445
|
try {
|
|
4152
4446
|
const body = {};
|
|
4153
4447
|
if (options.description !== void 0) body.description = options.description;
|
|
@@ -4160,40 +4454,40 @@ async function relayUpdateCommand(id, options) {
|
|
|
4160
4454
|
json(result);
|
|
4161
4455
|
return;
|
|
4162
4456
|
}
|
|
4163
|
-
|
|
4457
|
+
spinner6.stop("Relay endpoint updated");
|
|
4164
4458
|
console.log(` ${pc8.dim("ID:")} ${result.id}`);
|
|
4165
4459
|
console.log(` ${pc8.dim("Active:")} ${result.active}`);
|
|
4166
4460
|
console.log(` ${pc8.dim("Actions:")} ${result.actions?.length || 0}`);
|
|
4167
4461
|
console.log();
|
|
4168
4462
|
} catch (error2) {
|
|
4169
|
-
|
|
4463
|
+
spinner6.stop("Failed to update relay endpoint");
|
|
4170
4464
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
4171
4465
|
}
|
|
4172
4466
|
}
|
|
4173
4467
|
async function relayDeleteCommand(id) {
|
|
4174
4468
|
const { apiKey } = getConfig3();
|
|
4175
4469
|
const api = new OneApi(apiKey, getApiBase());
|
|
4176
|
-
const
|
|
4177
|
-
|
|
4470
|
+
const spinner6 = createSpinner();
|
|
4471
|
+
spinner6.start("Deleting relay endpoint...");
|
|
4178
4472
|
try {
|
|
4179
4473
|
const result = await api.deleteRelayEndpoint(id);
|
|
4180
4474
|
if (isAgentMode()) {
|
|
4181
4475
|
json({ deleted: true, id: result.id });
|
|
4182
4476
|
return;
|
|
4183
4477
|
}
|
|
4184
|
-
|
|
4478
|
+
spinner6.stop("Relay endpoint deleted");
|
|
4185
4479
|
console.log(` Deleted: ${result.id}`);
|
|
4186
4480
|
console.log();
|
|
4187
4481
|
} catch (error2) {
|
|
4188
|
-
|
|
4482
|
+
spinner6.stop("Failed to delete relay endpoint");
|
|
4189
4483
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
4190
4484
|
}
|
|
4191
4485
|
}
|
|
4192
4486
|
async function relayActivateCommand(id, options) {
|
|
4193
4487
|
const { apiKey } = getConfig3();
|
|
4194
4488
|
const api = new OneApi(apiKey, getApiBase());
|
|
4195
|
-
const
|
|
4196
|
-
|
|
4489
|
+
const spinner6 = createSpinner();
|
|
4490
|
+
spinner6.start("Activating relay endpoint...");
|
|
4197
4491
|
try {
|
|
4198
4492
|
const actions2 = parseJsonArg2(options.actions, "--actions");
|
|
4199
4493
|
const body = { actions: actions2 };
|
|
@@ -4203,21 +4497,21 @@ async function relayActivateCommand(id, options) {
|
|
|
4203
4497
|
json(result);
|
|
4204
4498
|
return;
|
|
4205
4499
|
}
|
|
4206
|
-
|
|
4500
|
+
spinner6.stop("Relay endpoint activated");
|
|
4207
4501
|
console.log(` ${pc8.dim("ID:")} ${result.id}`);
|
|
4208
4502
|
console.log(` ${pc8.dim("Active:")} ${result.active}`);
|
|
4209
4503
|
console.log(` ${pc8.dim("Actions:")} ${result.actions?.length || 0}`);
|
|
4210
4504
|
console.log();
|
|
4211
4505
|
} catch (error2) {
|
|
4212
|
-
|
|
4506
|
+
spinner6.stop("Failed to activate relay endpoint");
|
|
4213
4507
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
4214
4508
|
}
|
|
4215
4509
|
}
|
|
4216
4510
|
async function relayEventsCommand(options) {
|
|
4217
4511
|
const { apiKey } = getConfig3();
|
|
4218
4512
|
const api = new OneApi(apiKey, getApiBase());
|
|
4219
|
-
const
|
|
4220
|
-
|
|
4513
|
+
const spinner6 = createSpinner();
|
|
4514
|
+
spinner6.start("Loading relay events...");
|
|
4221
4515
|
try {
|
|
4222
4516
|
const query = {};
|
|
4223
4517
|
if (options.limit) query.limit = options.limit;
|
|
@@ -4241,7 +4535,7 @@ async function relayEventsCommand(options) {
|
|
|
4241
4535
|
});
|
|
4242
4536
|
return;
|
|
4243
4537
|
}
|
|
4244
|
-
|
|
4538
|
+
spinner6.stop(`${events.length} event${events.length === 1 ? "" : "s"} found`);
|
|
4245
4539
|
if (events.length === 0) {
|
|
4246
4540
|
console.log("\n No events found.\n");
|
|
4247
4541
|
return;
|
|
@@ -4261,22 +4555,22 @@ async function relayEventsCommand(options) {
|
|
|
4261
4555
|
}))
|
|
4262
4556
|
);
|
|
4263
4557
|
} catch (error2) {
|
|
4264
|
-
|
|
4558
|
+
spinner6.stop("Failed to list relay events");
|
|
4265
4559
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
4266
4560
|
}
|
|
4267
4561
|
}
|
|
4268
4562
|
async function relayEventGetCommand(id) {
|
|
4269
4563
|
const { apiKey } = getConfig3();
|
|
4270
4564
|
const api = new OneApi(apiKey, getApiBase());
|
|
4271
|
-
const
|
|
4272
|
-
|
|
4565
|
+
const spinner6 = createSpinner();
|
|
4566
|
+
spinner6.start("Loading relay event...");
|
|
4273
4567
|
try {
|
|
4274
4568
|
const result = await api.getRelayEvent(id);
|
|
4275
4569
|
if (isAgentMode()) {
|
|
4276
4570
|
json(result);
|
|
4277
4571
|
return;
|
|
4278
4572
|
}
|
|
4279
|
-
|
|
4573
|
+
spinner6.stop("Relay event loaded");
|
|
4280
4574
|
console.log();
|
|
4281
4575
|
console.log(` ${pc8.dim("ID:")} ${result.id}`);
|
|
4282
4576
|
console.log(` ${pc8.dim("Platform:")} ${result.platform}`);
|
|
@@ -4286,7 +4580,7 @@ async function relayEventGetCommand(id) {
|
|
|
4286
4580
|
console.log(JSON.stringify(result.payload, null, 2));
|
|
4287
4581
|
console.log();
|
|
4288
4582
|
} catch (error2) {
|
|
4289
|
-
|
|
4583
|
+
spinner6.stop("Failed to load relay event");
|
|
4290
4584
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
4291
4585
|
}
|
|
4292
4586
|
}
|
|
@@ -4296,8 +4590,8 @@ async function relayDeliveriesCommand(options) {
|
|
|
4296
4590
|
}
|
|
4297
4591
|
const { apiKey } = getConfig3();
|
|
4298
4592
|
const api = new OneApi(apiKey, getApiBase());
|
|
4299
|
-
const
|
|
4300
|
-
|
|
4593
|
+
const spinner6 = createSpinner();
|
|
4594
|
+
spinner6.start("Loading deliveries...");
|
|
4301
4595
|
try {
|
|
4302
4596
|
const deliveries = options.endpointId ? await api.listRelayEndpointDeliveries(options.endpointId) : await api.listRelayEventDeliveries(options.eventId);
|
|
4303
4597
|
const items = Array.isArray(deliveries) ? deliveries : deliveries.rows || [];
|
|
@@ -4305,7 +4599,7 @@ async function relayDeliveriesCommand(options) {
|
|
|
4305
4599
|
json({ deliveries: items });
|
|
4306
4600
|
return;
|
|
4307
4601
|
}
|
|
4308
|
-
|
|
4602
|
+
spinner6.stop(`${items.length} deliver${items.length === 1 ? "y" : "ies"} found`);
|
|
4309
4603
|
if (items.length === 0) {
|
|
4310
4604
|
console.log("\n No deliveries found.\n");
|
|
4311
4605
|
return;
|
|
@@ -4327,22 +4621,22 @@ async function relayDeliveriesCommand(options) {
|
|
|
4327
4621
|
}))
|
|
4328
4622
|
);
|
|
4329
4623
|
} catch (error2) {
|
|
4330
|
-
|
|
4624
|
+
spinner6.stop("Failed to load deliveries");
|
|
4331
4625
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
4332
4626
|
}
|
|
4333
4627
|
}
|
|
4334
4628
|
async function relayEventTypesCommand(platform) {
|
|
4335
4629
|
const { apiKey } = getConfig3();
|
|
4336
4630
|
const api = new OneApi(apiKey, getApiBase());
|
|
4337
|
-
const
|
|
4338
|
-
|
|
4631
|
+
const spinner6 = createSpinner();
|
|
4632
|
+
spinner6.start(`Loading event types for ${pc8.cyan(platform)}...`);
|
|
4339
4633
|
try {
|
|
4340
4634
|
const eventTypes = await api.listRelayEventTypes(platform);
|
|
4341
4635
|
if (isAgentMode()) {
|
|
4342
4636
|
json({ platform, eventTypes });
|
|
4343
4637
|
return;
|
|
4344
4638
|
}
|
|
4345
|
-
|
|
4639
|
+
spinner6.stop(`${eventTypes.length} event type${eventTypes.length === 1 ? "" : "s"} found`);
|
|
4346
4640
|
if (eventTypes.length === 0) {
|
|
4347
4641
|
console.log(`
|
|
4348
4642
|
No event types found for ${platform}.
|
|
@@ -4355,7 +4649,7 @@ async function relayEventTypesCommand(platform) {
|
|
|
4355
4649
|
}
|
|
4356
4650
|
console.log();
|
|
4357
4651
|
} catch (error2) {
|
|
4358
|
-
|
|
4652
|
+
spinner6.stop("Failed to load event types");
|
|
4359
4653
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
4360
4654
|
}
|
|
4361
4655
|
}
|
|
@@ -6748,7 +7042,7 @@ async function searchSyncedData(query, options) {
|
|
|
6748
7042
|
|
|
6749
7043
|
// src/lib/sync/index.ts
|
|
6750
7044
|
import { spawn as spawn4 } from "child_process";
|
|
6751
|
-
import * as
|
|
7045
|
+
import * as p8 from "@clack/prompts";
|
|
6752
7046
|
import pc9 from "picocolors";
|
|
6753
7047
|
async function syncInstallCommand() {
|
|
6754
7048
|
if (await isSqliteAvailable()) {
|
|
@@ -6835,12 +7129,12 @@ async function syncProfilesCommand(platform) {
|
|
|
6835
7129
|
const profiles = listBuiltinProfiles(platform);
|
|
6836
7130
|
if (isAgentMode()) {
|
|
6837
7131
|
json({
|
|
6838
|
-
profiles: profiles.map((
|
|
6839
|
-
platform:
|
|
6840
|
-
model:
|
|
6841
|
-
description:
|
|
6842
|
-
hasEnrich: !!
|
|
6843
|
-
hasIdentityKey: !!
|
|
7132
|
+
profiles: profiles.map((p10) => ({
|
|
7133
|
+
platform: p10.platform,
|
|
7134
|
+
model: p10.model,
|
|
7135
|
+
description: p10.description,
|
|
7136
|
+
hasEnrich: !!p10.enrich,
|
|
7137
|
+
hasIdentityKey: !!p10.identityKey
|
|
6844
7138
|
})),
|
|
6845
7139
|
total: profiles.length,
|
|
6846
7140
|
_hint: profiles.length > 0 ? "Use a built-in profile: one --agent sync init <platform> <model>" : "No built-in profiles found. Use sync init to auto-infer from action knowledge."
|
|
@@ -6854,24 +7148,24 @@ async function syncProfilesCommand(platform) {
|
|
|
6854
7148
|
);
|
|
6855
7149
|
return;
|
|
6856
7150
|
}
|
|
6857
|
-
for (const
|
|
7151
|
+
for (const p10 of profiles) {
|
|
6858
7152
|
const extras = [];
|
|
6859
|
-
if (
|
|
6860
|
-
if (
|
|
6861
|
-
if (
|
|
7153
|
+
if (p10.enrich) extras.push("enrich");
|
|
7154
|
+
if (p10.identityKey) extras.push("identity");
|
|
7155
|
+
if (p10.dateFilter) extras.push("incremental");
|
|
6862
7156
|
const tags = extras.length > 0 ? ` ${pc9.dim(`[${extras.join(", ")}]`)}` : "";
|
|
6863
|
-
console.log(` ${pc9.bold(`${
|
|
7157
|
+
console.log(` ${pc9.bold(`${p10.platform}/${p10.model}`.padEnd(35))} ${p10.description}${tags}`);
|
|
6864
7158
|
}
|
|
6865
7159
|
console.log(`
|
|
6866
7160
|
${profiles.length} built-in profile(s). Run ${pc9.bold("one sync init <platform> <model>")} to use one.`);
|
|
6867
7161
|
}
|
|
6868
7162
|
async function syncModelsCommand(platform) {
|
|
6869
7163
|
const api = getApi();
|
|
6870
|
-
const
|
|
6871
|
-
|
|
7164
|
+
const spinner6 = createSpinner();
|
|
7165
|
+
spinner6.start(`Discovering models for ${platform}...`);
|
|
6872
7166
|
try {
|
|
6873
7167
|
const models = await discoverModels(api, platform);
|
|
6874
|
-
|
|
7168
|
+
spinner6.stop(`Found ${models.length} models`);
|
|
6875
7169
|
if (isAgentMode()) {
|
|
6876
7170
|
json({ platform, models, total: models.length });
|
|
6877
7171
|
return;
|
|
@@ -6885,15 +7179,15 @@ async function syncModelsCommand(platform) {
|
|
|
6885
7179
|
);
|
|
6886
7180
|
note2(lines.join("\n"), `${platform} \u2014 ${models.length} models`);
|
|
6887
7181
|
} catch (err) {
|
|
6888
|
-
|
|
7182
|
+
spinner6.stop("Failed");
|
|
6889
7183
|
error(`Error discovering models: ${err instanceof Error ? err.message : String(err)}`);
|
|
6890
7184
|
}
|
|
6891
7185
|
}
|
|
6892
7186
|
async function syncInitCommand(platform, model, options) {
|
|
6893
7187
|
if (!options.config) {
|
|
6894
7188
|
const api = getApi();
|
|
6895
|
-
const
|
|
6896
|
-
|
|
7189
|
+
const spinner6 = createSpinner();
|
|
7190
|
+
spinner6.start(`Looking up ${platform}/${model}...`);
|
|
6897
7191
|
try {
|
|
6898
7192
|
const models = await discoverModels(api, platform);
|
|
6899
7193
|
const match = models.find((m) => m.name === model || m.name.toLowerCase() === model.toLowerCase());
|
|
@@ -6903,9 +7197,9 @@ async function syncInitCommand(platform, model, options) {
|
|
|
6903
7197
|
if (actionId && !actionId.startsWith("conn_mod_def::")) {
|
|
6904
7198
|
actionId = void 0;
|
|
6905
7199
|
}
|
|
6906
|
-
|
|
7200
|
+
spinner6.stop(actionId ? "Found model + action ID" : "Found model (action ID not resolved)");
|
|
6907
7201
|
} else {
|
|
6908
|
-
|
|
7202
|
+
spinner6.stop("Model not found in available actions");
|
|
6909
7203
|
}
|
|
6910
7204
|
const builtin = loadBuiltinProfile(platform, model);
|
|
6911
7205
|
let template;
|
|
@@ -7005,7 +7299,7 @@ Run with --config to save:
|
|
|
7005
7299
|
}
|
|
7006
7300
|
}
|
|
7007
7301
|
} catch (err) {
|
|
7008
|
-
|
|
7302
|
+
spinner6.stop("Failed");
|
|
7009
7303
|
error(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
7010
7304
|
}
|
|
7011
7305
|
return;
|
|
@@ -7091,7 +7385,7 @@ async function syncRunCommand(platform, options) {
|
|
|
7091
7385
|
const api = getApi();
|
|
7092
7386
|
const profiles = listProfiles(platform);
|
|
7093
7387
|
const targetModels = options.models;
|
|
7094
|
-
const toSync = targetModels ? profiles.filter((
|
|
7388
|
+
const toSync = targetModels ? profiles.filter((p10) => targetModels.includes(p10.model)) : profiles;
|
|
7095
7389
|
if (toSync.length === 0) {
|
|
7096
7390
|
error(
|
|
7097
7391
|
`No sync profiles found for ${platform}` + (targetModels ? ` with models: ${targetModels.join(", ")}` : "") + `. Run 'one sync init ${platform} <model> --config ...' first.`
|
|
@@ -7246,8 +7540,8 @@ async function syncDeleteCommand(platformModel, options) {
|
|
|
7246
7540
|
return;
|
|
7247
7541
|
}
|
|
7248
7542
|
if (!options.yes && !isAgentMode()) {
|
|
7249
|
-
const confirmed = await
|
|
7250
|
-
if (
|
|
7543
|
+
const confirmed = await p8.confirm({ message: `Delete ${preview.count} record(s) from ${platform}/${model}?` });
|
|
7544
|
+
if (p8.isCancel(confirmed) || !confirmed) {
|
|
7251
7545
|
db.close();
|
|
7252
7546
|
cancel2("Cancelled.");
|
|
7253
7547
|
return;
|
|
@@ -7269,15 +7563,15 @@ async function syncDeleteCommand(platformModel, options) {
|
|
|
7269
7563
|
async function syncListCommand(platform) {
|
|
7270
7564
|
const profiles = listProfiles(platform);
|
|
7271
7565
|
const state = readSyncState();
|
|
7272
|
-
const syncs = profiles.map((
|
|
7273
|
-
const modelState = state[
|
|
7566
|
+
const syncs = profiles.map((p10) => {
|
|
7567
|
+
const modelState = state[p10.platform]?.[p10.model];
|
|
7274
7568
|
return {
|
|
7275
|
-
platform:
|
|
7276
|
-
model:
|
|
7569
|
+
platform: p10.platform,
|
|
7570
|
+
model: p10.model,
|
|
7277
7571
|
lastSync: modelState?.lastSync ?? null,
|
|
7278
7572
|
totalRecords: modelState?.totalRecords ?? 0,
|
|
7279
7573
|
pagesProcessed: modelState?.pagesProcessed ?? 0,
|
|
7280
|
-
dbSize: getDatabaseSize(
|
|
7574
|
+
dbSize: getDatabaseSize(p10.platform),
|
|
7281
7575
|
status: modelState?.status ?? "idle"
|
|
7282
7576
|
};
|
|
7283
7577
|
});
|
|
@@ -7300,7 +7594,7 @@ async function syncRemoveCommand(platform, options) {
|
|
|
7300
7594
|
const modelList = options.models?.split(",").map((m) => m.trim());
|
|
7301
7595
|
const preview = [];
|
|
7302
7596
|
const profiles = listProfiles(platform);
|
|
7303
|
-
const targetModels = modelList ?? profiles.map((
|
|
7597
|
+
const targetModels = modelList ?? profiles.map((p10) => p10.model);
|
|
7304
7598
|
try {
|
|
7305
7599
|
if (targetModels.length > 0) {
|
|
7306
7600
|
const db = await openDatabase(platform);
|
|
@@ -7312,14 +7606,14 @@ async function syncRemoveCommand(platform, options) {
|
|
|
7312
7606
|
} catch {
|
|
7313
7607
|
for (const model of targetModels) preview.push({ model, records: 0 });
|
|
7314
7608
|
}
|
|
7315
|
-
const totalRecords = preview.reduce((sum,
|
|
7609
|
+
const totalRecords = preview.reduce((sum, p10) => sum + p10.records, 0);
|
|
7316
7610
|
const dbSize = getDatabaseSize(platform);
|
|
7317
7611
|
if (options.dryRun) {
|
|
7318
7612
|
if (isAgentMode()) {
|
|
7319
7613
|
json({ dryRun: true, platform, models: preview, totalRecords, dbSize });
|
|
7320
7614
|
} else {
|
|
7321
7615
|
note2(
|
|
7322
|
-
preview.map((
|
|
7616
|
+
preview.map((p10) => ` ${p10.model.padEnd(30)} ${String(p10.records).padStart(8)} records`).join("\n") + `
|
|
7323
7617
|
|
|
7324
7618
|
Total: ${totalRecords} records across ${preview.length} model(s), ${dbSize} on disk`,
|
|
7325
7619
|
`Would remove from ${platform}`
|
|
@@ -7329,10 +7623,10 @@ async function syncRemoveCommand(platform, options) {
|
|
|
7329
7623
|
}
|
|
7330
7624
|
if (!options.yes && !isAgentMode()) {
|
|
7331
7625
|
const target = modelList ? `${platform}/${modelList.join(", ")}` : `all synced data for ${platform}`;
|
|
7332
|
-
const confirmed = await
|
|
7626
|
+
const confirmed = await p8.confirm({
|
|
7333
7627
|
message: `Remove ${target}? (${totalRecords} records, ${dbSize} on disk)`
|
|
7334
7628
|
});
|
|
7335
|
-
if (
|
|
7629
|
+
if (p8.isCancel(confirmed) || !confirmed) {
|
|
7336
7630
|
cancel2("Cancelled.");
|
|
7337
7631
|
return;
|
|
7338
7632
|
}
|
|
@@ -7624,8 +7918,8 @@ async function cacheUpdateAllCommand() {
|
|
|
7624
7918
|
console.log("No cached entries to update");
|
|
7625
7919
|
return;
|
|
7626
7920
|
}
|
|
7627
|
-
const
|
|
7628
|
-
|
|
7921
|
+
const spinner6 = createSpinner();
|
|
7922
|
+
spinner6.start(`Updating ${entries.length} cached ${entries.length === 1 ? "entry" : "entries"}...`);
|
|
7629
7923
|
let updated = 0;
|
|
7630
7924
|
let failed = 0;
|
|
7631
7925
|
const errors = [];
|
|
@@ -7649,7 +7943,7 @@ async function cacheUpdateAllCommand() {
|
|
|
7649
7943
|
});
|
|
7650
7944
|
}
|
|
7651
7945
|
}
|
|
7652
|
-
|
|
7946
|
+
spinner6.stop(`Updated ${updated} ${updated === 1 ? "entry" : "entries"}${failed > 0 ? `, ${failed} failed` : ""}`);
|
|
7653
7947
|
if (isAgentMode()) {
|
|
7654
7948
|
json({ updated, failed, errors: errors.length > 0 ? errors : void 0 });
|
|
7655
7949
|
return;
|
|
@@ -7670,10 +7964,12 @@ var GUIDE_OVERVIEW = `# One CLI \u2014 Agent Guide
|
|
|
7670
7964
|
|
|
7671
7965
|
## Setup
|
|
7672
7966
|
|
|
7673
|
-
1. Run \`one init\`
|
|
7967
|
+
1. Run \`one init\` for full interactive setup (authentication, skill installation, and platform connections)
|
|
7674
7968
|
2. Run \`one add <platform>\` to connect platforms via OAuth
|
|
7675
7969
|
3. Run \`one --agent connection list\` to verify connections
|
|
7676
7970
|
|
|
7971
|
+
You can also use \`one login\` / \`one logout\` to manage authentication separately (global or per-directory).
|
|
7972
|
+
|
|
7677
7973
|
## The --agent Flag
|
|
7678
7974
|
|
|
7679
7975
|
Always use \`--agent\` for machine-readable JSON output. It disables colors, spinners, and interactive prompts.
|
|
@@ -8399,7 +8695,7 @@ function pairKey(a, b) {
|
|
|
8399
8695
|
}
|
|
8400
8696
|
function getWorkflowExamples(connectedPlatforms) {
|
|
8401
8697
|
const results = [];
|
|
8402
|
-
const platforms = connectedPlatforms.map((
|
|
8698
|
+
const platforms = connectedPlatforms.map((p10) => p10.toLowerCase());
|
|
8403
8699
|
for (let i = 0; i < platforms.length; i++) {
|
|
8404
8700
|
for (let j = i + 1; j < platforms.length; j++) {
|
|
8405
8701
|
const key = pairKey(platforms[i], platforms[j]);
|
|
@@ -8643,13 +8939,13 @@ function buildDemoActions(connections) {
|
|
|
8643
8939
|
const connectedPlatforms = connections.map((c) => c.platform.toLowerCase());
|
|
8644
8940
|
const popularPlatforms = ["gmail", "google-calendar", "slack", "shopify", "hub-spot", "github"];
|
|
8645
8941
|
const platformsToShow = [
|
|
8646
|
-
...connectedPlatforms.filter((
|
|
8647
|
-
...popularPlatforms.filter((
|
|
8942
|
+
...connectedPlatforms.filter((p10) => PLATFORM_DEMO_ACTIONS[p10]),
|
|
8943
|
+
...popularPlatforms.filter((p10) => !connectedPlatforms.includes(p10))
|
|
8648
8944
|
];
|
|
8649
8945
|
const seen = /* @__PURE__ */ new Set();
|
|
8650
|
-
const unique = platformsToShow.filter((
|
|
8651
|
-
if (seen.has(
|
|
8652
|
-
seen.add(
|
|
8946
|
+
const unique = platformsToShow.filter((p10) => {
|
|
8947
|
+
if (seen.has(p10)) return false;
|
|
8948
|
+
seen.add(p10);
|
|
8653
8949
|
return true;
|
|
8654
8950
|
}).slice(0, 6);
|
|
8655
8951
|
for (const platform of unique) {
|
|
@@ -8680,6 +8976,125 @@ function buildWorkflowIdeas(connections) {
|
|
|
8680
8976
|
return lines.join("\n");
|
|
8681
8977
|
}
|
|
8682
8978
|
|
|
8979
|
+
// src/commands/logout.ts
|
|
8980
|
+
import fs16 from "fs";
|
|
8981
|
+
import * as p9 from "@clack/prompts";
|
|
8982
|
+
function formatWhoami(config2, apiKey, pc12) {
|
|
8983
|
+
const whoami = config2.whoami;
|
|
8984
|
+
const env = getEnvFromApiKey(apiKey);
|
|
8985
|
+
const envLabel = env === "test" ? pc12.yellow("test") : pc12.green("live");
|
|
8986
|
+
const lines = [];
|
|
8987
|
+
if (whoami) {
|
|
8988
|
+
const contextParts = [];
|
|
8989
|
+
if (whoami.organization) contextParts.push(whoami.organization.name);
|
|
8990
|
+
if (whoami.project) contextParts.push(whoami.project.name);
|
|
8991
|
+
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
8992
|
+
lines.push(`${pc12.bold(scopeDisplay)} ${pc12.dim("\xB7")} ${envLabel}`);
|
|
8993
|
+
lines.push(`${whoami.user.name} ${pc12.dim(`(${whoami.user.email})`)}`);
|
|
8994
|
+
} else {
|
|
8995
|
+
lines.push(`${pc12.dim("Key:")} ${apiKey.slice(0, 8)}... ${pc12.dim("\xB7")} ${envLabel}`);
|
|
8996
|
+
}
|
|
8997
|
+
return lines;
|
|
8998
|
+
}
|
|
8999
|
+
async function logoutCommand() {
|
|
9000
|
+
const apiKey = getApiKey();
|
|
9001
|
+
if (!apiKey) {
|
|
9002
|
+
if (isAgentMode()) {
|
|
9003
|
+
json({ error: "Not logged in." });
|
|
9004
|
+
process.exit(1);
|
|
9005
|
+
}
|
|
9006
|
+
error("Not logged in. Run: one login");
|
|
9007
|
+
return;
|
|
9008
|
+
}
|
|
9009
|
+
if (isAgentMode()) {
|
|
9010
|
+
const globalPath = getGlobalConfigPath();
|
|
9011
|
+
const projectPath = getProjectConfigPath();
|
|
9012
|
+
let cleared = false;
|
|
9013
|
+
if (fs16.existsSync(projectPath)) {
|
|
9014
|
+
fs16.unlinkSync(projectPath);
|
|
9015
|
+
cleared = true;
|
|
9016
|
+
}
|
|
9017
|
+
if (fs16.existsSync(globalPath)) {
|
|
9018
|
+
fs16.unlinkSync(globalPath);
|
|
9019
|
+
cleared = true;
|
|
9020
|
+
}
|
|
9021
|
+
json({ status: cleared ? "logged_out" : "not_logged_in", message: cleared ? "Credentials cleared." : "No config found." });
|
|
9022
|
+
return;
|
|
9023
|
+
}
|
|
9024
|
+
const pc12 = (await import("picocolors")).default;
|
|
9025
|
+
const globalConfig = readGlobalConfig();
|
|
9026
|
+
const projectConfig = readProjectConfig();
|
|
9027
|
+
const hasGlobal = globalConfig?.apiKey != null;
|
|
9028
|
+
const hasProject = projectConfig?.apiKey != null;
|
|
9029
|
+
let targetScope;
|
|
9030
|
+
if (hasGlobal && hasProject) {
|
|
9031
|
+
const infoLines = ["You are logged in with multiple configs.", ""];
|
|
9032
|
+
if (projectConfig) {
|
|
9033
|
+
infoLines.push(`${pc12.cyan("Local config:")}`);
|
|
9034
|
+
infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey, pc12));
|
|
9035
|
+
infoLines.push("");
|
|
9036
|
+
}
|
|
9037
|
+
if (globalConfig) {
|
|
9038
|
+
infoLines.push(`${pc12.magenta("Global config:")}`);
|
|
9039
|
+
infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey, pc12));
|
|
9040
|
+
}
|
|
9041
|
+
p9.note(infoLines.join("\n"));
|
|
9042
|
+
const choice = await p9.select({
|
|
9043
|
+
message: "What would you like to log out of?",
|
|
9044
|
+
options: [
|
|
9045
|
+
{ value: "project", label: "This directory", hint: "local config only" },
|
|
9046
|
+
{ value: "global", label: "Globally", hint: "global config only" },
|
|
9047
|
+
{ value: "both", label: "Both", hint: "remove all credentials" }
|
|
9048
|
+
]
|
|
9049
|
+
});
|
|
9050
|
+
if (p9.isCancel(choice)) {
|
|
9051
|
+
p9.cancel("Logout cancelled.");
|
|
9052
|
+
return;
|
|
9053
|
+
}
|
|
9054
|
+
targetScope = choice;
|
|
9055
|
+
} else if (hasProject) {
|
|
9056
|
+
const infoLines = ["You are logged in.", ""];
|
|
9057
|
+
infoLines.push(`${pc12.dim("Stored in")} ${pc12.cyan("local config")}`);
|
|
9058
|
+
infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey, pc12));
|
|
9059
|
+
p9.note(infoLines.join("\n"));
|
|
9060
|
+
targetScope = "project";
|
|
9061
|
+
} else if (hasGlobal) {
|
|
9062
|
+
const infoLines = ["You are logged in.", ""];
|
|
9063
|
+
infoLines.push(`${pc12.dim("Stored in")} ${pc12.magenta("global config")}`);
|
|
9064
|
+
infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey, pc12));
|
|
9065
|
+
p9.note(infoLines.join("\n"));
|
|
9066
|
+
targetScope = "global";
|
|
9067
|
+
} else {
|
|
9068
|
+
p9.log.warn("Credentials are set via environment variable or .onerc, not a config file.");
|
|
9069
|
+
p9.log.info("Remove the ONE_SECRET variable from your environment or .onerc file.");
|
|
9070
|
+
p9.outro("Nothing to remove.");
|
|
9071
|
+
return;
|
|
9072
|
+
}
|
|
9073
|
+
const scopeLabels = {
|
|
9074
|
+
project: "local",
|
|
9075
|
+
global: "global",
|
|
9076
|
+
both: "all"
|
|
9077
|
+
};
|
|
9078
|
+
const confirm6 = await p9.confirm({
|
|
9079
|
+
message: `Remove ${scopeLabels[targetScope]} credentials?`
|
|
9080
|
+
});
|
|
9081
|
+
if (p9.isCancel(confirm6) || !confirm6) {
|
|
9082
|
+
p9.cancel("Logout cancelled.");
|
|
9083
|
+
return;
|
|
9084
|
+
}
|
|
9085
|
+
if (targetScope === "project" || targetScope === "both") {
|
|
9086
|
+
const projectPath = getProjectConfigPath();
|
|
9087
|
+
if (fs16.existsSync(projectPath)) fs16.unlinkSync(projectPath);
|
|
9088
|
+
}
|
|
9089
|
+
if (targetScope === "global" || targetScope === "both") {
|
|
9090
|
+
const globalPath = getGlobalConfigPath();
|
|
9091
|
+
if (fs16.existsSync(globalPath)) fs16.unlinkSync(globalPath);
|
|
9092
|
+
}
|
|
9093
|
+
p9.log.success("Credentials cleared.");
|
|
9094
|
+
p9.log.info("Your API key is still active. Manage keys at app.withone.ai/settings");
|
|
9095
|
+
p9.outro("Logged out.");
|
|
9096
|
+
}
|
|
9097
|
+
|
|
8683
9098
|
// src/index.ts
|
|
8684
9099
|
var require3 = createRequire2(import.meta.url);
|
|
8685
9100
|
var { version } = require3("../package.json");
|
|
@@ -8687,6 +9102,8 @@ var program = new Command();
|
|
|
8687
9102
|
program.name("one").option("--agent", "Machine-readable JSON output (no colors, spinners, or prompts)").description(`One CLI \u2014 Connect AI agents to 250+ platforms through one interface.
|
|
8688
9103
|
|
|
8689
9104
|
Setup:
|
|
9105
|
+
one login Authenticate via browser (opens app.withone.ai)
|
|
9106
|
+
one logout Clear local credentials
|
|
8690
9107
|
one init Set up API key and install MCP server
|
|
8691
9108
|
one add <platform> Connect a platform via OAuth (e.g. gmail, slack, shopify)
|
|
8692
9109
|
one connection delete <key> Remove a connection (alias: one connection rm)
|
|
@@ -8773,6 +9190,12 @@ program.hook("postAction", async () => {
|
|
|
8773
9190
|
program.command("init").description("Set up One and install MCP to your AI agents (interactive: picks global or project scope)").option("-y, --yes", "Skip confirmations").option("-g, --global", "Write the One config globally (~/.one/config.json) \u2014 skips the scope picker").option("-p, --project", "Write the One config for this project only (~/.one/projects/<slug>/) \u2014 skips the scope picker").action(async (options) => {
|
|
8774
9191
|
await initCommand(options);
|
|
8775
9192
|
});
|
|
9193
|
+
program.command("login").description("Authenticate with One via browser").action(async () => {
|
|
9194
|
+
await loginCommand();
|
|
9195
|
+
});
|
|
9196
|
+
program.command("logout").description("Clear local credentials").action(async () => {
|
|
9197
|
+
await logoutCommand();
|
|
9198
|
+
});
|
|
8776
9199
|
var config = program.command("config").description("Configure the CLI (access control, skills, ...)").action(async () => {
|
|
8777
9200
|
await configCommand();
|
|
8778
9201
|
});
|
|
@@ -8862,18 +9285,18 @@ config.command("reset").description("Remove the project config for the current d
|
|
|
8862
9285
|
return;
|
|
8863
9286
|
}
|
|
8864
9287
|
if (!isAgentMode()) {
|
|
8865
|
-
const
|
|
8866
|
-
const confirmed = await
|
|
9288
|
+
const p10 = await import("@clack/prompts");
|
|
9289
|
+
const confirmed = await p10.confirm({
|
|
8867
9290
|
message: "Delete the global config? This removes your API key for all projects without a project config.",
|
|
8868
9291
|
initialValue: false
|
|
8869
9292
|
});
|
|
8870
|
-
if (
|
|
9293
|
+
if (p10.isCancel(confirmed) || !confirmed) {
|
|
8871
9294
|
console.log("Cancelled.");
|
|
8872
9295
|
return;
|
|
8873
9296
|
}
|
|
8874
9297
|
}
|
|
8875
|
-
const
|
|
8876
|
-
|
|
9298
|
+
const fs18 = await import("fs");
|
|
9299
|
+
fs18.unlinkSync(globalPath);
|
|
8877
9300
|
if (isAgentMode()) {
|
|
8878
9301
|
json({ deleted: true, scope: "global" });
|
|
8879
9302
|
} else {
|
|
@@ -8890,12 +9313,12 @@ config.command("reset").description("Remove the project config for the current d
|
|
|
8890
9313
|
}
|
|
8891
9314
|
return;
|
|
8892
9315
|
}
|
|
8893
|
-
const
|
|
8894
|
-
const configContent =
|
|
8895
|
-
|
|
9316
|
+
const fs17 = await import("fs");
|
|
9317
|
+
const configContent = fs17.readFileSync(resolved.path, "utf-8");
|
|
9318
|
+
fs17.unlinkSync(resolved.path);
|
|
8896
9319
|
const next = resolveConfig();
|
|
8897
|
-
|
|
8898
|
-
|
|
9320
|
+
fs17.mkdirSync(path16.dirname(resolved.path), { recursive: true });
|
|
9321
|
+
fs17.writeFileSync(resolved.path, configContent);
|
|
8899
9322
|
let fallbackLabel;
|
|
8900
9323
|
if (next.scope === "project") {
|
|
8901
9324
|
fallbackLabel = `parent project config (${path16.basename(next.projectRoot)})`;
|
|
@@ -8905,19 +9328,19 @@ config.command("reset").description("Remove the project config for the current d
|
|
|
8905
9328
|
fallbackLabel = "no config";
|
|
8906
9329
|
}
|
|
8907
9330
|
if (!isAgentMode()) {
|
|
8908
|
-
const
|
|
8909
|
-
const confirmed = await
|
|
9331
|
+
const p10 = await import("@clack/prompts");
|
|
9332
|
+
const confirmed = await p10.confirm({
|
|
8910
9333
|
message: `Delete project config for ${path16.basename(resolved.projectRoot)}? Will fall back to ${fallbackLabel}.`,
|
|
8911
9334
|
initialValue: false
|
|
8912
9335
|
});
|
|
8913
|
-
if (
|
|
9336
|
+
if (p10.isCancel(confirmed) || !confirmed) {
|
|
8914
9337
|
console.log("Cancelled.");
|
|
8915
9338
|
return;
|
|
8916
9339
|
}
|
|
8917
9340
|
}
|
|
8918
|
-
|
|
9341
|
+
fs17.unlinkSync(resolved.path);
|
|
8919
9342
|
try {
|
|
8920
|
-
|
|
9343
|
+
fs17.rmdirSync(path16.dirname(resolved.path));
|
|
8921
9344
|
} catch {
|
|
8922
9345
|
}
|
|
8923
9346
|
if (isAgentMode()) {
|