@withone/cli 1.47.0 → 1.47.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -488,6 +488,9 @@ Press Ctrl+C during execution to pause - the run can be resumed later with `one
488
488
  | `--skip-validation` | Skip input validation against action schemas |
489
489
  | `--allow-bash` | Allow bash step execution (disabled by default for security) |
490
490
  | `-v, --verbose` | Show full request/response for each step |
491
+ | `--output-file <path>` | Stream the full result to a file instead of stdout — for large results that would otherwise be truncated or exceed the JSON string-size limit. stdout (and `--agent` output) then carries an `outputFile` pointer instead of inline `steps`. |
492
+
493
+ Step-level `if`/`unless` conditions (and `while`/`condition` steps) are null-safe: a condition that references a skipped or not-yet-run step's output (e.g. `$.steps.maybeSkipped.output.x`) evaluates to `false` rather than crashing the run.
491
494
 
492
495
  ### `one flow list`
493
496
 
@@ -15,6 +15,14 @@ function setAgentMode(value) {
15
15
  function isAgentMode() {
16
16
  return _agentMode || process.env.ONE_AGENT === "1";
17
17
  }
18
+ function silenceWarningsInAgentMode() {
19
+ const agent = process.argv.includes("--agent") || process.env.ONE_AGENT === "1";
20
+ if (!agent) return;
21
+ process.env.NODE_NO_WARNINGS = "1";
22
+ process.removeAllListeners("warning");
23
+ process.emitWarning = (() => {
24
+ });
25
+ }
18
26
  function createSpinner() {
19
27
  if (isAgentMode()) {
20
28
  return { start() {
@@ -141,6 +149,7 @@ function semanticSearchUpgradeLine(opts = {}) {
141
149
  export {
142
150
  setAgentMode,
143
151
  isAgentMode,
152
+ silenceWarningsInAgentMode,
144
153
  createSpinner,
145
154
  intro2 as intro,
146
155
  outro2 as outro,
@@ -902,6 +902,14 @@ function evaluateExpression(expr, context) {
902
902
  const fn = new Function("$", `return (${expr})`);
903
903
  return fn(context);
904
904
  }
905
+ function evaluateCondition(expr, context) {
906
+ try {
907
+ return Boolean(evaluateExpression(expr, context));
908
+ } catch (err) {
909
+ if (err instanceof TypeError) return false;
910
+ throw err;
911
+ }
912
+ }
905
913
  var ALLOWED_MODULES = {
906
914
  buffer: () => import("buffer"),
907
915
  crypto: () => import("crypto"),
@@ -1106,7 +1114,7 @@ async function executeCodeModule(stepId, modulePath, context, options) {
1106
1114
  }
1107
1115
  async function executeConditionStep(step, context, api, permissions, allowedActionIds, options, flowStack) {
1108
1116
  const condition = step.condition;
1109
- const result = evaluateExpression(condition.expression, context);
1117
+ const result = evaluateCondition(condition.expression, context);
1110
1118
  const branch = result ? condition.then : condition.else || [];
1111
1119
  const branchResults = await executeSteps(branch, context, api, permissions, allowedActionIds, options, void 0, flowStack);
1112
1120
  return {
@@ -1246,7 +1254,7 @@ async function executeWhileStep(step, context, api, permissions, allowedActionId
1246
1254
  };
1247
1255
  for (let iteration = 0; iteration < maxIterations; iteration++) {
1248
1256
  if (iteration > 0) {
1249
- const conditionResult = evaluateExpression(config.condition, context);
1257
+ const conditionResult = evaluateCondition(config.condition, context);
1250
1258
  if (!conditionResult) break;
1251
1259
  }
1252
1260
  await executeSteps(config.steps, context, api, permissions, allowedActionIds, options, void 0, flowStack);
@@ -1271,7 +1279,7 @@ async function executeSubflowStep(step, context, api, permissions, allowedAction
1271
1279
  if (flowStack.includes(resolvedKey)) {
1272
1280
  throw new Error(`Circular flow detected: ${[...flowStack, resolvedKey].join(" \u2192 ")}`);
1273
1281
  }
1274
- const { loadFlowWithMeta: loadFlowWithMeta2 } = await import("./flow-runner-UWIM4Z2Y.js");
1282
+ const { loadFlowWithMeta: loadFlowWithMeta2 } = await import("./flow-runner-7YOPMXWO.js");
1275
1283
  const { flow: subFlow, rootDir: subRootDir } = loadFlowWithMeta2(resolvedKey);
1276
1284
  const subContext = await executeFlow(
1277
1285
  subFlow,
@@ -1468,7 +1476,7 @@ function checkRequires(step, context) {
1468
1476
  }
1469
1477
  async function executeSingleStep(step, context, api, permissions, allowedActionIds, options, flowStack = []) {
1470
1478
  if (step.if) {
1471
- const condResult = evaluateExpression(step.if, context);
1479
+ const condResult = evaluateCondition(step.if, context);
1472
1480
  if (!condResult) {
1473
1481
  const result = { status: "skipped" };
1474
1482
  context.steps[step.id] = result;
@@ -1476,7 +1484,7 @@ async function executeSingleStep(step, context, api, permissions, allowedActionI
1476
1484
  }
1477
1485
  }
1478
1486
  if (step.unless) {
1479
- const condResult = evaluateExpression(step.unless, context);
1487
+ const condResult = evaluateCondition(step.unless, context);
1480
1488
  if (condResult) {
1481
1489
  const result = { status: "skipped" };
1482
1490
  context.steps[step.id] = result;
@@ -6,7 +6,7 @@ import {
6
6
  note,
7
7
  okJson,
8
8
  requireMemoryInit
9
- } from "./chunk-Q3OY2F6W.js";
9
+ } from "./chunk-HS5AHQ4V.js";
10
10
  import {
11
11
  getBackend,
12
12
  upsertRecord
@@ -3,7 +3,7 @@ import {
3
3
  isAgentMode,
4
4
  json,
5
5
  requireMemoryInit
6
- } from "./chunk-Q3OY2F6W.js";
6
+ } from "./chunk-HS5AHQ4V.js";
7
7
  import {
8
8
  getBackend
9
9
  } from "./chunk-OADHUAEU.js";
@@ -11,7 +11,7 @@ import {
11
11
  saveFlow,
12
12
  summarizeFlowInputs,
13
13
  walkSteps
14
- } from "./chunk-5NLP47QP.js";
14
+ } from "./chunk-IFTHWFLL.js";
15
15
  import "./chunk-44CV5IMX.js";
16
16
  import "./chunk-K6MWE2ZH.js";
17
17
  export {
package/dist/index.js CHANGED
@@ -30,10 +30,10 @@ import {
30
30
  searchCachePath,
31
31
  validateActionInput,
32
32
  writeCache
33
- } from "./chunk-5NLP47QP.js";
33
+ } from "./chunk-IFTHWFLL.js";
34
34
  import {
35
35
  memSqlCommand
36
- } from "./chunk-CESNNUKJ.js";
36
+ } from "./chunk-QV3Y5N5G.js";
37
37
  import {
38
38
  countRecords,
39
39
  deleteDatabase,
@@ -58,7 +58,7 @@ import {
58
58
  upsertRecords,
59
59
  writeDraftProfile,
60
60
  writeProfile
61
- } from "./chunk-4RZSK5LD.js";
61
+ } from "./chunk-PLMFRFTT.js";
62
62
  import {
63
63
  getByDotPath
64
64
  } from "./chunk-44CV5IMX.js";
@@ -80,8 +80,9 @@ import {
80
80
  requireMemoryInit,
81
81
  semanticSearchUpgradeHint,
82
82
  semanticSearchUpgradeLine,
83
- setAgentMode
84
- } from "./chunk-Q3OY2F6W.js";
83
+ setAgentMode,
84
+ silenceWarningsInAgentMode
85
+ } from "./chunk-HS5AHQ4V.js";
85
86
  import {
86
87
  SCHEMA_VERSION,
87
88
  addRecord,
@@ -3653,6 +3654,26 @@ function validateCodeModules(flow2, rootDir) {
3653
3654
  // src/commands/flow.ts
3654
3655
  import fs5 from "fs";
3655
3656
  import path5 from "path";
3657
+ async function writeFlowResultFile(filePath, meta, steps) {
3658
+ const abs = path5.resolve(filePath);
3659
+ const ws = fs5.createWriteStream(abs);
3660
+ const done = new Promise((resolve, reject) => {
3661
+ ws.on("finish", () => resolve());
3662
+ ws.on("error", reject);
3663
+ });
3664
+ ws.write(
3665
+ `{"event":"workflow:result","runId":${JSON.stringify(meta.runId)},"logFile":${JSON.stringify(meta.logFile)},"status":${JSON.stringify(meta.status)},"steps":{`
3666
+ );
3667
+ let first = true;
3668
+ for (const [id, result] of Object.entries(steps)) {
3669
+ ws.write(`${first ? "" : ","}${JSON.stringify(id)}:${JSON.stringify(result)}`);
3670
+ first = false;
3671
+ }
3672
+ ws.write("}}");
3673
+ ws.end();
3674
+ await done;
3675
+ return abs;
3676
+ }
3656
3677
  function getConfig2() {
3657
3678
  const apiKey = getApiKey();
3658
3679
  if (!apiKey) {
@@ -3853,16 +3874,16 @@ ${pc7.yellow("Pausing after current step completes...")} (run ID: ${runId})`);
3853
3874
  if (!options.verbose && !isAgentMode()) {
3854
3875
  execSpinner.stop("Workflow completed");
3855
3876
  }
3877
+ const resultFile = options.outputFile ? await writeFlowResultFile(options.outputFile, { runId, logFile: logPath, status: "success" }, context.steps) : void 0;
3856
3878
  if (isAgentMode()) {
3857
- json({
3858
- event: "workflow:result",
3859
- runId,
3860
- logFile: logPath,
3861
- status: "success",
3862
- steps: context.steps
3863
- });
3879
+ json(
3880
+ resultFile ? { event: "workflow:result", runId, logFile: logPath, status: "success", outputFile: resultFile } : { event: "workflow:result", runId, logFile: logPath, status: "success", steps: context.steps }
3881
+ );
3864
3882
  return;
3865
3883
  }
3884
+ if (resultFile) {
3885
+ note(`Full result written to ${resultFile}`, "Output");
3886
+ }
3866
3887
  const stepEntries = Object.entries(context.steps);
3867
3888
  const succeeded = stepEntries.filter(([, r]) => r.status === "success").length;
3868
3889
  const failed = stepEntries.filter(([, r]) => r.status === "failed").length;
@@ -7799,7 +7820,7 @@ ${result.total} results`);
7799
7820
  }
7800
7821
  }
7801
7822
  async function syncSqlCommand(platformModel, sql) {
7802
- const { syncSqlCommand: runSyncSql } = await import("./sql-5XR53LV5.js");
7823
+ const { syncSqlCommand: runSyncSql } = await import("./sql-W3ZUOUNR.js");
7803
7824
  await runSyncSql(platformModel, sql);
7804
7825
  }
7805
7826
  async function syncDeleteCommand(platformModel, options) {
@@ -7893,7 +7914,7 @@ async function maybeAutoMigrateLegacy(platform, models) {
7893
7914
  ` detected legacy .one/sync/data/${platform}.db (${dbSize}) \u2014 auto-migrating into memory before sync.
7894
7915
  `
7895
7916
  );
7896
- const { memMigrateCommand: memMigrateCommand3 } = await import("./migrate-DHZ3SI65.js");
7917
+ const { memMigrateCommand: memMigrateCommand3 } = await import("./migrate-UDEANXEZ.js");
7897
7918
  await memMigrateCommand3({ platform, yes: true });
7898
7919
  return;
7899
7920
  }
@@ -7902,7 +7923,7 @@ async function maybeAutoMigrateLegacy(platform, models) {
7902
7923
  initialValue: true
7903
7924
  });
7904
7925
  if (p7.isCancel(shouldMigrate) || !shouldMigrate) return;
7905
- const { memMigrateCommand: memMigrateCommand2 } = await import("./migrate-DHZ3SI65.js");
7926
+ const { memMigrateCommand: memMigrateCommand2 } = await import("./migrate-UDEANXEZ.js");
7906
7927
  await memMigrateCommand2({ platform, yes: true });
7907
7928
  }
7908
7929
  async function syncSuggestSearchableCommand(platformModel, options = {}) {
@@ -9391,6 +9412,8 @@ one --agent flow list # List all workflows
9391
9412
  - AI analysis via bash steps: \`claude --print\` with \`parseJson: true\`
9392
9413
  - Use \`--allow-bash\` to enable bash steps, \`--mock\` for dry-run with realistic mock responses (uses example data from action schemas)
9393
9414
  - Use \`--skip-validation\` to bypass input validation on action steps
9415
+ - Use \`--output-file <path>\` to stream the full result to a file instead of stdout \u2014 for large results that would otherwise be truncated or hit the JSON string-size limit; stdout (and \`--agent\` output) then carries an \`outputFile\` pointer instead of inline \`steps\`
9416
+ - Step-level \`if\`/\`unless\` (and \`while\`/\`condition\` steps) are null-safe: a condition referencing a skipped or not-yet-run step's output (e.g. \`$.steps.maybeSkipped.output.x\`) evaluates to \`false\` instead of crashing the flow
9394
9417
 
9395
9418
  ### 3. Relay \u2014 Webhook event forwarding between platforms
9396
9419
  Receive webhooks from platforms (Stripe, GitHub, Airtable, Attio, Google Calendar) and forward event data to any connected platform using passthrough actions with Handlebars templates. No middleware, no code.
@@ -10968,6 +10991,7 @@ function maybeShowTelemetryNotice() {
10968
10991
  }
10969
10992
 
10970
10993
  // src/cli.ts
10994
+ silenceWarningsInAgentMode();
10971
10995
  var require4 = createRequire3(import.meta.url);
10972
10996
  var { version } = require4("../package.json");
10973
10997
  var program = new Command();
@@ -11283,7 +11307,7 @@ var flow = program.command("flow").alias("f").description("Create, execute, and
11283
11307
  flow.command("create [key]").description("Create a new workflow from JSON definition").option("--definition <json>", "Workflow definition as JSON string").option("-o, --output <path>", "Custom output path (default .one/flows/<key>/flow.json)").action(async (key, options) => {
11284
11308
  await flowCreateCommand(key, options);
11285
11309
  });
11286
- flow.command("execute <keyOrPath>").alias("x").description("Execute a workflow by key or file path").option("-i, --input <name=value>", "Input parameter (repeatable)", collect, []).option("--dry-run", "Validate and show execution plan without running").option("--mock", "With --dry-run: execute transforms/code with realistic mock API responses").option("--skip-validation", "Skip input validation against action schemas").option("--allow-bash", "Allow bash step execution (disabled by default for security)").option("-v, --verbose", "Show full request/response for each step").action(async (keyOrPath, options) => {
11310
+ flow.command("execute <keyOrPath>").alias("x").description("Execute a workflow by key or file path").option("-i, --input <name=value>", "Input parameter (repeatable)", collect, []).option("--dry-run", "Validate and show execution plan without running").option("--mock", "With --dry-run: execute transforms/code with realistic mock API responses").option("--skip-validation", "Skip input validation against action schemas").option("--allow-bash", "Allow bash step execution (disabled by default for security)").option("-v, --verbose", "Show full request/response for each step").option("--output-file <path>", "Write the full result to a file (streamed) instead of stdout \u2014 avoids truncation/string-limit errors for large results; stdout/agent output then carries an outputFile pointer").action(async (keyOrPath, options) => {
11287
11311
  await flowExecuteCommand(keyOrPath, options);
11288
11312
  });
11289
11313
  flow.command("list").alias("ls").description("List all workflows in .one/flows/").action(async () => {
@@ -3,9 +3,9 @@ import {
3
3
  dotPathToJsonbExpr,
4
4
  memMigrateCommand,
5
5
  reviveStringifiedJson
6
- } from "./chunk-4RZSK5LD.js";
6
+ } from "./chunk-PLMFRFTT.js";
7
7
  import "./chunk-44CV5IMX.js";
8
- import "./chunk-Q3OY2F6W.js";
8
+ import "./chunk-HS5AHQ4V.js";
9
9
  import "./chunk-OADHUAEU.js";
10
10
  import "./chunk-TXTRXV74.js";
11
11
  import "./chunk-K6MWE2ZH.js";
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  memSqlCommand,
3
3
  syncSqlCommand
4
- } from "./chunk-CESNNUKJ.js";
5
- import "./chunk-Q3OY2F6W.js";
4
+ } from "./chunk-QV3Y5N5G.js";
5
+ import "./chunk-HS5AHQ4V.js";
6
6
  import "./chunk-OADHUAEU.js";
7
7
  import "./chunk-TXTRXV74.js";
8
8
  import "./chunk-K6MWE2ZH.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@withone/cli",
3
- "version": "1.47.0",
3
+ "version": "1.47.1",
4
4
  "description": "CLI for managing One",
5
5
  "type": "module",
6
6
  "files": [
@@ -271,6 +271,10 @@ Selectors in data fields (`data`, `queryParams`, `pathVars`, `connectionKey`) ar
271
271
 
272
272
  The `if`, `unless`, `condition.expression`, `while.condition`, `transform.expression`, and `code.source` fields **do** support full JavaScript expressions (e.g., `$.input.email && $.input.email.length > 0`).
273
273
 
274
+ **Condition null-safety:** `if`/`unless`, `while.condition`, and `condition.expression` are null-safe. A condition that walks into a skipped or not-yet-run step's output — e.g. `$.steps.maybeSkipped.output.value` — evaluates to `false` instead of throwing `Cannot read properties of undefined`. (This applies to *conditions* only; `transform.expression` and `code.source` still throw on undefined access, since their output feeds downstream steps and should fail loudly.)
275
+
276
+ **Large results:** pass `--output-file <path>` to `flow execute` to stream the full result to a file instead of stdout. Use it when a flow aggregates large outputs that would otherwise be truncated on stdout or exceed the JSON string-size limit. stdout (and `--agent` output) then carries `{"event":"workflow:result", ..., "outputFile":"<path>"}` instead of inline `steps` — read the file for the full result.
277
+
274
278
  ## Step Types
275
279
 
276
280
  ### `action` — Execute a One API action