@withone/cli 1.18.0 → 1.19.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.
@@ -10,7 +10,6 @@ import { exec } from "child_process";
10
10
  import { promisify } from "util";
11
11
 
12
12
  // src/lib/api.ts
13
- var API_BASE = "https://api.withone.ai/v1";
14
13
  var ApiError = class extends Error {
15
14
  constructor(status, message) {
16
15
  super(message);
@@ -19,14 +18,16 @@ var ApiError = class extends Error {
19
18
  }
20
19
  };
21
20
  var OneApi = class {
22
- constructor(apiKey) {
21
+ constructor(apiKey, apiBase) {
23
22
  this.apiKey = apiKey;
23
+ this.apiBase = apiBase ?? "https://api.withone.ai/v1";
24
24
  }
25
+ apiBase;
25
26
  async request(path3) {
26
27
  return this.requestFull({ path: path3 });
27
28
  }
28
29
  async requestFull(opts) {
29
- let url = `${API_BASE}${opts.path}`;
30
+ let url = `${this.apiBase}${opts.path}`;
30
31
  if (opts.queryParams && Object.keys(opts.queryParams).length > 0) {
31
32
  const params = new URLSearchParams(opts.queryParams);
32
33
  url += `?${params.toString()}`;
@@ -129,7 +130,7 @@ var OneApi = class {
129
130
  };
130
131
  }
131
132
  async requestWithMeta(opts) {
132
- let url = `${API_BASE}${opts.path}`;
133
+ let url = `${this.apiBase}${opts.path}`;
133
134
  if (opts.queryParams && Object.keys(opts.queryParams).length > 0) {
134
135
  const params = new URLSearchParams(opts.queryParams);
135
136
  url += `?${params.toString()}`;
@@ -216,7 +217,7 @@ var OneApi = class {
216
217
  };
217
218
  const finalActionPath = args.pathVariables ? replacePathVariables(action.path, args.pathVariables) : action.path;
218
219
  const normalizedPath = finalActionPath.startsWith("/") ? finalActionPath : `/${finalActionPath}`;
219
- const url = `${API_BASE.replace("/v1", "")}/v1/passthrough${normalizedPath}`;
220
+ const url = `${this.apiBase.replace("/v1", "")}/v1/passthrough${normalizedPath}`;
220
221
  const isCustomAction = action.tags?.includes("custom");
221
222
  let requestData = args.data;
222
223
  if (isCustomAction && method?.toLowerCase() !== "get") {
@@ -778,7 +779,7 @@ async function executeSubflowStep(step, context, api, permissions, allowedAction
778
779
  if (flowStack.includes(resolvedKey)) {
779
780
  throw new Error(`Circular flow detected: ${[...flowStack, resolvedKey].join(" \u2192 ")}`);
780
781
  }
781
- const { loadFlow: loadFlow2 } = await import("./flow-runner-SU4JHSZW.js");
782
+ const { loadFlow: loadFlow2 } = await import("./flow-runner-SHV6JPE6.js");
782
783
  const subFlow = loadFlow2(resolvedKey);
783
784
  const subContext = await executeFlow(
784
785
  subFlow,
@@ -4,7 +4,7 @@ import {
4
4
  loadFlow,
5
5
  resolveFlowPath,
6
6
  saveFlow
7
- } from "./chunk-CTL2YHUH.js";
7
+ } from "./chunk-SIZK6EAM.js";
8
8
  export {
9
9
  FlowRunner,
10
10
  listFlows,
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  loadFlow,
12
12
  resolveFlowPath,
13
13
  saveFlow
14
- } from "./chunk-CTL2YHUH.js";
14
+ } from "./chunk-SIZK6EAM.js";
15
15
 
16
16
  // src/index.ts
17
17
  import { createRequire as createRequire2 } from "module";
@@ -101,6 +101,22 @@ function getAccessControlFromAllSources() {
101
101
  function getAccessControl() {
102
102
  return readConfig()?.accessControl ?? {};
103
103
  }
104
+ var DEFAULT_API_BASE = "https://api.withone.ai/v1";
105
+ function getApiBase() {
106
+ const config = readConfig();
107
+ if (config?.apiBase) return `${config.apiBase}/v1`;
108
+ return DEFAULT_API_BASE;
109
+ }
110
+ function updateApiBase(url) {
111
+ const config = readConfig();
112
+ if (!config) return;
113
+ if (url) {
114
+ config.apiBase = url;
115
+ } else {
116
+ delete config.apiBase;
117
+ }
118
+ writeConfig(config);
119
+ }
104
120
  function getCacheTtl() {
105
121
  if (process.env.ONE_CACHE_TTL) {
106
122
  const val = parseInt(process.env.ONE_CACHE_TTL, 10);
@@ -465,6 +481,113 @@ async function configCommand() {
465
481
  p2.outro("No changes made.");
466
482
  return;
467
483
  }
484
+ const currentBase = getApiBase();
485
+ const isCustomBase = !!readConfig()?.apiBase;
486
+ const baseUrlMode = await p2.select({
487
+ message: "API base URL",
488
+ options: [
489
+ { value: "default", label: "Default", hint: "https://api.withone.ai" },
490
+ { value: "custom", label: "Custom", hint: "Use a different API endpoint" }
491
+ ],
492
+ initialValue: isCustomBase ? "custom" : "default"
493
+ });
494
+ if (p2.isCancel(baseUrlMode)) {
495
+ p2.outro("No changes made.");
496
+ return;
497
+ }
498
+ let newApiKey = config.apiKey;
499
+ if (baseUrlMode === "custom") {
500
+ const customUrl = await p2.text({
501
+ message: "Enter API base URL:",
502
+ placeholder: "https://development-api.withone.ai",
503
+ initialValue: isCustomBase ? currentBase.replace(/\/v1$/, "") : "",
504
+ validate: (value) => {
505
+ if (!value) return "URL is required";
506
+ try {
507
+ new URL(value);
508
+ } catch {
509
+ return "Invalid URL";
510
+ }
511
+ return void 0;
512
+ }
513
+ });
514
+ if (p2.isCancel(customUrl)) {
515
+ p2.outro("No changes made.");
516
+ return;
517
+ }
518
+ const normalized = customUrl.replace(/\/+$/, "").replace(/\/v1$/, "");
519
+ const apiKey = await p2.text({
520
+ message: `Enter your API key for ${pc.cyan(normalized)}:`,
521
+ placeholder: "sk_live_...",
522
+ validate: (value) => {
523
+ if (!value) return "API key is required";
524
+ if (!value.startsWith("sk_live_") && !value.startsWith("sk_test_")) {
525
+ return "API key should start with sk_live_ or sk_test_";
526
+ }
527
+ return void 0;
528
+ }
529
+ });
530
+ if (p2.isCancel(apiKey)) {
531
+ p2.outro("No changes made.");
532
+ return;
533
+ }
534
+ const spinner5 = p2.spinner();
535
+ spinner5.start("Validating API key...");
536
+ let isValid = false;
537
+ try {
538
+ const api = new OneApi(apiKey, `${normalized}/v1`);
539
+ isValid = await api.validateApiKey();
540
+ } catch (err) {
541
+ spinner5.stop("Connection failed");
542
+ const msg = err instanceof Error ? err.message : String(err);
543
+ p2.log.error(`Could not reach ${pc.cyan(normalized)}: ${msg}`);
544
+ return;
545
+ }
546
+ if (!isValid) {
547
+ spinner5.stop("Invalid API key");
548
+ p2.log.error(`Invalid API key for ${pc.cyan(normalized)}.`);
549
+ return;
550
+ }
551
+ spinner5.stop("API key validated");
552
+ updateApiBase(normalized);
553
+ newApiKey = apiKey;
554
+ } else if (isCustomBase) {
555
+ const apiKey = await p2.text({
556
+ message: `Enter your API key for ${pc.cyan("https://api.withone.ai")}:`,
557
+ placeholder: "sk_live_...",
558
+ validate: (value) => {
559
+ if (!value) return "API key is required";
560
+ if (!value.startsWith("sk_live_") && !value.startsWith("sk_test_")) {
561
+ return "API key should start with sk_live_ or sk_test_";
562
+ }
563
+ return void 0;
564
+ }
565
+ });
566
+ if (p2.isCancel(apiKey)) {
567
+ p2.outro("No changes made.");
568
+ return;
569
+ }
570
+ const spinner5 = p2.spinner();
571
+ spinner5.start("Validating API key...");
572
+ let isValid = false;
573
+ try {
574
+ const api = new OneApi(apiKey, "https://api.withone.ai/v1");
575
+ isValid = await api.validateApiKey();
576
+ } catch (err) {
577
+ spinner5.stop("Connection failed");
578
+ const msg = err instanceof Error ? err.message : String(err);
579
+ p2.log.error(`Could not reach ${pc.cyan("https://api.withone.ai")}: ${msg}`);
580
+ return;
581
+ }
582
+ if (!isValid) {
583
+ spinner5.stop("Invalid API key");
584
+ p2.log.error(`Invalid API key. Get a valid key at ${getApiKeyUrl()}`);
585
+ return;
586
+ }
587
+ spinner5.stop("API key validated");
588
+ updateApiBase(null);
589
+ newApiKey = apiKey;
590
+ }
468
591
  const settings = {
469
592
  permissions,
470
593
  connectionKeys: connectionKeys ?? ["*"],
@@ -472,30 +595,35 @@ async function configCommand() {
472
595
  knowledgeAgent
473
596
  };
474
597
  updateAccessControl(settings);
598
+ const updatedConfig = readConfig();
599
+ if (updatedConfig && newApiKey !== config.apiKey) {
600
+ updatedConfig.apiKey = newApiKey;
601
+ writeConfig(updatedConfig);
602
+ }
475
603
  const ac = getAccessControl();
476
604
  const statuses = getAgentStatuses();
477
605
  const reinstalled = [];
478
606
  for (const s of statuses) {
479
607
  if (s.globalMcp) {
480
- installMcpConfig(s.agent, config.apiKey, "global", ac);
608
+ installMcpConfig(s.agent, newApiKey, "global", ac);
481
609
  reinstalled.push(`${s.agent.name} (global)`);
482
610
  }
483
611
  if (s.projectMcp) {
484
- installMcpConfig(s.agent, config.apiKey, "project", ac);
612
+ installMcpConfig(s.agent, newApiKey, "project", ac);
485
613
  reinstalled.push(`${s.agent.name} (project)`);
486
614
  }
487
615
  }
488
616
  if (reinstalled.length > 0) {
489
617
  p2.log.success(`Updated MCP configs: ${reinstalled.join(", ")}`);
490
618
  }
491
- p2.outro("Access control updated.");
619
+ p2.outro("Configuration updated.");
492
620
  }
493
621
  async function selectConnections(apiKey) {
494
622
  const spinner5 = p2.spinner();
495
623
  spinner5.start("Fetching connections...");
496
624
  let connections;
497
625
  try {
498
- const api = new OneApi(apiKey);
626
+ const api = new OneApi(apiKey, getApiBase());
499
627
  const rawConnections = await api.listConnections();
500
628
  connections = rawConnections.map((c) => ({ platform: c.platform, key: c.key }));
501
629
  spinner5.stop(`Found ${connections.length} connection(s)`);
@@ -665,7 +793,7 @@ ${pc2.cyan(getApiKeyUrl())}`, "API Key");
665
793
  }
666
794
  const spinner5 = p3.spinner();
667
795
  spinner5.start("Validating API key...");
668
- const api = new OneApi(newKey);
796
+ const api = new OneApi(newKey, getApiBase());
669
797
  const isValid = await api.validateApiKey();
670
798
  if (!isValid) {
671
799
  spinner5.stop("Invalid API key");
@@ -884,7 +1012,7 @@ ${pc2.cyan(getApiKeyUrl())}`, "API Key");
884
1012
  }
885
1013
  const spinner5 = p3.spinner();
886
1014
  spinner5.start("Validating API key...");
887
- const api = new OneApi(apiKey);
1015
+ const api = new OneApi(apiKey, getApiBase());
888
1016
  const isValid = await api.validateApiKey();
889
1017
  if (!isValid) {
890
1018
  spinner5.stop("Invalid API key");
@@ -928,7 +1056,7 @@ var TOP_INTEGRATIONS = [
928
1056
  { value: "notion", label: "Notion", hint: "Access pages, databases, and docs" }
929
1057
  ];
930
1058
  async function promptConnectIntegrations(apiKey) {
931
- const api = new OneApi(apiKey);
1059
+ const api = new OneApi(apiKey, getApiBase());
932
1060
  const connected = [];
933
1061
  try {
934
1062
  const existing = await api.listConnections();
@@ -1090,7 +1218,7 @@ async function connectionAddCommand(platformArg) {
1090
1218
  p4.cancel("Not configured. Run `one init` first.");
1091
1219
  process.exit(1);
1092
1220
  }
1093
- const api = new OneApi(apiKey);
1221
+ const api = new OneApi(apiKey, getApiBase());
1094
1222
  const spinner5 = p4.spinner();
1095
1223
  spinner5.start("Loading platforms...");
1096
1224
  let platforms;
@@ -1194,7 +1322,7 @@ async function connectionListCommand(options) {
1194
1322
  if (!apiKey) {
1195
1323
  error("Not configured. Run `one init` first.");
1196
1324
  }
1197
- const api = new OneApi(apiKey);
1325
+ const api = new OneApi(apiKey, getApiBase());
1198
1326
  const spinner5 = createSpinner();
1199
1327
  spinner5.start("Loading connections...");
1200
1328
  try {
@@ -1290,7 +1418,7 @@ async function platformsCommand(options) {
1290
1418
  if (isAgentMode()) {
1291
1419
  options.json = true;
1292
1420
  }
1293
- const api = new OneApi(apiKey);
1421
+ const api = new OneApi(apiKey, getApiBase());
1294
1422
  const spinner5 = createSpinner();
1295
1423
  spinner5.start("Loading platforms...");
1296
1424
  try {
@@ -1498,7 +1626,7 @@ function parseJsonArg(value, argName) {
1498
1626
  async function actionsSearchCommand(platform, query, options) {
1499
1627
  intro2(pc6.bgCyan(pc6.black(" One ")));
1500
1628
  const { apiKey, permissions, actionIds, knowledgeAgent } = getConfig();
1501
- const api = new OneApi(apiKey);
1629
+ const api = new OneApi(apiKey, getApiBase());
1502
1630
  const spinner5 = createSpinner();
1503
1631
  spinner5.start(`Searching actions on ${pc6.cyan(platform)} for "${query}"...`);
1504
1632
  try {
@@ -1640,7 +1768,7 @@ async function actionsKnowledgeCommand(platform, actionId, options) {
1640
1768
  }
1641
1769
  intro2(pc6.bgCyan(pc6.black(" One ")));
1642
1770
  const { apiKey, actionIds, connectionKeys } = getConfig();
1643
- const api = new OneApi(apiKey);
1771
+ const api = new OneApi(apiKey, getApiBase());
1644
1772
  if (!isActionAllowed(actionId, actionIds)) {
1645
1773
  error(`Action "${actionId}" is not in the allowed action list.`);
1646
1774
  }
@@ -1747,7 +1875,7 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
1747
1875
  if (!connectionKeys.includes("*") && !connectionKeys.includes(connectionKey)) {
1748
1876
  error(`Connection key "${connectionKey}" is not allowed.`);
1749
1877
  }
1750
- const api = new OneApi(apiKey);
1878
+ const api = new OneApi(apiKey, getApiBase());
1751
1879
  const spinner5 = createSpinner();
1752
1880
  spinner5.start("Loading action details...");
1753
1881
  try {
@@ -2746,7 +2874,7 @@ Execute: ${pc7.cyan(`one flow execute ${flow2.key}`)}`);
2746
2874
  async function flowExecuteCommand(keyOrPath, options) {
2747
2875
  intro2(pc7.bgCyan(pc7.black(" One Workflow ")));
2748
2876
  const { apiKey, permissions, actionIds } = getConfig2();
2749
- const api = new OneApi(apiKey);
2877
+ const api = new OneApi(apiKey, getApiBase());
2750
2878
  const spinner5 = createSpinner();
2751
2879
  spinner5.start(`Loading workflow "${keyOrPath}"...`);
2752
2880
  let flow2;
@@ -2918,7 +3046,7 @@ async function flowResumeCommand(runId) {
2918
3046
  error(`Run "${runId}" is ${state.status} \u2014 can only resume paused or failed runs`);
2919
3047
  }
2920
3048
  const { apiKey, permissions, actionIds } = getConfig2();
2921
- const api = new OneApi(apiKey);
3049
+ const api = new OneApi(apiKey, getApiBase());
2922
3050
  let flow2;
2923
3051
  try {
2924
3052
  flow2 = loadFlow(state.flowKey);
@@ -3236,7 +3364,7 @@ async function relayCreateCommand(options) {
3236
3364
  if (!connectionKeys.includes("*") && !connectionKeys.includes(options.connectionKey)) {
3237
3365
  error(`Connection key "${options.connectionKey}" is not allowed.`);
3238
3366
  }
3239
- const api = new OneApi(apiKey);
3367
+ const api = new OneApi(apiKey, getApiBase());
3240
3368
  const spinner5 = createSpinner();
3241
3369
  spinner5.start("Creating relay endpoint...");
3242
3370
  try {
@@ -3268,7 +3396,7 @@ async function relayCreateCommand(options) {
3268
3396
  }
3269
3397
  async function relayListCommand(options) {
3270
3398
  const { apiKey } = getConfig3();
3271
- const api = new OneApi(apiKey);
3399
+ const api = new OneApi(apiKey, getApiBase());
3272
3400
  const spinner5 = createSpinner();
3273
3401
  spinner5.start("Loading relay endpoints...");
3274
3402
  try {
@@ -3315,7 +3443,7 @@ async function relayListCommand(options) {
3315
3443
  }
3316
3444
  async function relayGetCommand(id) {
3317
3445
  const { apiKey } = getConfig3();
3318
- const api = new OneApi(apiKey);
3446
+ const api = new OneApi(apiKey, getApiBase());
3319
3447
  const spinner5 = createSpinner();
3320
3448
  spinner5.start("Loading relay endpoint...");
3321
3449
  try {
@@ -3346,7 +3474,7 @@ async function relayGetCommand(id) {
3346
3474
  }
3347
3475
  async function relayUpdateCommand(id, options) {
3348
3476
  const { apiKey } = getConfig3();
3349
- const api = new OneApi(apiKey);
3477
+ const api = new OneApi(apiKey, getApiBase());
3350
3478
  const spinner5 = createSpinner();
3351
3479
  spinner5.start("Updating relay endpoint...");
3352
3480
  try {
@@ -3373,7 +3501,7 @@ async function relayUpdateCommand(id, options) {
3373
3501
  }
3374
3502
  async function relayDeleteCommand(id) {
3375
3503
  const { apiKey } = getConfig3();
3376
- const api = new OneApi(apiKey);
3504
+ const api = new OneApi(apiKey, getApiBase());
3377
3505
  const spinner5 = createSpinner();
3378
3506
  spinner5.start("Deleting relay endpoint...");
3379
3507
  try {
@@ -3392,7 +3520,7 @@ async function relayDeleteCommand(id) {
3392
3520
  }
3393
3521
  async function relayActivateCommand(id, options) {
3394
3522
  const { apiKey } = getConfig3();
3395
- const api = new OneApi(apiKey);
3523
+ const api = new OneApi(apiKey, getApiBase());
3396
3524
  const spinner5 = createSpinner();
3397
3525
  spinner5.start("Activating relay endpoint...");
3398
3526
  try {
@@ -3416,7 +3544,7 @@ async function relayActivateCommand(id, options) {
3416
3544
  }
3417
3545
  async function relayEventsCommand(options) {
3418
3546
  const { apiKey } = getConfig3();
3419
- const api = new OneApi(apiKey);
3547
+ const api = new OneApi(apiKey, getApiBase());
3420
3548
  const spinner5 = createSpinner();
3421
3549
  spinner5.start("Loading relay events...");
3422
3550
  try {
@@ -3463,7 +3591,7 @@ async function relayEventsCommand(options) {
3463
3591
  }
3464
3592
  async function relayEventGetCommand(id) {
3465
3593
  const { apiKey } = getConfig3();
3466
- const api = new OneApi(apiKey);
3594
+ const api = new OneApi(apiKey, getApiBase());
3467
3595
  const spinner5 = createSpinner();
3468
3596
  spinner5.start("Loading relay event...");
3469
3597
  try {
@@ -3491,7 +3619,7 @@ async function relayDeliveriesCommand(options) {
3491
3619
  error("Provide either --endpoint-id or --event-id");
3492
3620
  }
3493
3621
  const { apiKey } = getConfig3();
3494
- const api = new OneApi(apiKey);
3622
+ const api = new OneApi(apiKey, getApiBase());
3495
3623
  const spinner5 = createSpinner();
3496
3624
  spinner5.start("Loading deliveries...");
3497
3625
  try {
@@ -3523,7 +3651,7 @@ async function relayDeliveriesCommand(options) {
3523
3651
  }
3524
3652
  async function relayEventTypesCommand(platform) {
3525
3653
  const { apiKey } = getConfig3();
3526
- const api = new OneApi(apiKey);
3654
+ const api = new OneApi(apiKey, getApiBase());
3527
3655
  const spinner5 = createSpinner();
3528
3656
  spinner5.start(`Loading event types for ${pc8.cyan(platform)}...`);
3529
3657
  try {
@@ -3616,7 +3744,7 @@ async function cacheUpdateAllCommand() {
3616
3744
  if (!apiKey) {
3617
3745
  error("Not configured. Run `one init` first.");
3618
3746
  }
3619
- const api = new OneApi(apiKey);
3747
+ const api = new OneApi(apiKey, getApiBase());
3620
3748
  const entries = listCacheEntries();
3621
3749
  if (entries.length === 0) {
3622
3750
  if (isAgentMode()) {
@@ -4119,7 +4247,7 @@ async function onboardCommand(step) {
4119
4247
  let connections = [];
4120
4248
  if (currentStep >= 2) {
4121
4249
  try {
4122
- const api = new OneApi(apiKey);
4250
+ const api = new OneApi(apiKey, getApiBase());
4123
4251
  connections = await api.listConnections();
4124
4252
  } catch {
4125
4253
  }
@@ -4452,6 +4580,14 @@ async function updateCommand() {
4452
4580
  error("Update failed \u2014 try running: npm install -g @withone/cli@latest");
4453
4581
  }
4454
4582
  }
4583
+ function isNewerVersion(latest, current) {
4584
+ const parse = (v) => v.split(".").map(Number);
4585
+ const [lMaj, lMin, lPat] = parse(latest);
4586
+ const [cMaj, cMin, cPat] = parse(current);
4587
+ if (lMaj !== cMaj) return lMaj > cMaj;
4588
+ if (lMin !== cMin) return lMin > cMin;
4589
+ return lPat > cPat;
4590
+ }
4455
4591
  function autoUpdate(targetVersion, publishedAt) {
4456
4592
  if (publishedAt) {
4457
4593
  const age = Date.now() - new Date(publishedAt).getTime();
@@ -4535,7 +4671,7 @@ program.hook("postAction", async () => {
4535
4671
  const info = await updateCheckPromise;
4536
4672
  if (!info) return;
4537
4673
  const current = getCurrentVersion();
4538
- if (current === info.version) return;
4674
+ if (!isNewerVersion(info.version, current)) return;
4539
4675
  autoUpdate(info.version, info.publishedAt);
4540
4676
  });
4541
4677
  program.command("init").description("Set up One and install MCP to your AI agents").option("-y, --yes", "Skip confirmations").option("-g, --global", "Install MCP globally (available in all projects)").option("-p, --project", "Install MCP for this project only (creates .mcp.json)").action(async (options) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@withone/cli",
3
- "version": "1.18.0",
3
+ "version": "1.19.0",
4
4
  "description": "CLI for managing One",
5
5
  "type": "module",
6
6
  "files": [