@withone/cli 1.34.0 → 1.36.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 CHANGED
@@ -39,7 +39,14 @@ npm install -g @withone/cli
39
39
  one init
40
40
  ```
41
41
 
42
- `one init` walks you through setup: enter your [API key](https://app.withone.ai/settings/api-keys), pick your AI agents, and you're done. The MCP server gets installed automatically.
42
+ `one init` walks you through setup: authenticate via browser or enter your [API key](https://app.withone.ai/settings/api-keys), pick your AI agents, and you're done. The MCP server gets installed automatically.
43
+
44
+ Or authenticate directly:
45
+
46
+ ```bash
47
+ one login # Opens browser for authentication (global or per-directory)
48
+ one logout # Clear credentials (with scope picker and confirmation)
49
+ ```
43
50
 
44
51
  Requires Node.js 18+.
45
52
 
@@ -248,6 +255,7 @@ one actions execute stripe <actionId> <connectionKey> \
248
255
  | `--dry-run` | Show the request without executing it |
249
256
  | `--mock` | Return example response without making an API call |
250
257
  | `--skip-validation` | Skip input validation against the action schema |
258
+ | `--output <path>` | Save response to a file (for binary downloads) |
251
259
 
252
260
  The CLI validates required parameters (path variables, query params, body fields) against the action schema before executing. Missing params return a clear error with the flag name and description. Pass `--skip-validation` to bypass.
253
261
 
@@ -11,6 +11,10 @@ import { exec, spawn } from "child_process";
11
11
  import { promisify } from "util";
12
12
 
13
13
  // src/lib/api.ts
14
+ import { createWriteStream } from "fs";
15
+ import { resolve } from "path";
16
+ import { pipeline } from "stream/promises";
17
+ import { Readable } from "stream";
14
18
  var ApiError = class extends Error {
15
19
  constructor(status, message, retryAfterSeconds) {
16
20
  super(message);
@@ -328,12 +332,45 @@ var OneApi = class {
328
332
  const text = await response.text();
329
333
  throw new ApiError(response.status, text || `HTTP ${response.status}`);
330
334
  }
335
+ const responseContentType = response.headers.get("content-type") || "";
336
+ const isExplicitJson = responseContentType.includes("application/json") || responseContentType.includes("text/");
337
+ if (isExplicitJson || !responseContentType) {
338
+ const responseText2 = await response.text();
339
+ const responseData = responseText2 ? JSON.parse(responseText2) : {};
340
+ return { requestConfig: sanitizedConfig, responseData };
341
+ }
342
+ if (args.output) {
343
+ const outputPath = resolve(args.output);
344
+ const body = response.body;
345
+ if (!body) {
346
+ throw new ApiError(0, "Response body is null \u2014 cannot save to file");
347
+ }
348
+ const nodeReadable = Readable.fromWeb(body);
349
+ await pipeline(nodeReadable, createWriteStream(outputPath));
350
+ const contentLength = response.headers.get("content-length");
351
+ const size = contentLength ? parseInt(contentLength, 10) : void 0;
352
+ return {
353
+ requestConfig: sanitizedConfig,
354
+ responseData: { saved: true, path: outputPath, size, contentType: responseContentType }
355
+ };
356
+ }
331
357
  const responseText = await response.text();
332
- const responseData = responseText ? JSON.parse(responseText) : {};
333
- return {
334
- requestConfig: sanitizedConfig,
335
- responseData
336
- };
358
+ try {
359
+ const responseData = responseText ? JSON.parse(responseText) : {};
360
+ return { requestConfig: sanitizedConfig, responseData };
361
+ } catch {
362
+ const contentLength = response.headers.get("content-length");
363
+ const size = contentLength ? parseInt(contentLength, 10) : responseText.length;
364
+ return {
365
+ requestConfig: sanitizedConfig,
366
+ responseData: {
367
+ binary: true,
368
+ size,
369
+ contentType: responseContentType,
370
+ message: "Binary response received. Use --output <path> to save to a file."
371
+ }
372
+ };
373
+ }
337
374
  }
338
375
  // Webhook Relay methods
339
376
  async createRelayEndpoint(body) {
@@ -394,7 +431,7 @@ var TimeoutError = class extends Error {
394
431
  }
395
432
  };
396
433
  function sleep(ms) {
397
- return new Promise((resolve) => setTimeout(resolve, ms));
434
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
398
435
  }
399
436
  function replacePathVariables(path3, variables) {
400
437
  if (!path3) return path3;
@@ -532,7 +569,7 @@ function setByDotPath(obj, dotPath, value) {
532
569
  // src/lib/flow-engine.ts
533
570
  var execAsync = promisify(exec);
534
571
  function sleep2(ms) {
535
- return new Promise((resolve) => setTimeout(resolve, ms));
572
+ return new Promise((resolve2) => setTimeout(resolve2, ms));
536
573
  }
537
574
  var StepTimeoutError = class extends Error {
538
575
  errorCode = "TIMEOUT";
@@ -843,7 +880,7 @@ async function executeCodeModule(stepId, modulePath, context, options) {
843
880
  const { env: _omitEnv, ...safeContext } = context;
844
881
  void _omitEnv;
845
882
  const stdinPayload = JSON.stringify(safeContext);
846
- return await new Promise((resolve, reject) => {
883
+ return await new Promise((resolve2, reject) => {
847
884
  const child = spawn(process.execPath, [absPath], {
848
885
  cwd: rootDir,
849
886
  stdio: ["pipe", "pipe", "pipe"]
@@ -862,11 +899,11 @@ async function executeCodeModule(stepId, modulePath, context, options) {
862
899
  }
863
900
  const trimmed = stdout.trim();
864
901
  if (trimmed === "") {
865
- resolve(void 0);
902
+ resolve2(void 0);
866
903
  return;
867
904
  }
868
905
  try {
869
- resolve(JSON.parse(stripCodeFences(trimmed)));
906
+ resolve2(JSON.parse(stripCodeFences(trimmed)));
870
907
  } catch (err) {
871
908
  reject(new Error(`Code module "${modulePath}" did not print valid JSON to stdout: ${err.message}`));
872
909
  }
@@ -1042,7 +1079,7 @@ async function executeSubflowStep(step, context, api, permissions, allowedAction
1042
1079
  if (flowStack.includes(resolvedKey)) {
1043
1080
  throw new Error(`Circular flow detected: ${[...flowStack, resolvedKey].join(" \u2192 ")}`);
1044
1081
  }
1045
- const { loadFlowWithMeta: loadFlowWithMeta2 } = await import("./flow-runner-TNI7YWVY.js");
1082
+ const { loadFlowWithMeta: loadFlowWithMeta2 } = await import("./flow-runner-OVOGDXNR.js");
1046
1083
  const { flow: subFlow, rootDir: subRootDir } = loadFlowWithMeta2(resolvedKey);
1047
1084
  const subContext = await executeFlow(
1048
1085
  subFlow,
@@ -11,7 +11,7 @@ import {
11
11
  saveFlow,
12
12
  summarizeFlowInputs,
13
13
  walkSteps
14
- } from "./chunk-HZP7NT4K.js";
14
+ } from "./chunk-MNJJE4PJ.js";
15
15
  export {
16
16
  FlowRunner,
17
17
  collectStepTypes,