@withone/cli 1.55.0 → 1.55.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
@@ -587,8 +587,13 @@ Resume a paused or failed workflow run from where it left off.
587
587
 
588
588
  ```bash
589
589
  one flow resume abc123
590
+ one flow resume abc123 --allow-bash # required if the flow has bash steps
590
591
  ```
591
592
 
593
+ `--allow-bash` is gated the same way as on `flow execute` — resuming doesn't
594
+ inherit the permission from the original run, so pass it again. `one flow list`
595
+ shows which flows need it.
596
+
592
597
  ### `one flow runs [flowKey]`
593
598
 
594
599
  List workflow runs, optionally filtered by workflow key.
package/dist/index.js CHANGED
@@ -150,15 +150,15 @@ import {
150
150
 
151
151
  // src/cli.ts
152
152
  import { createRequire as createRequire3 } from "module";
153
- import path11 from "path";
153
+ import path12 from "path";
154
154
  import { Command } from "commander";
155
155
 
156
156
  // src/commands/init.ts
157
157
  import * as p3 from "@clack/prompts";
158
158
  import pc2 from "picocolors";
159
159
  import fs3 from "fs";
160
- import path3 from "path";
161
- import { fileURLToPath as fileURLToPath2 } from "url";
160
+ import path4 from "path";
161
+ import { fileURLToPath as fileURLToPath3 } from "url";
162
162
 
163
163
  // src/lib/agents.ts
164
164
  import fs from "fs";
@@ -649,16 +649,42 @@ import open2 from "open";
649
649
 
650
650
  // src/lib/skill-sync.ts
651
651
  import fs2 from "fs";
652
- import path2 from "path";
653
- import { fileURLToPath } from "url";
652
+ import path3 from "path";
653
+ import { fileURLToPath as fileURLToPath2 } from "url";
654
654
 
655
655
  // src/commands/update.ts
656
- import { createRequire } from "module";
657
656
  import { spawn } from "child_process";
658
657
  import { readFileSync, writeFileSync, mkdirSync, rmSync } from "fs";
659
658
  import { join } from "path";
659
+
660
+ // src/lib/version.ts
661
+ import { createRequire } from "module";
662
+ import { existsSync } from "fs";
663
+ import path2 from "path";
664
+ import { fileURLToPath } from "url";
660
665
  var require2 = createRequire(import.meta.url);
661
- var { version: currentVersion } = require2("../package.json");
666
+ var cached = null;
667
+ function cliVersion() {
668
+ if (cached !== null) return cached;
669
+ const dir = path2.dirname(fileURLToPath(import.meta.url));
670
+ for (let i = 1; i <= 4; i++) {
671
+ const candidate = path2.resolve(dir, ...Array(i).fill(".."), "package.json");
672
+ if (!existsSync(candidate)) continue;
673
+ try {
674
+ const version2 = require2(candidate).version;
675
+ if (version2) {
676
+ cached = version2;
677
+ return cached;
678
+ }
679
+ } catch {
680
+ }
681
+ }
682
+ cached = "unknown";
683
+ return cached;
684
+ }
685
+
686
+ // src/commands/update.ts
687
+ var currentVersion = cliVersion();
662
688
  var ONE_DIR = () => join(homeDir(), ".one");
663
689
  var CACHE_PATH = () => join(ONE_DIR(), "update-check.json");
664
690
  var LOCK_PATH = () => join(ONE_DIR(), "auto-update.lock");
@@ -814,17 +840,17 @@ function autoUpdate(targetVersion, publishedAt) {
814
840
  var CANONICAL_SKILL_DIR = ".agents/skills";
815
841
  var VERSION_MARKER = ".one-cli-version";
816
842
  function getPackagedSkillDir() {
817
- const here = path2.dirname(fileURLToPath(import.meta.url));
818
- return path2.resolve(here, "..", "skills", "one");
843
+ const here = path3.dirname(fileURLToPath2(import.meta.url));
844
+ return path3.resolve(here, "..", "skills", "one");
819
845
  }
820
846
  function getCanonicalSkillPath() {
821
- return path2.join(homeDir(), CANONICAL_SKILL_DIR, "one");
847
+ return path3.join(homeDir(), CANONICAL_SKILL_DIR, "one");
822
848
  }
823
849
  function getVersionMarkerPath() {
824
- return path2.join(getCanonicalSkillPath(), VERSION_MARKER);
850
+ return path3.join(getCanonicalSkillPath(), VERSION_MARKER);
825
851
  }
826
852
  function isSkillInstalled() {
827
- return fs2.existsSync(path2.join(getCanonicalSkillPath(), "SKILL.md"));
853
+ return fs2.existsSync(path3.join(getCanonicalSkillPath(), "SKILL.md"));
828
854
  }
829
855
  function readInstalledSkillVersion() {
830
856
  try {
@@ -844,8 +870,8 @@ function writeInstalledSkillVersion(version2) {
844
870
  function copyDirSync(src, dest) {
845
871
  fs2.mkdirSync(dest, { recursive: true });
846
872
  for (const entry of fs2.readdirSync(src, { withFileTypes: true })) {
847
- const srcPath = path2.join(src, entry.name);
848
- const destPath = path2.join(dest, entry.name);
873
+ const srcPath = path3.join(src, entry.name);
874
+ const destPath = path3.join(dest, entry.name);
849
875
  if (entry.isDirectory()) {
850
876
  copyDirSync(srcPath, destPath);
851
877
  } else {
@@ -872,7 +898,7 @@ function forceSyncSkills() {
872
898
  }
873
899
  function performSync(current, reason) {
874
900
  const source = getPackagedSkillDir();
875
- if (!fs2.existsSync(path2.join(source, "SKILL.md"))) {
901
+ if (!fs2.existsSync(path3.join(source, "SKILL.md"))) {
876
902
  return { synced: false, reason: "source-missing" };
877
903
  }
878
904
  const canonical = getCanonicalSkillPath();
@@ -1240,7 +1266,7 @@ async function chooseConfigScope(options) {
1240
1266
  const hasGlobal = globalConfigExists();
1241
1267
  const hasProject = projectConfigExists();
1242
1268
  const projectRoot = resolved.projectRoot;
1243
- const projectName = path3.basename(projectRoot);
1269
+ const projectName = path4.basename(projectRoot);
1244
1270
  const homeGlobal = tildify(getGlobalConfigPath());
1245
1271
  const homeProject = tildify(getProjectConfigPath(projectRoot));
1246
1272
  if (hasProject) {
@@ -1525,26 +1551,26 @@ var SKILL_AGENTS = [
1525
1551
  ];
1526
1552
  var CANONICAL_SKILL_DIR2 = ".agents/skills";
1527
1553
  function getSkillSourceDir() {
1528
- const __dirname2 = path3.dirname(fileURLToPath2(import.meta.url));
1529
- return path3.resolve(__dirname2, "..", "skills", "one");
1554
+ const __dirname2 = path4.dirname(fileURLToPath3(import.meta.url));
1555
+ return path4.resolve(__dirname2, "..", "skills", "one");
1530
1556
  }
1531
1557
  function getCanonicalSkillPath2() {
1532
- return path3.join(homeDir(), CANONICAL_SKILL_DIR2, "one");
1558
+ return path4.join(homeDir(), CANONICAL_SKILL_DIR2, "one");
1533
1559
  }
1534
1560
  function getAgentSkillPath(agent) {
1535
- return path3.join(homeDir(), agent.skillDir, "one");
1561
+ return path4.join(homeDir(), agent.skillDir, "one");
1536
1562
  }
1537
1563
  function isSkillInstalled2() {
1538
- return fs3.existsSync(path3.join(getCanonicalSkillPath2(), "SKILL.md"));
1564
+ return fs3.existsSync(path4.join(getCanonicalSkillPath2(), "SKILL.md"));
1539
1565
  }
1540
1566
  function isSkillInstalledForAgent(agent) {
1541
- return fs3.existsSync(path3.join(getAgentSkillPath(agent), "SKILL.md"));
1567
+ return fs3.existsSync(path4.join(getAgentSkillPath(agent), "SKILL.md"));
1542
1568
  }
1543
1569
  function copyDirSync2(src, dest) {
1544
1570
  fs3.mkdirSync(dest, { recursive: true });
1545
1571
  for (const entry of fs3.readdirSync(src, { withFileTypes: true })) {
1546
- const srcPath = path3.join(src, entry.name);
1547
- const destPath = path3.join(dest, entry.name);
1572
+ const srcPath = path4.join(src, entry.name);
1573
+ const destPath = path4.join(dest, entry.name);
1548
1574
  if (entry.isDirectory()) {
1549
1575
  copyDirSync2(srcPath, destPath);
1550
1576
  } else {
@@ -1557,7 +1583,7 @@ function installSkillForAgents(agentIds) {
1557
1583
  const canonical = getCanonicalSkillPath2();
1558
1584
  const installed = [];
1559
1585
  const failed = [];
1560
- if (!fs3.existsSync(path3.join(source, "SKILL.md"))) {
1586
+ if (!fs3.existsSync(path4.join(source, "SKILL.md"))) {
1561
1587
  return { installed: [], failed: ["skill source not found"] };
1562
1588
  }
1563
1589
  try {
@@ -1579,14 +1605,14 @@ function installSkillForAgents(agentIds) {
1579
1605
  continue;
1580
1606
  }
1581
1607
  try {
1582
- const agentSkillsDir = path3.dirname(agentPath);
1608
+ const agentSkillsDir = path4.dirname(agentPath);
1583
1609
  fs3.mkdirSync(agentSkillsDir, { recursive: true });
1584
1610
  try {
1585
1611
  fs3.lstatSync(agentPath);
1586
1612
  fs3.rmSync(agentPath, { recursive: true });
1587
1613
  } catch {
1588
1614
  }
1589
- const relative = path3.relative(agentSkillsDir, canonical);
1615
+ const relative = path4.relative(agentSkillsDir, canonical);
1590
1616
  fs3.symlinkSync(relative, agentPath);
1591
1617
  installed.push(agent.name);
1592
1618
  seen.set(agentPath, true);
@@ -1833,7 +1859,7 @@ ${whoami.user.name} ${pc2.dim(`(${whoami.user.email})`)}`,
1833
1859
  };
1834
1860
  await promptConnectIntegrations(apiKey, connParams);
1835
1861
  const savedPath = scope === "project" ? getProjectConfigPath() : getGlobalConfigPath();
1836
- const resolutionHint = scope === "project" ? `When you run ${pc2.cyan("one")} from ${pc2.bold(path3.basename(getProjectRoot()))}, it uses this project config.
1862
+ const resolutionHint = scope === "project" ? `When you run ${pc2.cyan("one")} from ${pc2.bold(path4.basename(getProjectRoot()))}, it uses this project config.
1837
1863
  From anywhere else, it falls back to your global config.` : `This config applies to every folder unless a project config is set.`;
1838
1864
  p3.note(
1839
1865
  `${scopeLabel(scope)} Config saved to:
@@ -2523,11 +2549,11 @@ async function actionsSearchCommand(platform, query, options) {
2523
2549
  const useCache = options.cache !== false;
2524
2550
  const searchType = agentType || "knowledge";
2525
2551
  const cachePath = searchCachePath(platform, query, searchType);
2526
- const cached = useCache ? readCache(cachePath) : null;
2552
+ const cached2 = useCache ? readCache(cachePath) : null;
2527
2553
  let cleanedActions;
2528
2554
  let cacheHit = false;
2529
- if (cached && isFresh(cached)) {
2530
- cleanedActions = cached.data.actions;
2555
+ if (cached2 && isFresh(cached2)) {
2556
+ cleanedActions = cached2.data.actions;
2531
2557
  cacheHit = true;
2532
2558
  } else {
2533
2559
  try {
@@ -2535,12 +2561,12 @@ async function actionsSearchCommand(platform, query, options) {
2535
2561
  platform,
2536
2562
  query,
2537
2563
  agentType,
2538
- cached?.etag ?? void 0
2564
+ cached2?.etag ?? void 0
2539
2565
  );
2540
- if (result.status === 304 && cached) {
2541
- cached.cachedAt = (/* @__PURE__ */ new Date()).toISOString();
2542
- writeCache(cachePath, cached);
2543
- cleanedActions = cached.data.actions;
2566
+ if (result.status === 304 && cached2) {
2567
+ cached2.cachedAt = (/* @__PURE__ */ new Date()).toISOString();
2568
+ writeCache(cachePath, cached2);
2569
+ cleanedActions = cached2.data.actions;
2544
2570
  cacheHit = true;
2545
2571
  } else {
2546
2572
  let actions2 = result.data;
@@ -2559,12 +2585,12 @@ async function actionsSearchCommand(platform, query, options) {
2559
2585
  ));
2560
2586
  }
2561
2587
  } catch (fetchError) {
2562
- if (cached) {
2588
+ if (cached2) {
2563
2589
  process.stderr.write(
2564
- `Warning: serving cached search results (network unavailable, cached ${formatAge(getAge(cached))} ago)
2590
+ `Warning: serving cached search results (network unavailable, cached ${formatAge(getAge(cached2))} ago)
2565
2591
  `
2566
2592
  );
2567
- cleanedActions = cached.data.actions;
2593
+ cleanedActions = cached2.data.actions;
2568
2594
  cacheHit = true;
2569
2595
  } else {
2570
2596
  throw fetchError;
@@ -2573,8 +2599,8 @@ async function actionsSearchCommand(platform, query, options) {
2573
2599
  }
2574
2600
  if (isAgentMode()) {
2575
2601
  const response = { actions: cleanedActions };
2576
- if (cacheHit && cached) {
2577
- response._cache = buildCacheMeta(cached, true);
2602
+ if (cacheHit && cached2) {
2603
+ response._cache = buildCacheMeta(cached2, true);
2578
2604
  } else {
2579
2605
  const freshEntry = readCache(cachePath);
2580
2606
  response._cache = buildCacheMeta(freshEntry, false);
@@ -3196,7 +3222,7 @@ import pc7 from "picocolors";
3196
3222
 
3197
3223
  // src/lib/flow-validator.ts
3198
3224
  import fs4 from "fs";
3199
- import path4 from "path";
3225
+ import path5 from "path";
3200
3226
  import { spawnSync } from "child_process";
3201
3227
  function validateFlowSchema(flow2) {
3202
3228
  const errors = [];
@@ -3271,32 +3297,32 @@ function validateStepsArray(steps, pathPrefix, errors) {
3271
3297
  const validTypes = FLOW_SCHEMA.stepTypes.map((st) => st.type);
3272
3298
  for (let i = 0; i < steps.length; i++) {
3273
3299
  const step = steps[i];
3274
- const path12 = `${pathPrefix}[${i}]`;
3300
+ const path13 = `${pathPrefix}[${i}]`;
3275
3301
  if (!step || typeof step !== "object" || Array.isArray(step)) {
3276
- errors.push({ path: path12, message: "Step must be an object" });
3302
+ errors.push({ path: path13, message: "Step must be an object" });
3277
3303
  continue;
3278
3304
  }
3279
3305
  const s = step;
3280
3306
  if (!s.id || typeof s.id !== "string") {
3281
- errors.push({ path: `${path12}.id`, message: 'Step must have a string "id"' });
3307
+ errors.push({ path: `${path13}.id`, message: 'Step must have a string "id"' });
3282
3308
  }
3283
3309
  if (!s.name || typeof s.name !== "string") {
3284
- errors.push({ path: `${path12}.name`, message: 'Step must have a string "name"' });
3310
+ errors.push({ path: `${path13}.name`, message: 'Step must have a string "name"' });
3285
3311
  }
3286
3312
  if (!s.type || !validTypes.includes(s.type)) {
3287
- errors.push({ path: `${path12}.type`, message: `Step type must be one of: ${validTypes.join(", ")}` });
3313
+ errors.push({ path: `${path13}.type`, message: `Step type must be one of: ${validTypes.join(", ")}` });
3288
3314
  continue;
3289
3315
  }
3290
3316
  if (s.requires !== void 0) {
3291
3317
  if (!Array.isArray(s.requires)) {
3292
- errors.push({ path: `${path12}.requires`, message: '"requires" must be an array of selector strings (e.g. ["$.steps.foo.output.bar"])' });
3318
+ errors.push({ path: `${path13}.requires`, message: '"requires" must be an array of selector strings (e.g. ["$.steps.foo.output.bar"])' });
3293
3319
  } else {
3294
3320
  for (let r = 0; r < s.requires.length; r++) {
3295
3321
  const sel = s.requires[r];
3296
3322
  if (typeof sel !== "string") {
3297
- errors.push({ path: `${path12}.requires[${r}]`, message: '"requires" entry must be a selector string' });
3323
+ errors.push({ path: `${path13}.requires[${r}]`, message: '"requires" entry must be a selector string' });
3298
3324
  } else if (!sel.startsWith("$.")) {
3299
- errors.push({ path: `${path12}.requires[${r}]`, message: `"requires" entry "${sel}" must be a selector starting with "$." (e.g. "$.steps.foo.output.bar")` });
3325
+ errors.push({ path: `${path13}.requires[${r}]`, message: `"requires" entry "${sel}" must be a selector starting with "$." (e.g. "$.steps.foo.output.bar")` });
3300
3326
  }
3301
3327
  }
3302
3328
  }
@@ -3304,7 +3330,7 @@ function validateStepsArray(steps, pathPrefix, errors) {
3304
3330
  if (s.onError && typeof s.onError === "object") {
3305
3331
  const oe = s.onError;
3306
3332
  if (!FLOW_SCHEMA.errorStrategies.includes(oe.strategy)) {
3307
- errors.push({ path: `${path12}.onError.strategy`, message: `Error strategy must be one of: ${FLOW_SCHEMA.errorStrategies.join(", ")}` });
3333
+ errors.push({ path: `${path13}.onError.strategy`, message: `Error strategy must be one of: ${FLOW_SCHEMA.errorStrategies.join(", ")}` });
3308
3334
  }
3309
3335
  }
3310
3336
  const descriptor = getStepTypeDescriptor(s.type);
@@ -3314,14 +3340,14 @@ function validateStepsArray(steps, pathPrefix, errors) {
3314
3340
  if (!configObj || typeof configObj !== "object") {
3315
3341
  const hint = detectFlatConfigHint(s, descriptor);
3316
3342
  errors.push({
3317
- path: `${path12}.${configKey}`,
3343
+ path: `${path13}.${configKey}`,
3318
3344
  message: `${capitalize(descriptor.type)} step must have a "${configKey}" config object${hint}`
3319
3345
  });
3320
3346
  continue;
3321
3347
  }
3322
3348
  const config2 = configObj;
3323
3349
  for (const [fieldName, fd] of Object.entries(descriptor.fields)) {
3324
- const fieldPath = `${path12}.${configKey}.${fieldName}`;
3350
+ const fieldPath = `${path13}.${configKey}.${fieldName}`;
3325
3351
  const value = config2[fieldName];
3326
3352
  if (fd.required && (value === void 0 || value === null || value === "")) {
3327
3353
  errors.push({ path: fieldPath, message: `${capitalize(descriptor.type)} must have ${fd.type === "string" ? "a string" : fd.type === "array" ? "a" : "a"} "${fieldName}"` });
@@ -3354,30 +3380,30 @@ function validateStepsArray(steps, pathPrefix, errors) {
3354
3380
  }
3355
3381
  }
3356
3382
  if (descriptor.type === "action") {
3357
- validateConnectionForm(config2, `${path12}.${configKey}`, errors);
3383
+ validateConnectionForm(config2, `${path13}.${configKey}`, errors);
3358
3384
  }
3359
3385
  if (descriptor.type === "code") {
3360
3386
  const hasSource = typeof config2.source === "string" && config2.source.length > 0;
3361
3387
  const hasModule = typeof config2.module === "string" && config2.module.length > 0;
3362
3388
  if (!hasSource && !hasModule) {
3363
- errors.push({ path: `${path12}.${configKey}`, message: 'Code step must define either "source" (inline JS) or "module" (path to .mjs file)' });
3389
+ errors.push({ path: `${path13}.${configKey}`, message: 'Code step must define either "source" (inline JS) or "module" (path to .mjs file)' });
3364
3390
  } else if (hasSource && hasModule) {
3365
- errors.push({ path: `${path12}.${configKey}`, message: 'Code step cannot define both "source" and "module" \u2014 pick one' });
3391
+ errors.push({ path: `${path13}.${configKey}`, message: 'Code step cannot define both "source" and "module" \u2014 pick one' });
3366
3392
  }
3367
3393
  if (hasModule) {
3368
3394
  const m = config2.module;
3369
3395
  if (m.startsWith("/") || /^[a-zA-Z]:[\\/]/.test(m)) {
3370
- errors.push({ path: `${path12}.${configKey}.module`, message: "Code module path must be relative to the flow folder (no absolute paths)" });
3396
+ errors.push({ path: `${path13}.${configKey}.module`, message: "Code module path must be relative to the flow folder (no absolute paths)" });
3371
3397
  } else if (m.split(/[\\/]/).includes("..")) {
3372
- errors.push({ path: `${path12}.${configKey}.module`, message: 'Code module path must not escape the flow folder ("..")' });
3398
+ errors.push({ path: `${path13}.${configKey}.module`, message: 'Code module path must not escape the flow folder ("..")' });
3373
3399
  } else if (!m.endsWith(".mjs")) {
3374
- errors.push({ path: `${path12}.${configKey}.module`, message: "Code module must be a .mjs file" });
3400
+ errors.push({ path: `${path13}.${configKey}.module`, message: "Code module must be a .mjs file" });
3375
3401
  }
3376
3402
  }
3377
3403
  if (hasSource) {
3378
3404
  const syntaxError = checkCodeSourceSyntax(config2.source);
3379
3405
  if (syntaxError) {
3380
- errors.push({ path: `${path12}.${configKey}.source`, message: `Syntax error in code step: ${syntaxError}` });
3406
+ errors.push({ path: `${path13}.${configKey}.source`, message: `Syntax error in code step: ${syntaxError}` });
3381
3407
  }
3382
3408
  }
3383
3409
  }
@@ -3449,16 +3475,16 @@ function validateStepIds(flow2) {
3449
3475
  function collectIds(steps, pathPrefix) {
3450
3476
  for (let i = 0; i < steps.length; i++) {
3451
3477
  const step = steps[i];
3452
- const path12 = `${pathPrefix}[${i}]`;
3478
+ const path13 = `${pathPrefix}[${i}]`;
3453
3479
  if (seen.has(step.id)) {
3454
- errors.push({ path: `${path12}.id`, message: `Duplicate step ID: "${step.id}"` });
3480
+ errors.push({ path: `${path13}.id`, message: `Duplicate step ID: "${step.id}"` });
3455
3481
  } else {
3456
3482
  seen.add(step.id);
3457
3483
  }
3458
3484
  for (const { configKey, fieldName } of nestedKeys) {
3459
3485
  const config2 = step[configKey];
3460
3486
  if (config2 && Array.isArray(config2[fieldName])) {
3461
- collectIds(config2[fieldName], `${path12}.${configKey}.${fieldName}`);
3487
+ collectIds(config2[fieldName], `${path13}.${configKey}.${fieldName}`);
3462
3488
  }
3463
3489
  }
3464
3490
  }
@@ -3506,7 +3532,7 @@ function validateSelectorReferences(flow2, rootDir) {
3506
3532
  }
3507
3533
  return selectors;
3508
3534
  }
3509
- function checkSelectors(selectors, path12, precedingStepIds) {
3535
+ function checkSelectors(selectors, path13, precedingStepIds) {
3510
3536
  for (const selector of selectors) {
3511
3537
  const parts = selector.split(".");
3512
3538
  if (parts.length < 3) continue;
@@ -3514,15 +3540,15 @@ function validateSelectorReferences(flow2, rootDir) {
3514
3540
  if (root === "input") {
3515
3541
  const inputName = parts[2];
3516
3542
  if (!inputNames.has(inputName)) {
3517
- errors.push({ path: path12, message: `Selector "${selector}" references undefined input "${inputName}"` });
3543
+ errors.push({ path: path13, message: `Selector "${selector}" references undefined input "${inputName}"` });
3518
3544
  }
3519
3545
  } else if (root === "steps") {
3520
3546
  const stepId = parts[2].replace(/[\[\]]/g, "").split(/[\[\]]/)[0];
3521
3547
  if (!allStepIds.has(stepId)) {
3522
- errors.push({ path: path12, message: `Selector "${selector}" references undefined step "${stepId}"` });
3548
+ errors.push({ path: path13, message: `Selector "${selector}" references undefined step "${stepId}"` });
3523
3549
  } else if (precedingStepIds && !precedingStepIds.has(stepId)) {
3524
3550
  errors.push({
3525
- path: path12,
3551
+ path: path13,
3526
3552
  message: `Selector "${selector}" references step "${stepId}" which is declared after the current step. Steps execute in declaration order, so this will always resolve to undefined at runtime \u2014 move the dependency earlier in the steps array.`
3527
3553
  });
3528
3554
  }
@@ -3530,20 +3556,20 @@ function validateSelectorReferences(flow2, rootDir) {
3530
3556
  }
3531
3557
  }
3532
3558
  const EXPRESSION_FIELDS = /* @__PURE__ */ new Set(["condition.expression", "while.condition"]);
3533
- function checkOperatorsInSelectorField(value, path12) {
3559
+ function checkOperatorsInSelectorField(value, path13) {
3534
3560
  if (typeof value === "string" && value.startsWith("$.")) {
3535
3561
  if (value.includes("||")) {
3536
- errors.push({ path: path12, message: `Selector "${value}" contains unsupported operator "||". Selectors in data fields use dot-path resolution, not JS evaluation. Use the "default" field on the input definition instead, or use a "code" step for complex expressions.` });
3562
+ errors.push({ path: path13, message: `Selector "${value}" contains unsupported operator "||". Selectors in data fields use dot-path resolution, not JS evaluation. Use the "default" field on the input definition instead, or use a "code" step for complex expressions.` });
3537
3563
  } else if (value.includes("&&")) {
3538
- errors.push({ path: path12, message: `Selector "${value}" contains unsupported operator "&&". Selectors in data fields use dot-path resolution, not JS evaluation. Use a "condition" step or "code" step for complex expressions.` });
3564
+ errors.push({ path: path13, message: `Selector "${value}" contains unsupported operator "&&". Selectors in data fields use dot-path resolution, not JS evaluation. Use a "condition" step or "code" step for complex expressions.` });
3539
3565
  }
3540
3566
  } else if (value && typeof value === "object" && !Array.isArray(value)) {
3541
3567
  for (const [k, v] of Object.entries(value)) {
3542
- checkOperatorsInSelectorField(v, `${path12}.${k}`);
3568
+ checkOperatorsInSelectorField(v, `${path13}.${k}`);
3543
3569
  }
3544
3570
  } else if (Array.isArray(value)) {
3545
3571
  for (let i = 0; i < value.length; i++) {
3546
- checkOperatorsInSelectorField(value[i], `${path12}[${i}]`);
3572
+ checkOperatorsInSelectorField(value[i], `${path13}[${i}]`);
3547
3573
  }
3548
3574
  }
3549
3575
  }
@@ -3587,7 +3613,7 @@ function validateSelectorReferences(flow2, rootDir) {
3587
3613
  }
3588
3614
  const modulePath = step.type === "code" ? c.module : void 0;
3589
3615
  if (rootDir && typeof modulePath === "string" && modulePath.length > 0) {
3590
- const abs = path4.resolve(rootDir, modulePath);
3616
+ const abs = path5.resolve(rootDir, modulePath);
3591
3617
  if (fs4.existsSync(abs)) {
3592
3618
  try {
3593
3619
  const moduleText = fs4.readFileSync(abs, "utf-8");
@@ -3628,10 +3654,10 @@ var VALID_OUTPUT_SCHEMA_TYPES = /* @__PURE__ */ new Set(["string", "number", "bo
3628
3654
  function isOutputSchemaObject(v) {
3629
3655
  return !!v && typeof v === "object" && !Array.isArray(v);
3630
3656
  }
3631
- function walkOutputSchema(schema, path12) {
3657
+ function walkOutputSchema(schema, path13) {
3632
3658
  let current = schema;
3633
- for (let i = 0; i < path12.length; i++) {
3634
- const seg = path12[i];
3659
+ for (let i = 0; i < path13.length; i++) {
3660
+ const seg = path13[i];
3635
3661
  if (typeof current === "string") {
3636
3662
  return current === "unknown" || current === "object" || current === "array" ? "opaque" : "opaque";
3637
3663
  }
@@ -3783,7 +3809,7 @@ function validateCodeModules(flow2, rootDir) {
3783
3809
  const stepPath = `${pathPrefix}[${i}]`;
3784
3810
  if (step.type === "code" && step.code?.module) {
3785
3811
  const m = step.code.module;
3786
- const abs = path4.resolve(rootDir, m);
3812
+ const abs = path5.resolve(rootDir, m);
3787
3813
  if (!fs4.existsSync(abs)) {
3788
3814
  errors.push({
3789
3815
  path: `${stepPath}.code.module`,
@@ -3916,9 +3942,9 @@ function validateFileReadSchemas(flow2) {
3916
3942
 
3917
3943
  // src/commands/flow.ts
3918
3944
  import fs5 from "fs";
3919
- import path5 from "path";
3945
+ import path6 from "path";
3920
3946
  async function writeFlowResultFile(filePath, meta, steps) {
3921
- const abs = path5.resolve(filePath);
3947
+ const abs = path6.resolve(filePath);
3922
3948
  const ws = fs5.createWriteStream(abs);
3923
3949
  const done = new Promise((resolve, reject) => {
3924
3950
  ws.on("finish", () => resolve());
@@ -4326,7 +4352,7 @@ async function flowValidateCommand(keyOrPath) {
4326
4352
  const flowPath = resolveFlowPath(keyOrPath);
4327
4353
  const content = fs5.readFileSync(flowPath, "utf-8");
4328
4354
  flowData = JSON.parse(content);
4329
- rootDir = path5.dirname(flowPath);
4355
+ rootDir = path6.dirname(flowPath);
4330
4356
  }
4331
4357
  } catch (err) {
4332
4358
  spinner5.stop("Validation failed");
@@ -4353,7 +4379,7 @@ async function flowValidateCommand(keyOrPath) {
4353
4379
  }
4354
4380
  note(`Workflow "${flowData.key}" passed all validation checks`, "Valid");
4355
4381
  }
4356
- async function flowResumeCommand(runId) {
4382
+ async function flowResumeCommand(runId, options = {}) {
4357
4383
  intro(pc7.bgCyan(pc7.black(" One Workflow ")));
4358
4384
  const state = FlowRunner.loadRunState(runId);
4359
4385
  if (!state) {
@@ -4374,6 +4400,14 @@ async function flowResumeCommand(runId) {
4374
4400
  error(`Could not load workflow "${state.flowKey}": ${err instanceof Error ? err.message : String(err)}`);
4375
4401
  return;
4376
4402
  }
4403
+ if (!options.allowBash && flowRequiresBash(flow2)) {
4404
+ const msg = `Workflow "${flow2.key}" contains bash steps. Re-run with --allow-bash to permit shell execution.`;
4405
+ if (isAgentMode()) {
4406
+ json({ error: msg, requiresBash: true, flowKey: flow2.key, runId });
4407
+ process.exit(1);
4408
+ }
4409
+ error(msg);
4410
+ }
4377
4411
  const runner = FlowRunner.fromRunState(state);
4378
4412
  const onEvent = (event) => {
4379
4413
  if (isAgentMode()) {
@@ -4383,7 +4417,11 @@ async function flowResumeCommand(runId) {
4383
4417
  const spinner5 = createSpinner();
4384
4418
  spinner5.start(`Resuming run ${runId} (${state.completedSteps.length} steps already completed)...`);
4385
4419
  try {
4386
- const context = await runner.resume(flow2, api, permissions, actionIds, { onEvent, rootDir });
4420
+ const context = await runner.resume(flow2, api, permissions, actionIds, {
4421
+ onEvent,
4422
+ rootDir,
4423
+ allowBash: options.allowBash
4424
+ });
4387
4425
  spinner5.stop("Workflow completed");
4388
4426
  if (isAgentMode()) {
4389
4427
  json({
@@ -4502,7 +4540,7 @@ async function flowInspectCommand(runId, options = {}) {
4502
4540
  }
4503
4541
  console.log();
4504
4542
  console.log(` ${pc7.dim(`State: ${statePath}`)}`);
4505
- console.log(` ${pc7.dim(`Log: ${path5.join(".one/flows/.logs", `${state.flowKey}-${state.runId}.log`)}`)}`);
4543
+ console.log(` ${pc7.dim(`Log: ${path6.join(".one/flows/.logs", `${state.flowKey}-${state.runId}.log`)}`)}`);
4506
4544
  console.log();
4507
4545
  }
4508
4546
  function colorStatus(status) {
@@ -5208,10 +5246,10 @@ function handleId(response, config2, records) {
5208
5246
 
5209
5247
  // src/lib/memory/sync/state.ts
5210
5248
  import fs6 from "fs";
5211
- import path6 from "path";
5212
- var SYNC_DIR = path6.join(".one", "sync");
5213
- var STATE_DIR = path6.join(SYNC_DIR, "state");
5214
- var LEGACY_SINGLE_FILE = path6.join(SYNC_DIR, "sync_state.json");
5249
+ import path7 from "path";
5250
+ var SYNC_DIR = path7.join(".one", "sync");
5251
+ var STATE_DIR = path7.join(SYNC_DIR, "state");
5252
+ var LEGACY_SINGLE_FILE = path7.join(SYNC_DIR, "sync_state.json");
5215
5253
  var legacyMigrationDone = false;
5216
5254
  function rowToState(row) {
5217
5255
  return {
@@ -5264,7 +5302,7 @@ async function migrateLegacyOnce() {
5264
5302
  const backend = await getBackend();
5265
5303
  const platforms = fs6.readdirSync(STATE_DIR);
5266
5304
  for (const platform of platforms) {
5267
- const platformDir = path6.join(STATE_DIR, platform);
5305
+ const platformDir = path7.join(STATE_DIR, platform);
5268
5306
  let entries;
5269
5307
  try {
5270
5308
  entries = fs6.readdirSync(platformDir);
@@ -5274,7 +5312,7 @@ async function migrateLegacyOnce() {
5274
5312
  for (const entry of entries) {
5275
5313
  if (!entry.endsWith(".json")) continue;
5276
5314
  const model = entry.slice(0, -".json".length);
5277
- const filePath = path6.join(platformDir, entry);
5315
+ const filePath = path7.join(platformDir, entry);
5278
5316
  try {
5279
5317
  const raw = fs6.readFileSync(filePath, "utf-8");
5280
5318
  const modelState = JSON.parse(raw);
@@ -5331,11 +5369,11 @@ async function removeModelState(platform, model) {
5331
5369
 
5332
5370
  // src/lib/memory/sync/lock.ts
5333
5371
  import fs7 from "fs";
5334
- import path7 from "path";
5335
- var LOCK_DIR_REL = path7.join(".one", "sync", "locks");
5372
+ import path8 from "path";
5373
+ var LOCK_DIR_REL = path8.join(".one", "sync", "locks");
5336
5374
  var STALE_MS = 30 * 60 * 1e3;
5337
5375
  function lockPath(platform, model) {
5338
- return path7.join(LOCK_DIR_REL, `${platform}_${model}`);
5376
+ return path8.join(LOCK_DIR_REL, `${platform}_${model}`);
5339
5377
  }
5340
5378
  function isProcessAlive(pid) {
5341
5379
  try {
@@ -5354,7 +5392,7 @@ var SyncLockError = class extends Error {
5354
5392
  function acquireSyncLock(platform, model) {
5355
5393
  fs7.mkdirSync(LOCK_DIR_REL, { recursive: true });
5356
5394
  const dir = lockPath(platform, model);
5357
- const pidFile = path7.join(dir, "pid");
5395
+ const pidFile = path8.join(dir, "pid");
5358
5396
  try {
5359
5397
  fs7.mkdirSync(dir);
5360
5398
  } catch (err) {
@@ -5412,8 +5450,8 @@ function acquireSyncLock(platform, model) {
5412
5450
  // src/lib/memory/sync/hooks.ts
5413
5451
  import { spawn as spawn2 } from "child_process";
5414
5452
  import fs8 from "fs";
5415
- import path8 from "path";
5416
- var EVENTS_DIR = path8.join(".one", "sync", "events");
5453
+ import path9 from "path";
5454
+ var EVENTS_DIR = path9.join(".one", "sync", "events");
5417
5455
  function classifyRecords(db, model, records, idField, tableExists2) {
5418
5456
  if (!tableExists2 || records.length === 0) {
5419
5457
  return { inserts: records, updates: [] };
@@ -5460,7 +5498,7 @@ function appendEventLog(events) {
5460
5498
  if (events.length === 0) return;
5461
5499
  const { platform, model } = events[0];
5462
5500
  fs8.mkdirSync(EVENTS_DIR, { recursive: true });
5463
- const logPath = path8.join(EVENTS_DIR, `${platform}_${model}.jsonl`);
5501
+ const logPath = path9.join(EVENTS_DIR, `${platform}_${model}.jsonl`);
5464
5502
  const lines = events.map((e) => JSON.stringify(e)).join("\n") + "\n";
5465
5503
  fs8.appendFileSync(logPath, lines);
5466
5504
  }
@@ -5566,8 +5604,8 @@ function sleep(ms) {
5566
5604
  return new Promise((resolve) => setTimeout(resolve, ms));
5567
5605
  }
5568
5606
  function interpolate(template, record) {
5569
- return template.replace(/\{?\{(\w+(?:\.\w+)*)\}\}?/g, (_, path12) => {
5570
- const parts = path12.split(".");
5607
+ return template.replace(/\{?\{(\w+(?:\.\w+)*)\}\}?/g, (_, path13) => {
5608
+ const parts = path13.split(".");
5571
5609
  let value = record;
5572
5610
  for (const part of parts) {
5573
5611
  if (typeof value !== "object" || value === null) return "";
@@ -5595,8 +5633,8 @@ function deepMerge(target, source) {
5595
5633
  }
5596
5634
  return result;
5597
5635
  }
5598
- function getByDotPath2(obj, path12) {
5599
- const parts = path12.split(".");
5636
+ function getByDotPath2(obj, path13) {
5637
+ const parts = path13.split(".");
5600
5638
  let current = obj;
5601
5639
  for (const part of parts) {
5602
5640
  if (current === null || current === void 0 || typeof current !== "object") return void 0;
@@ -5605,8 +5643,8 @@ function getByDotPath2(obj, path12) {
5605
5643
  return current;
5606
5644
  }
5607
5645
  function stripExcludedFields(obj, paths) {
5608
- for (const path12 of paths) {
5609
- stripOnePath(obj, path12.replace(/\[\]/g, ".*").split("."));
5646
+ for (const path13 of paths) {
5647
+ stripOnePath(obj, path13.replace(/\[\]/g, ".*").split("."));
5610
5648
  }
5611
5649
  }
5612
5650
  function stripOnePath(obj, parts) {
@@ -6027,8 +6065,8 @@ function sleep2(ms) {
6027
6065
  return new Promise((resolve) => setTimeout(resolve, ms));
6028
6066
  }
6029
6067
  function stripFields(record, paths) {
6030
- for (const path12 of paths) {
6031
- stripOnePath2(record, path12.split("."));
6068
+ for (const path13 of paths) {
6069
+ stripOnePath2(record, path13.split("."));
6032
6070
  }
6033
6071
  }
6034
6072
  function stripOnePath2(obj, parts) {
@@ -7123,13 +7161,13 @@ function inferProfileFromKnowledge(knowledge, modelName, platform) {
7123
7161
  import { spawnSync as spawnSync2 } from "child_process";
7124
7162
  import fs10 from "fs";
7125
7163
  import os from "os";
7126
- import path10 from "path";
7164
+ import path11 from "path";
7127
7165
 
7128
7166
  // src/lib/memory/sync/schedule-registry.ts
7129
7167
  import fs9 from "fs";
7130
- import path9 from "path";
7131
- var REGISTRY_DIR = () => path9.join(homeDir(), ".one", "sync");
7132
- var REGISTRY_FILE = () => path9.join(REGISTRY_DIR(), "schedules.json");
7168
+ import path10 from "path";
7169
+ var REGISTRY_DIR = () => path10.join(homeDir(), ".one", "sync");
7170
+ var REGISTRY_FILE = () => path10.join(REGISTRY_DIR(), "schedules.json");
7133
7171
  function readRaw() {
7134
7172
  try {
7135
7173
  if (!fs9.existsSync(REGISTRY_FILE())) return { schedules: [] };
@@ -7148,7 +7186,7 @@ function writeRaw(file) {
7148
7186
  fs9.renameSync(tmp, REGISTRY_FILE());
7149
7187
  }
7150
7188
  function makeScheduleId(platform, cwd) {
7151
- const slug = path9.basename(cwd).replace(/[^a-zA-Z0-9_-]/g, "-").toLowerCase();
7189
+ const slug = path10.basename(cwd).replace(/[^a-zA-Z0-9_-]/g, "-").toLowerCase();
7152
7190
  return `${platform}-${slug}`;
7153
7191
  }
7154
7192
  function listRegistered() {
@@ -7182,7 +7220,7 @@ function removeRegistered(id) {
7182
7220
 
7183
7221
  // src/lib/memory/sync/schedule.ts
7184
7222
  var MARKER = "# one-sync";
7185
- var LOG_DIR_REL = path10.join(".one", "sync", "logs");
7223
+ var LOG_DIR_REL = path11.join(".one", "sync", "logs");
7186
7224
  function durationToCron(every) {
7187
7225
  const match = every.match(/^(\d+)([mhd])$/);
7188
7226
  if (!match) return null;
@@ -7299,7 +7337,7 @@ function migrateLegacyCronEntries() {
7299
7337
  const modelsMatch = command.match(/--models\s+(\S+)/);
7300
7338
  const models = modelsMatch ? modelsMatch[1].split(",") : void 0;
7301
7339
  const logMatch = command.match(/>>\s+"([^"]+)"/);
7302
- const logFile = logMatch ? logMatch[1] : path10.resolve(cwd, LOG_DIR_REL, `${platform}.log`);
7340
+ const logFile = logMatch ? logMatch[1] : path11.resolve(cwd, LOG_DIR_REL, `${platform}.log`);
7303
7341
  const id = makeScheduleId(platform, cwd);
7304
7342
  if (registeredIds.has(id)) continue;
7305
7343
  upsertRegistered({
@@ -7333,9 +7371,9 @@ function addSchedule(opts) {
7333
7371
  const cwd = process.cwd();
7334
7372
  const id = makeScheduleId(opts.platform, cwd);
7335
7373
  const replaced = getRegistered(id) !== void 0;
7336
- const logDir = path10.join(cwd, LOG_DIR_REL);
7374
+ const logDir = path11.join(cwd, LOG_DIR_REL);
7337
7375
  fs10.mkdirSync(logDir, { recursive: true });
7338
- const logFile = path10.join(logDir, `${opts.platform}.log`);
7376
+ const logFile = path11.join(logDir, `${opts.platform}.log`);
7339
7377
  const entry = {
7340
7378
  id,
7341
7379
  platform: opts.platform,
@@ -7679,11 +7717,11 @@ function isNoise(s) {
7679
7717
  if (/^-?\d+(\.\d+)?([eE][-+]?\d+)?$/.test(s)) return true;
7680
7718
  return false;
7681
7719
  }
7682
- function recordSample(stats, path12, value, jsType, recordIndex, totalSamples) {
7683
- let s = stats.get(path12);
7720
+ function recordSample(stats, path13, value, jsType, recordIndex, totalSamples) {
7721
+ let s = stats.get(path13);
7684
7722
  if (!s) {
7685
7723
  s = {
7686
- path: path12,
7724
+ path: path13,
7687
7725
  total: totalSamples,
7688
7726
  recordIndices: /* @__PURE__ */ new Set(),
7689
7727
  lenSum: 0,
@@ -7692,7 +7730,7 @@ function recordSample(stats, path12, value, jsType, recordIndex, totalSamples) {
7692
7730
  primaryType: jsType,
7693
7731
  examples: []
7694
7732
  };
7695
- stats.set(path12, s);
7733
+ stats.set(path13, s);
7696
7734
  }
7697
7735
  s.recordIndices.add(recordIndex);
7698
7736
  s.lenSum += value.length;
@@ -7701,28 +7739,28 @@ function recordSample(stats, path12, value, jsType, recordIndex, totalSamples) {
7701
7739
  if (s.primaryType !== jsType) s.primaryType = "mixed";
7702
7740
  if (s.examples.length < 3 && value.length < 200) s.examples.push(value);
7703
7741
  }
7704
- function walkRecord(record, path12, stats, recordIndex, totalSamples) {
7742
+ function walkRecord(record, path13, stats, recordIndex, totalSamples) {
7705
7743
  if (record === null || record === void 0) return;
7706
7744
  if (typeof record === "string") {
7707
7745
  const trimmed = record.trim();
7708
- if (trimmed) recordSample(stats, path12, trimmed, "string", recordIndex, totalSamples);
7746
+ if (trimmed) recordSample(stats, path13, trimmed, "string", recordIndex, totalSamples);
7709
7747
  return;
7710
7748
  }
7711
7749
  if (typeof record === "number" || typeof record === "boolean") {
7712
7750
  const str = String(record);
7713
7751
  const kind = typeof record === "number" ? "number" : "boolean";
7714
- if (str) recordSample(stats, path12, str, kind, recordIndex, totalSamples);
7752
+ if (str) recordSample(stats, path13, str, kind, recordIndex, totalSamples);
7715
7753
  return;
7716
7754
  }
7717
7755
  if (Array.isArray(record)) {
7718
- const childPath = path12 ? `${path12}[]` : "[]";
7756
+ const childPath = path13 ? `${path13}[]` : "[]";
7719
7757
  for (const item of record) walkRecord(item, childPath, stats, recordIndex, totalSamples);
7720
7758
  return;
7721
7759
  }
7722
7760
  if (typeof record === "object") {
7723
7761
  for (const [key, value] of Object.entries(record)) {
7724
7762
  if (key.startsWith("_")) continue;
7725
- const childPath = path12 ? `${path12}.${key}` : key;
7763
+ const childPath = path13 ? `${path13}.${key}` : key;
7726
7764
  walkRecord(value, childPath, stats, recordIndex, totalSamples);
7727
7765
  }
7728
7766
  }
@@ -8157,7 +8195,7 @@ function buildSearchablePreview(profile, samples) {
8157
8195
  const first = samples[0];
8158
8196
  const paths = getSearchablePaths(profile);
8159
8197
  if (paths) {
8160
- const perPathAgg = paths.map((path12) => ({ path: path12, hits: 0, total: samples.length, sample: "" }));
8198
+ const perPathAgg = paths.map((path13) => ({ path: path13, hits: 0, total: samples.length, sample: "" }));
8161
8199
  for (const record of samples) {
8162
8200
  const { paths: perPath } = extractSearchableFromPaths(record, paths);
8163
8201
  perPath.forEach((p10, i) => {
@@ -9114,16 +9152,16 @@ function projectEmbeddingApiKey(cfg) {
9114
9152
  }
9115
9153
  function redactSecrets(cfg) {
9116
9154
  const copy = JSON.parse(JSON.stringify(cfg));
9117
- for (const path12 of SECRET_PATHS) {
9118
- const val = getPath(copy, path12);
9155
+ for (const path13 of SECRET_PATHS) {
9156
+ const val = getPath(copy, path13);
9119
9157
  if (typeof val === "string" && val.length > 0) {
9120
- setPath(copy, path12, `${val.slice(0, 6)}\u2026(redacted, use --show-secrets)`);
9158
+ setPath(copy, path13, `${val.slice(0, 6)}\u2026(redacted, use --show-secrets)`);
9121
9159
  }
9122
9160
  }
9123
9161
  return copy;
9124
9162
  }
9125
- function getPath(obj, path12) {
9126
- const parts = path12.split(".");
9163
+ function getPath(obj, path13) {
9164
+ const parts = path13.split(".");
9127
9165
  let cur = obj;
9128
9166
  for (const part of parts) {
9129
9167
  if (cur == null || typeof cur !== "object") return void 0;
@@ -9131,8 +9169,8 @@ function getPath(obj, path12) {
9131
9169
  }
9132
9170
  return cur;
9133
9171
  }
9134
- function setPath(obj, path12, value) {
9135
- const parts = path12.split(".");
9172
+ function setPath(obj, path13, value) {
9173
+ const parts = path13.split(".");
9136
9174
  let cur = obj;
9137
9175
  for (let i = 0; i < parts.length - 1; i++) {
9138
9176
  const part = parts[i];
@@ -9142,8 +9180,8 @@ function setPath(obj, path12, value) {
9142
9180
  cur[parts[parts.length - 1]] = value;
9143
9181
  return obj;
9144
9182
  }
9145
- function unsetPath(obj, path12) {
9146
- const parts = path12.split(".");
9183
+ function unsetPath(obj, path13) {
9184
+ const parts = path13.split(".");
9147
9185
  let cur = obj;
9148
9186
  for (let i = 0; i < parts.length - 1; i++) {
9149
9187
  const part = parts[i];
@@ -11634,13 +11672,6 @@ function posthogHost() {
11634
11672
  function posthogKey() {
11635
11673
  return process.env.ONE_POSTHOG_KEY || DEFAULT_POSTHOG_KEY;
11636
11674
  }
11637
- function cliVersion() {
11638
- try {
11639
- return require3("../package.json").version;
11640
- } catch {
11641
- return "unknown";
11642
- }
11643
- }
11644
11675
  function envName() {
11645
11676
  const key = getApiKey();
11646
11677
  return key ? getEnvFromApiKey(key) : "live";
@@ -12113,11 +12144,11 @@ config.command("reset").description("Remove the project config for the current d
12113
12144
  const configContent = fs13.readFileSync(resolved.path, "utf-8");
12114
12145
  fs13.unlinkSync(resolved.path);
12115
12146
  const next = resolveConfig();
12116
- fs13.mkdirSync(path11.dirname(resolved.path), { recursive: true });
12147
+ fs13.mkdirSync(path12.dirname(resolved.path), { recursive: true });
12117
12148
  fs13.writeFileSync(resolved.path, configContent);
12118
12149
  let fallbackLabel;
12119
12150
  if (next.scope === "project") {
12120
- fallbackLabel = `parent project config (${path11.basename(next.projectRoot)})`;
12151
+ fallbackLabel = `parent project config (${path12.basename(next.projectRoot)})`;
12121
12152
  } else if (next.scope === "global") {
12122
12153
  fallbackLabel = "global config";
12123
12154
  } else {
@@ -12126,7 +12157,7 @@ config.command("reset").description("Remove the project config for the current d
12126
12157
  if (!isAgentMode()) {
12127
12158
  const p10 = await import("@clack/prompts");
12128
12159
  const confirmed = await p10.confirm({
12129
- message: `Delete project config for ${path11.basename(resolved.projectRoot)}? Will fall back to ${fallbackLabel}.`,
12160
+ message: `Delete project config for ${path12.basename(resolved.projectRoot)}? Will fall back to ${fallbackLabel}.`,
12130
12161
  initialValue: false
12131
12162
  });
12132
12163
  if (p10.isCancel(confirmed) || !confirmed) {
@@ -12136,7 +12167,7 @@ config.command("reset").description("Remove the project config for the current d
12136
12167
  }
12137
12168
  fs13.unlinkSync(resolved.path);
12138
12169
  try {
12139
- fs13.rmdirSync(path11.dirname(resolved.path));
12170
+ fs13.rmdirSync(path12.dirname(resolved.path));
12140
12171
  } catch {
12141
12172
  }
12142
12173
  if (isAgentMode()) {
@@ -12200,8 +12231,8 @@ flow.command("list").alias("ls").description("List all workflows in .one/flows/"
12200
12231
  flow.command("validate <keyOrPath>").description("Validate a workflow JSON file").action(async (keyOrPath) => {
12201
12232
  await flowValidateCommand(keyOrPath);
12202
12233
  });
12203
- flow.command("resume <runId>").description("Resume a paused or failed workflow run").action(async (runId) => {
12204
- await flowResumeCommand(runId);
12234
+ flow.command("resume <runId>").description("Resume a paused or failed workflow run").option("--allow-bash", "Allow bash step execution (disabled by default for security) \u2014 required to resume any flow containing bash steps").action(async (runId, options) => {
12235
+ await flowResumeCommand(runId, options);
12205
12236
  });
12206
12237
  flow.command("runs [flowKey]").description("List workflow runs (optionally filtered by flow key)").action(async (flowKey) => {
12207
12238
  await flowRunsCommand(flowKey);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@withone/cli",
3
- "version": "1.55.0",
3
+ "version": "1.55.1",
4
4
  "description": "CLI for managing One",
5
5
  "type": "module",
6
6
  "files": [
@@ -686,8 +686,14 @@ one --agent flow execute <key> --allow-bash -i key=value
686
686
  one --agent flow runs [flowKey]
687
687
  one --agent flow inspect <runId> # per-step outputs of a past run (add --full for untruncated)
688
688
  one --agent flow resume <runId>
689
+ one --agent flow resume <runId> --allow-bash # required if the flow has bash steps
689
690
  ```
690
691
 
692
+ `flow resume` gates bash exactly like `flow execute` — the permission is not
693
+ inherited from the original run. Resuming a bash flow without the flag fails
694
+ fast with `{"error": "...", "requiresBash": true, "flowKey": "...", "runId": "..."}`,
695
+ so re-invoke with `--allow-bash` rather than treating it as a broken run.
696
+
691
697
  ## Debugging a flow
692
698
 
693
699
  Three tools that turn "re-run the whole 40-step flow to debug step 30" into near-zero-cost inspection: