@withone/cli 1.44.1 → 1.45.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/dist/index.js CHANGED
@@ -5,22 +5,35 @@ import {
5
5
  OneApi,
6
6
  TimeoutError,
7
7
  buildActionKnowledgeWithGuidance,
8
+ buildCacheMeta,
9
+ clearAll,
10
+ clearEntry,
8
11
  filterByPermissions,
9
12
  flowRequiresBash,
13
+ formatAge,
10
14
  generateFlowGuide,
15
+ getAge,
11
16
  getNestedStepsKeys,
12
17
  getStepTypeDescriptor,
13
18
  isActionAllowed,
19
+ isFresh,
14
20
  isMethodAllowed,
21
+ knowledgeCachePath,
22
+ listCacheEntries,
15
23
  listFlows,
16
24
  loadFlowWithMeta,
25
+ makeCacheEntry,
26
+ readCache,
27
+ resolveActionDetails,
17
28
  resolveFlowPath,
18
29
  saveFlow,
19
- validateActionInput
20
- } from "./chunk-YGOS6KEC.js";
30
+ searchCachePath,
31
+ validateActionInput,
32
+ writeCache
33
+ } from "./chunk-UXKF6AEG.js";
21
34
  import {
22
35
  memSqlCommand
23
- } from "./chunk-7ZILTQQO.js";
36
+ } from "./chunk-TLRJMJGU.js";
24
37
  import {
25
38
  countRecords,
26
39
  deleteDatabase,
@@ -45,7 +58,7 @@ import {
45
58
  upsertRecords,
46
59
  writeDraftProfile,
47
60
  writeProfile
48
- } from "./chunk-VQPV5XET.js";
61
+ } from "./chunk-Z4HKASJT.js";
49
62
  import {
50
63
  getByDotPath
51
64
  } from "./chunk-44CV5IMX.js";
@@ -68,7 +81,7 @@ import {
68
81
  semanticSearchUpgradeHint,
69
82
  semanticSearchUpgradeLine,
70
83
  setAgentMode
71
- } from "./chunk-MNNKOQ6V.js";
84
+ } from "./chunk-KH4ERRJ5.js";
72
85
  import {
73
86
  SCHEMA_VERSION,
74
87
  addRecord,
@@ -78,44 +91,45 @@ import {
78
91
  listBackendPlugins,
79
92
  loadBackendFromConfig,
80
93
  upsertRecord
81
- } from "./chunk-YBEVCY4D.js";
94
+ } from "./chunk-TGWQUBKA.js";
82
95
  import {
83
96
  DEFAULT_MEMORY_CONFIG,
84
- configExists,
85
97
  defaultSearchableText,
86
98
  embed,
99
+ getMemoryConfig,
100
+ getMemoryConfigOrDefault,
101
+ memoryConfigExists,
102
+ setOpenAiApiKey,
103
+ updateMemoryConfig
104
+ } from "./chunk-77564KWS.js";
105
+ import {
106
+ configExists,
87
107
  ensureWhoAmI,
88
108
  getAccessControl,
89
109
  getAccessControlFromAllSources,
90
110
  getApiBase,
91
111
  getApiKey,
92
- getCacheTtl,
93
112
  getEnvFromApiKey,
94
113
  getGlobalConfigPath,
95
- getMemoryConfig,
96
- getMemoryConfigOrDefault,
97
114
  getOpenAiApiKey,
98
115
  getProjectConfigPath,
99
116
  getProjectRoot,
100
117
  getWhoAmI,
101
118
  globalConfigExists,
102
- memoryConfigExists,
103
119
  projectConfigExists,
104
120
  readConfig,
105
121
  readGlobalConfig,
106
122
  readProjectConfig,
107
123
  resolveConfig,
108
- setOpenAiApiKey,
109
124
  updateAccessControl,
110
125
  updateApiBase,
111
- updateMemoryConfig,
112
126
  updateWhoAmI,
113
127
  writeConfig
114
- } from "./chunk-ZD5S4IWT.js";
128
+ } from "./chunk-TVIZC7AC.js";
115
129
 
116
130
  // src/cli.ts
117
131
  import { createRequire as createRequire2 } from "module";
118
- import path12 from "path";
132
+ import path11 from "path";
119
133
  import { Command } from "commander";
120
134
 
121
135
  // src/commands/init.ts
@@ -621,14 +635,17 @@ import { fileURLToPath } from "url";
621
635
  // src/commands/update.ts
622
636
  import { createRequire } from "module";
623
637
  import { spawn } from "child_process";
624
- import { readFileSync, writeFileSync, mkdirSync } from "fs";
638
+ import { readFileSync, writeFileSync, mkdirSync, rmSync } from "fs";
625
639
  import { homedir } from "os";
626
640
  import { join } from "path";
627
641
  var require2 = createRequire(import.meta.url);
628
642
  var { version: currentVersion } = require2("../package.json");
629
- var CACHE_PATH = join(homedir(), ".one", "update-check.json");
643
+ var ONE_DIR = join(homedir(), ".one");
644
+ var CACHE_PATH = join(ONE_DIR, "update-check.json");
645
+ var LOCK_PATH = join(ONE_DIR, "auto-update.lock");
630
646
  var CHECK_INTERVAL_MS = 4 * 60 * 60 * 1e3;
631
647
  var AGE_GATE_MS = 30 * 60 * 1e3;
648
+ var LOCK_TTL_MS = 10 * 60 * 1e3;
632
649
  async function fetchLatestVersionInfo() {
633
650
  try {
634
651
  const res = await fetch("https://registry.npmjs.org/@withone/cli");
@@ -641,14 +658,14 @@ async function fetchLatestVersionInfo() {
641
658
  return null;
642
659
  }
643
660
  }
644
- function readCache() {
661
+ function readCache2() {
645
662
  try {
646
663
  return JSON.parse(readFileSync(CACHE_PATH, "utf8"));
647
664
  } catch {
648
665
  return null;
649
666
  }
650
667
  }
651
- function writeCache(latestVersion, publishedAt) {
668
+ function writeCache2(latestVersion, publishedAt) {
652
669
  try {
653
670
  mkdirSync(join(homedir(), ".one"), { recursive: true });
654
671
  writeFileSync(CACHE_PATH, JSON.stringify({ lastCheck: Date.now(), latestVersion, publishedAt }));
@@ -657,16 +674,16 @@ function writeCache(latestVersion, publishedAt) {
657
674
  }
658
675
  async function checkLatestVersion() {
659
676
  const info = await fetchLatestVersionInfo();
660
- if (info) writeCache(info.version, info.publishedAt);
677
+ if (info) writeCache2(info.version, info.publishedAt);
661
678
  return info?.version ?? null;
662
679
  }
663
680
  async function checkLatestVersionCached() {
664
- const cache2 = readCache();
681
+ const cache2 = readCache2();
665
682
  if (cache2 && Date.now() - cache2.lastCheck < CHECK_INTERVAL_MS) {
666
683
  return { version: cache2.latestVersion, publishedAt: cache2.publishedAt ?? null };
667
684
  }
668
685
  const info = await fetchLatestVersionInfo();
669
- if (info) writeCache(info.version, info.publishedAt);
686
+ if (info) writeCache2(info.version, info.publishedAt);
670
687
  return info;
671
688
  }
672
689
  function getCurrentVersion() {
@@ -725,16 +742,52 @@ function isNewerVersion(latest, current) {
725
742
  if (lMin !== cMin) return lMin > cMin;
726
743
  return lPat > cPat;
727
744
  }
745
+ function isAutoUpdateDisabled() {
746
+ const v = process.env.ONE_NO_AUTO_UPDATE ?? process.env.ONE_DISABLE_AUTO_UPDATE;
747
+ return v === "1" || v === "true";
748
+ }
749
+ function acquireUpdateLock(targetVersion) {
750
+ try {
751
+ mkdirSync(ONE_DIR, { recursive: true });
752
+ } catch {
753
+ }
754
+ try {
755
+ const lock = JSON.parse(readFileSync(LOCK_PATH, "utf8"));
756
+ const startedAt = typeof lock.startedAt === "number" ? lock.startedAt : 0;
757
+ if (Date.now() - startedAt < LOCK_TTL_MS) return false;
758
+ rmSync(LOCK_PATH, { force: true });
759
+ } catch {
760
+ }
761
+ try {
762
+ writeFileSync(
763
+ LOCK_PATH,
764
+ JSON.stringify({ pid: process.pid, startedAt: Date.now(), targetVersion }),
765
+ { flag: "wx" }
766
+ // fail if another invocation created it first
767
+ );
768
+ return true;
769
+ } catch {
770
+ return false;
771
+ }
772
+ }
728
773
  function autoUpdate(targetVersion, publishedAt) {
774
+ if (isAutoUpdateDisabled()) return;
729
775
  if (publishedAt) {
730
776
  const age = Date.now() - new Date(publishedAt).getTime();
731
777
  if (age < AGE_GATE_MS) return;
732
778
  }
779
+ if (!acquireUpdateLock(targetVersion)) return;
733
780
  const child = spawn("npm", ["install", "-g", `@withone/cli@${targetVersion}`], {
734
781
  detached: true,
735
782
  stdio: "ignore",
736
783
  shell: true
737
784
  });
785
+ child.on("error", () => {
786
+ try {
787
+ rmSync(LOCK_PATH, { force: true });
788
+ } catch {
789
+ }
790
+ });
738
791
  child.unref();
739
792
  }
740
793
 
@@ -2301,123 +2354,6 @@ async function platformsCommand(options) {
2301
2354
  // src/commands/actions.ts
2302
2355
  import * as p6 from "@clack/prompts";
2303
2356
  import pc6 from "picocolors";
2304
-
2305
- // src/lib/cache.ts
2306
- import fs4 from "fs";
2307
- import path4 from "path";
2308
- import os4 from "os";
2309
- var CACHE_BASE = path4.join(os4.homedir(), ".one", "cache");
2310
- var KNOWLEDGE_DIR = path4.join(CACHE_BASE, "knowledge");
2311
- var SEARCH_DIR = path4.join(CACHE_BASE, "search");
2312
- function sanitizeFilename(input) {
2313
- return input.replace(/[^a-zA-Z0-9_\-\.]/g, "_");
2314
- }
2315
- function knowledgeCachePath(actionId) {
2316
- return path4.join(KNOWLEDGE_DIR, `${sanitizeFilename(actionId)}.json`);
2317
- }
2318
- function searchCachePath(platform, query, type) {
2319
- const key = `${platform}_${sanitizeFilename(query)}_${type || "knowledge"}`;
2320
- return path4.join(SEARCH_DIR, `${key}.json`);
2321
- }
2322
- function readCache2(filePath) {
2323
- try {
2324
- const content = fs4.readFileSync(filePath, "utf-8");
2325
- return JSON.parse(content);
2326
- } catch {
2327
- return null;
2328
- }
2329
- }
2330
- function writeCache2(filePath, entry) {
2331
- try {
2332
- const dir = path4.dirname(filePath);
2333
- fs4.mkdirSync(dir, { recursive: true });
2334
- fs4.writeFileSync(filePath, JSON.stringify(entry, null, 2));
2335
- } catch {
2336
- }
2337
- }
2338
- function isFresh(entry) {
2339
- const cachedTime = new Date(entry.cachedAt).getTime();
2340
- const now = Date.now();
2341
- return now - cachedTime < entry.ttl * 1e3;
2342
- }
2343
- function getAge(entry) {
2344
- return Math.floor((Date.now() - new Date(entry.cachedAt).getTime()) / 1e3);
2345
- }
2346
- function buildCacheMeta(entry, hit) {
2347
- if (!entry) {
2348
- return { hit: false, age: 0, fresh: false };
2349
- }
2350
- return {
2351
- hit,
2352
- age: getAge(entry),
2353
- fresh: isFresh(entry)
2354
- };
2355
- }
2356
- function formatAge(seconds) {
2357
- if (seconds < 60) return `${seconds}s`;
2358
- if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
2359
- if (seconds < 86400) {
2360
- const h2 = Math.floor(seconds / 3600);
2361
- const m = Math.floor(seconds % 3600 / 60);
2362
- return m > 0 ? `${h2}h ${m}m` : `${h2}h`;
2363
- }
2364
- const d = Math.floor(seconds / 86400);
2365
- const h = Math.floor(seconds % 86400 / 3600);
2366
- return h > 0 ? `${d}d ${h}h` : `${d}d`;
2367
- }
2368
- function listCacheEntries() {
2369
- const entries = [];
2370
- for (const [dir, type] of [[KNOWLEDGE_DIR, "knowledge"], [SEARCH_DIR, "search"]]) {
2371
- try {
2372
- const files = fs4.readdirSync(dir);
2373
- for (const file of files) {
2374
- if (!file.endsWith(".json")) continue;
2375
- const filePath = path4.join(dir, file);
2376
- const entry = readCache2(filePath);
2377
- if (entry) {
2378
- entries.push({ type, filePath, entry });
2379
- }
2380
- }
2381
- } catch {
2382
- }
2383
- }
2384
- return entries;
2385
- }
2386
- function clearAll() {
2387
- let count = 0;
2388
- for (const dir of [KNOWLEDGE_DIR, SEARCH_DIR]) {
2389
- try {
2390
- const files = fs4.readdirSync(dir);
2391
- for (const file of files) {
2392
- fs4.unlinkSync(path4.join(dir, file));
2393
- count++;
2394
- }
2395
- fs4.rmdirSync(dir);
2396
- } catch {
2397
- }
2398
- }
2399
- return count;
2400
- }
2401
- function clearEntry(actionId) {
2402
- const filePath = knowledgeCachePath(actionId);
2403
- try {
2404
- fs4.unlinkSync(filePath);
2405
- return true;
2406
- } catch {
2407
- return false;
2408
- }
2409
- }
2410
- function makeCacheEntry(key, data, etag) {
2411
- return {
2412
- key,
2413
- etag,
2414
- cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
2415
- ttl: getCacheTtl(),
2416
- data
2417
- };
2418
- }
2419
-
2420
- // src/commands/actions.ts
2421
2357
  function getConfig() {
2422
2358
  const apiKey = getApiKey();
2423
2359
  if (!apiKey) {
@@ -2447,7 +2383,7 @@ async function actionsSearchCommand(platform, query, options) {
2447
2383
  const agentType = knowledgeAgent ? "knowledge" : options.type || "execute";
2448
2384
  const useCache = options.cache !== false;
2449
2385
  const cachePath = searchCachePath(platform, query, agentType || "knowledge");
2450
- const cached = useCache ? readCache2(cachePath) : null;
2386
+ const cached = useCache ? readCache(cachePath) : null;
2451
2387
  let cleanedActions;
2452
2388
  let cacheHit = false;
2453
2389
  if (cached && isFresh(cached)) {
@@ -2463,7 +2399,7 @@ async function actionsSearchCommand(platform, query, options) {
2463
2399
  );
2464
2400
  if (result.status === 304 && cached) {
2465
2401
  cached.cachedAt = (/* @__PURE__ */ new Date()).toISOString();
2466
- writeCache2(cachePath, cached);
2402
+ writeCache(cachePath, cached);
2467
2403
  cleanedActions = cached.data.actions;
2468
2404
  cacheHit = true;
2469
2405
  } else {
@@ -2476,7 +2412,7 @@ async function actionsSearchCommand(platform, query, options) {
2476
2412
  method: action.method,
2477
2413
  path: action.path
2478
2414
  }));
2479
- writeCache2(cachePath, makeCacheEntry(
2415
+ writeCache(cachePath, makeCacheEntry(
2480
2416
  `${platform}_${query}_${agentType || "knowledge"}`,
2481
2417
  { actions: cleanedActions },
2482
2418
  result.etag
@@ -2500,7 +2436,7 @@ async function actionsSearchCommand(platform, query, options) {
2500
2436
  if (cacheHit && cached) {
2501
2437
  response._cache = buildCacheMeta(cached, true);
2502
2438
  } else {
2503
- const freshEntry = readCache2(cachePath);
2439
+ const freshEntry = readCache(cachePath);
2504
2440
  response._cache = buildCacheMeta(freshEntry, false);
2505
2441
  }
2506
2442
  json(response);
@@ -2560,7 +2496,7 @@ Execute: ${pc6.cyan(`one actions execute ${platform} <actionId> <connectionK
2560
2496
  async function actionsKnowledgeCommand(platform, actionId, options) {
2561
2497
  const cachePath = knowledgeCachePath(actionId);
2562
2498
  if (options.cacheStatus) {
2563
- const entry = readCache2(cachePath);
2499
+ const entry = readCache(cachePath);
2564
2500
  if (!entry) {
2565
2501
  json({
2566
2502
  cached: false,
@@ -2607,44 +2543,13 @@ async function actionsKnowledgeCommand(platform, actionId, options) {
2607
2543
  const spinner5 = createSpinner();
2608
2544
  spinner5.start(`Loading knowledge for action ${pc6.dim(actionId)}...`);
2609
2545
  try {
2610
- const useCache = options.cache !== false;
2611
- const cached = useCache ? readCache2(cachePath) : null;
2612
- let knowledgeData;
2613
- let cacheHit = false;
2614
- let cacheEntry = cached;
2615
- if (cached && isFresh(cached) && useCache) {
2616
- knowledgeData = cached.data;
2617
- cacheHit = true;
2618
- } else {
2619
- try {
2620
- const result = await api.getActionKnowledgeWithMeta(
2621
- actionId,
2622
- cached?.etag ?? void 0
2623
- );
2624
- if (result.status === 304 && cached) {
2625
- cached.cachedAt = (/* @__PURE__ */ new Date()).toISOString();
2626
- writeCache2(cachePath, cached);
2627
- knowledgeData = cached.data;
2628
- cacheHit = true;
2629
- } else {
2630
- knowledgeData = result.data;
2631
- const newEntry = makeCacheEntry(actionId, knowledgeData, result.etag);
2632
- writeCache2(cachePath, newEntry);
2633
- cacheEntry = newEntry;
2634
- }
2635
- } catch (fetchError) {
2636
- if (cached) {
2637
- process.stderr.write(
2638
- `Warning: serving cached knowledge (network unavailable, cached ${formatAge(getAge(cached))} ago)
2639
- `
2640
- );
2641
- knowledgeData = cached.data;
2642
- cacheHit = true;
2643
- } else {
2644
- throw fetchError;
2645
- }
2646
- }
2647
- }
2546
+ const { details, cacheHit, entry } = await resolveActionDetails(api, actionId, {
2547
+ useCache: options.cache !== false
2548
+ });
2549
+ const knowledgeData = {
2550
+ knowledge: details.knowledge || "No knowledge was found",
2551
+ method: details.method || "No method was found"
2552
+ };
2648
2553
  const knowledgeWithGuidance = buildActionKnowledgeWithGuidance(
2649
2554
  knowledgeData.knowledge,
2650
2555
  knowledgeData.method,
@@ -2655,7 +2560,7 @@ async function actionsKnowledgeCommand(platform, actionId, options) {
2655
2560
  const response = {
2656
2561
  knowledge: knowledgeWithGuidance,
2657
2562
  method: knowledgeData.method,
2658
- _cache: buildCacheMeta(cacheEntry, cacheHit)
2563
+ _cache: buildCacheMeta(entry, cacheHit)
2659
2564
  };
2660
2565
  json(response);
2661
2566
  return;
@@ -2693,7 +2598,7 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
2693
2598
  const spinner5 = createSpinner();
2694
2599
  spinner5.start("Loading action details...");
2695
2600
  try {
2696
- const actionDetails = await api.getActionDetails(actionId);
2601
+ const { details: actionDetails, cacheHit: preflightCacheHit } = await resolveActionDetails(api, actionId, { useCache: options.cache !== false });
2697
2602
  if (!isMethodAllowed(actionDetails.method, permissions)) {
2698
2603
  spinner5.stop("Permission denied");
2699
2604
  error(
@@ -2739,7 +2644,8 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
2739
2644
  url: actionDetails.path
2740
2645
  },
2741
2646
  response: mockResponse,
2742
- ...mockResponse === null ? { message: "No example output available for this action" } : {}
2647
+ ...mockResponse === null ? { message: "No example output available for this action" } : {},
2648
+ _preflight: { cache: preflightCacheHit ? "hit" : "miss" }
2743
2649
  });
2744
2650
  return;
2745
2651
  }
@@ -2780,7 +2686,8 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
2780
2686
  headers: options.dryRun ? result.requestConfig.headers : void 0,
2781
2687
  data: options.dryRun ? result.requestConfig.data : void 0
2782
2688
  },
2783
- response: options.dryRun ? void 0 : result.responseData
2689
+ response: options.dryRun ? void 0 : result.responseData,
2690
+ _preflight: { cache: preflightCacheHit ? "hit" : "miss" }
2784
2691
  });
2785
2692
  return;
2786
2693
  }
@@ -2824,7 +2731,7 @@ function parseParallelSegments() {
2824
2731
  error('Could not locate "actions execute" in argv');
2825
2732
  }
2826
2733
  const raw = argv.slice(execIdx + 1);
2827
- const flags = { dryRun: false, mock: false, skipValidation: false, maxConcurrency: 5 };
2734
+ const flags = { dryRun: false, mock: false, skipValidation: false, maxConcurrency: 5, useCache: true };
2828
2735
  const cleaned = [];
2829
2736
  for (let i = 0; i < raw.length; i++) {
2830
2737
  const t = raw[i];
@@ -2841,6 +2748,10 @@ function parseParallelSegments() {
2841
2748
  flags.skipValidation = true;
2842
2749
  continue;
2843
2750
  }
2751
+ if (t === "--no-cache") {
2752
+ flags.useCache = false;
2753
+ continue;
2754
+ }
2844
2755
  if (t === "--max-concurrency") {
2845
2756
  flags.maxConcurrency = parseInt(raw[++i], 10) || 5;
2846
2757
  continue;
@@ -2930,8 +2841,11 @@ async function actionsExecuteParallelCommand() {
2930
2841
  segErrors.push(`Connection key "${seg.connectionKey}" is not allowed`);
2931
2842
  }
2932
2843
  let actionDetails;
2844
+ let preflightCacheHit = false;
2933
2845
  try {
2934
- actionDetails = await api.getActionDetails(seg.actionId);
2846
+ const resolved = await resolveActionDetails(api, seg.actionId, { useCache: flags.useCache });
2847
+ actionDetails = resolved.details;
2848
+ preflightCacheHit = resolved.cacheHit;
2935
2849
  } catch (err) {
2936
2850
  segErrors.push(`Action not found: ${err instanceof Error ? err.message : String(err)}`);
2937
2851
  }
@@ -2977,7 +2891,7 @@ async function actionsExecuteParallelCommand() {
2977
2891
  if (segErrors.length > 0) {
2978
2892
  errors.push({ segment: i + 1, label, messages: segErrors });
2979
2893
  } else if (actionDetails) {
2980
- prepared.push({ segment: seg, index: i, actionDetails, data, pathVariables, queryParams, headers });
2894
+ prepared.push({ segment: seg, index: i, actionDetails, preflightCacheHit, data, pathVariables, queryParams, headers });
2981
2895
  }
2982
2896
  }
2983
2897
  if (errors.length > 0) {
@@ -3015,7 +2929,8 @@ async function actionsExecuteParallelCommand() {
3015
2929
  durationMs: Date.now() - start,
3016
2930
  mock: true,
3017
2931
  request: { method: action.actionDetails.method, url: action.actionDetails.path },
3018
- response: mockResponse
2932
+ response: mockResponse,
2933
+ _preflight: { cache: action.preflightCacheHit ? "hit" : "miss" }
3019
2934
  };
3020
2935
  }
3021
2936
  const result = await api.executePassthroughRequest({
@@ -3042,7 +2957,8 @@ async function actionsExecuteParallelCommand() {
3042
2957
  url: result.requestConfig.url,
3043
2958
  ...flags.dryRun ? { headers: result.requestConfig.headers, data: result.requestConfig.data } : {}
3044
2959
  },
3045
- response: flags.dryRun ? void 0 : result.responseData
2960
+ response: flags.dryRun ? void 0 : result.responseData,
2961
+ _preflight: { cache: action.preflightCacheHit ? "hit" : "miss" }
3046
2962
  };
3047
2963
  })
3048
2964
  );
@@ -3123,8 +3039,8 @@ function colorMethod(method) {
3123
3039
  import pc7 from "picocolors";
3124
3040
 
3125
3041
  // src/lib/flow-validator.ts
3126
- import fs5 from "fs";
3127
- import path5 from "path";
3042
+ import fs4 from "fs";
3043
+ import path4 from "path";
3128
3044
  import { spawnSync } from "child_process";
3129
3045
  function validateFlowSchema(flow2) {
3130
3046
  const errors = [];
@@ -3189,32 +3105,32 @@ function validateStepsArray(steps, pathPrefix, errors) {
3189
3105
  const validTypes = FLOW_SCHEMA.stepTypes.map((st) => st.type);
3190
3106
  for (let i = 0; i < steps.length; i++) {
3191
3107
  const step = steps[i];
3192
- const path13 = `${pathPrefix}[${i}]`;
3108
+ const path12 = `${pathPrefix}[${i}]`;
3193
3109
  if (!step || typeof step !== "object" || Array.isArray(step)) {
3194
- errors.push({ path: path13, message: "Step must be an object" });
3110
+ errors.push({ path: path12, message: "Step must be an object" });
3195
3111
  continue;
3196
3112
  }
3197
3113
  const s = step;
3198
3114
  if (!s.id || typeof s.id !== "string") {
3199
- errors.push({ path: `${path13}.id`, message: 'Step must have a string "id"' });
3115
+ errors.push({ path: `${path12}.id`, message: 'Step must have a string "id"' });
3200
3116
  }
3201
3117
  if (!s.name || typeof s.name !== "string") {
3202
- errors.push({ path: `${path13}.name`, message: 'Step must have a string "name"' });
3118
+ errors.push({ path: `${path12}.name`, message: 'Step must have a string "name"' });
3203
3119
  }
3204
3120
  if (!s.type || !validTypes.includes(s.type)) {
3205
- errors.push({ path: `${path13}.type`, message: `Step type must be one of: ${validTypes.join(", ")}` });
3121
+ errors.push({ path: `${path12}.type`, message: `Step type must be one of: ${validTypes.join(", ")}` });
3206
3122
  continue;
3207
3123
  }
3208
3124
  if (s.requires !== void 0) {
3209
3125
  if (!Array.isArray(s.requires)) {
3210
- errors.push({ path: `${path13}.requires`, message: '"requires" must be an array of selector strings (e.g. ["$.steps.foo.output.bar"])' });
3126
+ errors.push({ path: `${path12}.requires`, message: '"requires" must be an array of selector strings (e.g. ["$.steps.foo.output.bar"])' });
3211
3127
  } else {
3212
3128
  for (let r = 0; r < s.requires.length; r++) {
3213
3129
  const sel = s.requires[r];
3214
3130
  if (typeof sel !== "string") {
3215
- errors.push({ path: `${path13}.requires[${r}]`, message: '"requires" entry must be a selector string' });
3131
+ errors.push({ path: `${path12}.requires[${r}]`, message: '"requires" entry must be a selector string' });
3216
3132
  } else if (!sel.startsWith("$.")) {
3217
- errors.push({ path: `${path13}.requires[${r}]`, message: `"requires" entry "${sel}" must be a selector starting with "$." (e.g. "$.steps.foo.output.bar")` });
3133
+ errors.push({ path: `${path12}.requires[${r}]`, message: `"requires" entry "${sel}" must be a selector starting with "$." (e.g. "$.steps.foo.output.bar")` });
3218
3134
  }
3219
3135
  }
3220
3136
  }
@@ -3222,7 +3138,7 @@ function validateStepsArray(steps, pathPrefix, errors) {
3222
3138
  if (s.onError && typeof s.onError === "object") {
3223
3139
  const oe = s.onError;
3224
3140
  if (!FLOW_SCHEMA.errorStrategies.includes(oe.strategy)) {
3225
- errors.push({ path: `${path13}.onError.strategy`, message: `Error strategy must be one of: ${FLOW_SCHEMA.errorStrategies.join(", ")}` });
3141
+ errors.push({ path: `${path12}.onError.strategy`, message: `Error strategy must be one of: ${FLOW_SCHEMA.errorStrategies.join(", ")}` });
3226
3142
  }
3227
3143
  }
3228
3144
  const descriptor = getStepTypeDescriptor(s.type);
@@ -3232,14 +3148,14 @@ function validateStepsArray(steps, pathPrefix, errors) {
3232
3148
  if (!configObj || typeof configObj !== "object") {
3233
3149
  const hint = detectFlatConfigHint(s, descriptor);
3234
3150
  errors.push({
3235
- path: `${path13}.${configKey}`,
3151
+ path: `${path12}.${configKey}`,
3236
3152
  message: `${capitalize(descriptor.type)} step must have a "${configKey}" config object${hint}`
3237
3153
  });
3238
3154
  continue;
3239
3155
  }
3240
3156
  const config2 = configObj;
3241
3157
  for (const [fieldName, fd] of Object.entries(descriptor.fields)) {
3242
- const fieldPath = `${path13}.${configKey}.${fieldName}`;
3158
+ const fieldPath = `${path12}.${configKey}.${fieldName}`;
3243
3159
  const value = config2[fieldName];
3244
3160
  if (fd.required && (value === void 0 || value === null || value === "")) {
3245
3161
  errors.push({ path: fieldPath, message: `${capitalize(descriptor.type)} must have ${fd.type === "string" ? "a string" : fd.type === "array" ? "a" : "a"} "${fieldName}"` });
@@ -3272,30 +3188,30 @@ function validateStepsArray(steps, pathPrefix, errors) {
3272
3188
  }
3273
3189
  }
3274
3190
  if (descriptor.type === "action") {
3275
- validateConnectionForm(config2, `${path13}.${configKey}`, errors);
3191
+ validateConnectionForm(config2, `${path12}.${configKey}`, errors);
3276
3192
  }
3277
3193
  if (descriptor.type === "code") {
3278
3194
  const hasSource = typeof config2.source === "string" && config2.source.length > 0;
3279
3195
  const hasModule = typeof config2.module === "string" && config2.module.length > 0;
3280
3196
  if (!hasSource && !hasModule) {
3281
- errors.push({ path: `${path13}.${configKey}`, message: 'Code step must define either "source" (inline JS) or "module" (path to .mjs file)' });
3197
+ errors.push({ path: `${path12}.${configKey}`, message: 'Code step must define either "source" (inline JS) or "module" (path to .mjs file)' });
3282
3198
  } else if (hasSource && hasModule) {
3283
- errors.push({ path: `${path13}.${configKey}`, message: 'Code step cannot define both "source" and "module" \u2014 pick one' });
3199
+ errors.push({ path: `${path12}.${configKey}`, message: 'Code step cannot define both "source" and "module" \u2014 pick one' });
3284
3200
  }
3285
3201
  if (hasModule) {
3286
3202
  const m = config2.module;
3287
3203
  if (m.startsWith("/") || /^[a-zA-Z]:[\\/]/.test(m)) {
3288
- errors.push({ path: `${path13}.${configKey}.module`, message: "Code module path must be relative to the flow folder (no absolute paths)" });
3204
+ errors.push({ path: `${path12}.${configKey}.module`, message: "Code module path must be relative to the flow folder (no absolute paths)" });
3289
3205
  } else if (m.split(/[\\/]/).includes("..")) {
3290
- errors.push({ path: `${path13}.${configKey}.module`, message: 'Code module path must not escape the flow folder ("..")' });
3206
+ errors.push({ path: `${path12}.${configKey}.module`, message: 'Code module path must not escape the flow folder ("..")' });
3291
3207
  } else if (!m.endsWith(".mjs")) {
3292
- errors.push({ path: `${path13}.${configKey}.module`, message: "Code module must be a .mjs file" });
3208
+ errors.push({ path: `${path12}.${configKey}.module`, message: "Code module must be a .mjs file" });
3293
3209
  }
3294
3210
  }
3295
3211
  if (hasSource) {
3296
3212
  const syntaxError = checkCodeSourceSyntax(config2.source);
3297
3213
  if (syntaxError) {
3298
- errors.push({ path: `${path13}.${configKey}.source`, message: `Syntax error in code step: ${syntaxError}` });
3214
+ errors.push({ path: `${path12}.${configKey}.source`, message: `Syntax error in code step: ${syntaxError}` });
3299
3215
  }
3300
3216
  }
3301
3217
  }
@@ -3367,16 +3283,16 @@ function validateStepIds(flow2) {
3367
3283
  function collectIds(steps, pathPrefix) {
3368
3284
  for (let i = 0; i < steps.length; i++) {
3369
3285
  const step = steps[i];
3370
- const path13 = `${pathPrefix}[${i}]`;
3286
+ const path12 = `${pathPrefix}[${i}]`;
3371
3287
  if (seen.has(step.id)) {
3372
- errors.push({ path: `${path13}.id`, message: `Duplicate step ID: "${step.id}"` });
3288
+ errors.push({ path: `${path12}.id`, message: `Duplicate step ID: "${step.id}"` });
3373
3289
  } else {
3374
3290
  seen.add(step.id);
3375
3291
  }
3376
3292
  for (const { configKey, fieldName } of nestedKeys) {
3377
3293
  const config2 = step[configKey];
3378
3294
  if (config2 && Array.isArray(config2[fieldName])) {
3379
- collectIds(config2[fieldName], `${path13}.${configKey}.${fieldName}`);
3295
+ collectIds(config2[fieldName], `${path12}.${configKey}.${fieldName}`);
3380
3296
  }
3381
3297
  }
3382
3298
  }
@@ -3424,7 +3340,7 @@ function validateSelectorReferences(flow2) {
3424
3340
  }
3425
3341
  return selectors;
3426
3342
  }
3427
- function checkSelectors(selectors, path13, precedingStepIds) {
3343
+ function checkSelectors(selectors, path12, precedingStepIds) {
3428
3344
  for (const selector of selectors) {
3429
3345
  const parts = selector.split(".");
3430
3346
  if (parts.length < 3) continue;
@@ -3432,15 +3348,15 @@ function validateSelectorReferences(flow2) {
3432
3348
  if (root === "input") {
3433
3349
  const inputName = parts[2];
3434
3350
  if (!inputNames.has(inputName)) {
3435
- errors.push({ path: path13, message: `Selector "${selector}" references undefined input "${inputName}"` });
3351
+ errors.push({ path: path12, message: `Selector "${selector}" references undefined input "${inputName}"` });
3436
3352
  }
3437
3353
  } else if (root === "steps") {
3438
3354
  const stepId = parts[2].replace(/[\[\]]/g, "").split(/[\[\]]/)[0];
3439
3355
  if (!allStepIds.has(stepId)) {
3440
- errors.push({ path: path13, message: `Selector "${selector}" references undefined step "${stepId}"` });
3356
+ errors.push({ path: path12, message: `Selector "${selector}" references undefined step "${stepId}"` });
3441
3357
  } else if (precedingStepIds && !precedingStepIds.has(stepId)) {
3442
3358
  errors.push({
3443
- path: path13,
3359
+ path: path12,
3444
3360
  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.`
3445
3361
  });
3446
3362
  }
@@ -3448,20 +3364,20 @@ function validateSelectorReferences(flow2) {
3448
3364
  }
3449
3365
  }
3450
3366
  const EXPRESSION_FIELDS = /* @__PURE__ */ new Set(["condition.expression", "while.condition"]);
3451
- function checkOperatorsInSelectorField(value, path13) {
3367
+ function checkOperatorsInSelectorField(value, path12) {
3452
3368
  if (typeof value === "string" && value.startsWith("$.")) {
3453
3369
  if (value.includes("||")) {
3454
- 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.` });
3370
+ 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.` });
3455
3371
  } else if (value.includes("&&")) {
3456
- 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.` });
3372
+ 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.` });
3457
3373
  }
3458
3374
  } else if (value && typeof value === "object" && !Array.isArray(value)) {
3459
3375
  for (const [k, v] of Object.entries(value)) {
3460
- checkOperatorsInSelectorField(v, `${path13}.${k}`);
3376
+ checkOperatorsInSelectorField(v, `${path12}.${k}`);
3461
3377
  }
3462
3378
  } else if (Array.isArray(value)) {
3463
3379
  for (let i = 0; i < value.length; i++) {
3464
- checkOperatorsInSelectorField(value[i], `${path13}[${i}]`);
3380
+ checkOperatorsInSelectorField(value[i], `${path12}[${i}]`);
3465
3381
  }
3466
3382
  }
3467
3383
  }
@@ -3529,10 +3445,10 @@ var VALID_OUTPUT_SCHEMA_TYPES = /* @__PURE__ */ new Set(["string", "number", "bo
3529
3445
  function isOutputSchemaObject(v) {
3530
3446
  return !!v && typeof v === "object" && !Array.isArray(v);
3531
3447
  }
3532
- function walkOutputSchema(schema, path13) {
3448
+ function walkOutputSchema(schema, path12) {
3533
3449
  let current = schema;
3534
- for (let i = 0; i < path13.length; i++) {
3535
- const seg = path13[i];
3450
+ for (let i = 0; i < path12.length; i++) {
3451
+ const seg = path12[i];
3536
3452
  if (typeof current === "string") {
3537
3453
  return current === "unknown" || current === "object" || current === "array" ? "opaque" : "opaque";
3538
3454
  }
@@ -3683,8 +3599,8 @@ function validateCodeModules(flow2, rootDir) {
3683
3599
  const stepPath = `${pathPrefix}[${i}]`;
3684
3600
  if (step.type === "code" && step.code?.module) {
3685
3601
  const m = step.code.module;
3686
- const abs = path5.resolve(rootDir, m);
3687
- if (!fs5.existsSync(abs)) {
3602
+ const abs = path4.resolve(rootDir, m);
3603
+ if (!fs4.existsSync(abs)) {
3688
3604
  errors.push({
3689
3605
  path: `${stepPath}.code.module`,
3690
3606
  message: `Code module "${m}" not found at ${abs}`
@@ -3713,8 +3629,8 @@ function validateCodeModules(flow2, rootDir) {
3713
3629
  }
3714
3630
 
3715
3631
  // src/commands/flow.ts
3716
- import fs6 from "fs";
3717
- import path6 from "path";
3632
+ import fs5 from "fs";
3633
+ import path5 from "path";
3718
3634
  function getConfig2() {
3719
3635
  const apiKey = getApiKey();
3720
3636
  if (!apiKey) {
@@ -3772,7 +3688,7 @@ async function flowCreateCommand(key, options) {
3772
3688
  if (raw.startsWith("@")) {
3773
3689
  const filePath = raw.slice(1);
3774
3690
  try {
3775
- raw = fs6.readFileSync(filePath, "utf-8");
3691
+ raw = fs5.readFileSync(filePath, "utf-8");
3776
3692
  } catch (err) {
3777
3693
  error(`Cannot read file "${filePath}": ${err.message}`);
3778
3694
  }
@@ -4002,9 +3918,9 @@ async function flowValidateCommand(keyOrPath) {
4002
3918
  rootDir = loaded.rootDir;
4003
3919
  } catch {
4004
3920
  const flowPath = resolveFlowPath(keyOrPath);
4005
- const content = fs6.readFileSync(flowPath, "utf-8");
3921
+ const content = fs5.readFileSync(flowPath, "utf-8");
4006
3922
  flowData = JSON.parse(content);
4007
- rootDir = path6.dirname(flowPath);
3923
+ rootDir = path5.dirname(flowPath);
4008
3924
  }
4009
3925
  } catch (err) {
4010
3926
  spinner5.stop("Validation failed");
@@ -4827,11 +4743,11 @@ function handleId(response, config2, records) {
4827
4743
  }
4828
4744
 
4829
4745
  // src/lib/memory/sync/state.ts
4830
- import fs7 from "fs";
4831
- import path7 from "path";
4832
- var SYNC_DIR = path7.join(".one", "sync");
4833
- var STATE_DIR = path7.join(SYNC_DIR, "state");
4834
- var LEGACY_SINGLE_FILE = path7.join(SYNC_DIR, "sync_state.json");
4746
+ import fs6 from "fs";
4747
+ import path6 from "path";
4748
+ var SYNC_DIR = path6.join(".one", "sync");
4749
+ var STATE_DIR = path6.join(SYNC_DIR, "state");
4750
+ var LEGACY_SINGLE_FILE = path6.join(SYNC_DIR, "sync_state.json");
4835
4751
  var legacyMigrationDone = false;
4836
4752
  function rowToState(row) {
4837
4753
  return {
@@ -4859,9 +4775,9 @@ function stateToRow(platform, model, state, lastError) {
4859
4775
  async function migrateLegacyOnce() {
4860
4776
  if (legacyMigrationDone) return;
4861
4777
  legacyMigrationDone = true;
4862
- if (fs7.existsSync(LEGACY_SINGLE_FILE)) {
4778
+ if (fs6.existsSync(LEGACY_SINGLE_FILE)) {
4863
4779
  try {
4864
- const raw = fs7.readFileSync(LEGACY_SINGLE_FILE, "utf-8");
4780
+ const raw = fs6.readFileSync(LEGACY_SINGLE_FILE, "utf-8");
4865
4781
  const legacy = JSON.parse(raw);
4866
4782
  const backend = await getBackend();
4867
4783
  for (const [platform, models] of Object.entries(legacy)) {
@@ -4871,32 +4787,32 @@ async function migrateLegacyOnce() {
4871
4787
  await backend.setSyncState(stateToRow(platform, model, modelState));
4872
4788
  }
4873
4789
  }
4874
- fs7.unlinkSync(LEGACY_SINGLE_FILE);
4790
+ fs6.unlinkSync(LEGACY_SINGLE_FILE);
4875
4791
  } catch {
4876
4792
  try {
4877
- fs7.unlinkSync(LEGACY_SINGLE_FILE);
4793
+ fs6.unlinkSync(LEGACY_SINGLE_FILE);
4878
4794
  } catch {
4879
4795
  }
4880
4796
  }
4881
4797
  }
4882
- if (fs7.existsSync(STATE_DIR)) {
4798
+ if (fs6.existsSync(STATE_DIR)) {
4883
4799
  try {
4884
4800
  const backend = await getBackend();
4885
- const platforms = fs7.readdirSync(STATE_DIR);
4801
+ const platforms = fs6.readdirSync(STATE_DIR);
4886
4802
  for (const platform of platforms) {
4887
- const platformDir = path7.join(STATE_DIR, platform);
4803
+ const platformDir = path6.join(STATE_DIR, platform);
4888
4804
  let entries;
4889
4805
  try {
4890
- entries = fs7.readdirSync(platformDir);
4806
+ entries = fs6.readdirSync(platformDir);
4891
4807
  } catch {
4892
4808
  continue;
4893
4809
  }
4894
4810
  for (const entry of entries) {
4895
4811
  if (!entry.endsWith(".json")) continue;
4896
4812
  const model = entry.slice(0, -".json".length);
4897
- const filePath = path7.join(platformDir, entry);
4813
+ const filePath = path6.join(platformDir, entry);
4898
4814
  try {
4899
- const raw = fs7.readFileSync(filePath, "utf-8");
4815
+ const raw = fs6.readFileSync(filePath, "utf-8");
4900
4816
  const modelState = JSON.parse(raw);
4901
4817
  const existing = await backend.getSyncState(platform, model);
4902
4818
  if (!existing) {
@@ -4906,7 +4822,7 @@ async function migrateLegacyOnce() {
4906
4822
  }
4907
4823
  }
4908
4824
  }
4909
- fs7.rmSync(STATE_DIR, { recursive: true, force: true });
4825
+ fs6.rmSync(STATE_DIR, { recursive: true, force: true });
4910
4826
  } catch {
4911
4827
  }
4912
4828
  }
@@ -4950,12 +4866,12 @@ async function removeModelState(platform, model) {
4950
4866
  }
4951
4867
 
4952
4868
  // src/lib/memory/sync/lock.ts
4953
- import fs8 from "fs";
4954
- import path8 from "path";
4955
- var LOCK_DIR_REL = path8.join(".one", "sync", "locks");
4869
+ import fs7 from "fs";
4870
+ import path7 from "path";
4871
+ var LOCK_DIR_REL = path7.join(".one", "sync", "locks");
4956
4872
  var STALE_MS = 30 * 60 * 1e3;
4957
4873
  function lockPath(platform, model) {
4958
- return path8.join(LOCK_DIR_REL, `${platform}_${model}`);
4874
+ return path7.join(LOCK_DIR_REL, `${platform}_${model}`);
4959
4875
  }
4960
4876
  function isProcessAlive(pid) {
4961
4877
  try {
@@ -4972,15 +4888,15 @@ var SyncLockError = class extends Error {
4972
4888
  }
4973
4889
  };
4974
4890
  function acquireSyncLock(platform, model) {
4975
- fs8.mkdirSync(LOCK_DIR_REL, { recursive: true });
4891
+ fs7.mkdirSync(LOCK_DIR_REL, { recursive: true });
4976
4892
  const dir = lockPath(platform, model);
4977
- const pidFile = path8.join(dir, "pid");
4893
+ const pidFile = path7.join(dir, "pid");
4978
4894
  try {
4979
- fs8.mkdirSync(dir);
4895
+ fs7.mkdirSync(dir);
4980
4896
  } catch (err) {
4981
4897
  const stat = (() => {
4982
4898
  try {
4983
- return fs8.statSync(dir);
4899
+ return fs7.statSync(dir);
4984
4900
  } catch {
4985
4901
  return null;
4986
4902
  }
@@ -4989,7 +4905,7 @@ function acquireSyncLock(platform, model) {
4989
4905
  const age = Date.now() - stat.mtimeMs;
4990
4906
  let ownerPid = null;
4991
4907
  try {
4992
- const raw = fs8.readFileSync(pidFile, "utf-8");
4908
+ const raw = fs7.readFileSync(pidFile, "utf-8");
4993
4909
  const parsed = parseInt(raw.trim(), 10);
4994
4910
  if (!isNaN(parsed)) ownerPid = parsed;
4995
4911
  } catch {
@@ -4998,8 +4914,8 @@ function acquireSyncLock(platform, model) {
4998
4914
  const veryOld = age > STALE_MS;
4999
4915
  if (ownerDead || veryOld) {
5000
4916
  try {
5001
- fs8.rmSync(dir, { recursive: true, force: true });
5002
- fs8.mkdirSync(dir);
4917
+ fs7.rmSync(dir, { recursive: true, force: true });
4918
+ fs7.mkdirSync(dir);
5003
4919
  } catch {
5004
4920
  throw new SyncLockError(
5005
4921
  `Could not take over stale lock at ${dir}. Remove it manually if no sync is running.`
@@ -5016,13 +4932,13 @@ function acquireSyncLock(platform, model) {
5016
4932
  }
5017
4933
  }
5018
4934
  try {
5019
- fs8.writeFileSync(pidFile, String(process.pid));
4935
+ fs7.writeFileSync(pidFile, String(process.pid));
5020
4936
  } catch {
5021
4937
  }
5022
4938
  return {
5023
4939
  release() {
5024
4940
  try {
5025
- fs8.rmSync(dir, { recursive: true, force: true });
4941
+ fs7.rmSync(dir, { recursive: true, force: true });
5026
4942
  } catch {
5027
4943
  }
5028
4944
  }
@@ -5031,9 +4947,9 @@ function acquireSyncLock(platform, model) {
5031
4947
 
5032
4948
  // src/lib/memory/sync/hooks.ts
5033
4949
  import { spawn as spawn2 } from "child_process";
5034
- import fs9 from "fs";
5035
- import path9 from "path";
5036
- var EVENTS_DIR = path9.join(".one", "sync", "events");
4950
+ import fs8 from "fs";
4951
+ import path8 from "path";
4952
+ var EVENTS_DIR = path8.join(".one", "sync", "events");
5037
4953
  function classifyRecords(db, model, records, idField, tableExists2) {
5038
4954
  if (!tableExists2 || records.length === 0) {
5039
4955
  return { inserts: records, updates: [] };
@@ -5079,10 +4995,10 @@ async function fireHooks(hookCommand, events) {
5079
4995
  function appendEventLog(events) {
5080
4996
  if (events.length === 0) return;
5081
4997
  const { platform, model } = events[0];
5082
- fs9.mkdirSync(EVENTS_DIR, { recursive: true });
5083
- const logPath = path9.join(EVENTS_DIR, `${platform}_${model}.jsonl`);
4998
+ fs8.mkdirSync(EVENTS_DIR, { recursive: true });
4999
+ const logPath = path8.join(EVENTS_DIR, `${platform}_${model}.jsonl`);
5084
5000
  const lines = events.map((e) => JSON.stringify(e)).join("\n") + "\n";
5085
- fs9.appendFileSync(logPath, lines);
5001
+ fs8.appendFileSync(logPath, lines);
5086
5002
  }
5087
5003
  function runShellHook(command, events) {
5088
5004
  return new Promise((resolve) => {
@@ -5105,10 +5021,10 @@ function runShellHook(command, events) {
5105
5021
  }
5106
5022
 
5107
5023
  // src/lib/memory/sync/mem-writer.ts
5108
- function resolveWildcardPath(root, path13) {
5109
- const segments = path13.split("[]");
5024
+ function resolveWildcardPath(root, path12) {
5025
+ const segments = path12.split("[]");
5110
5026
  if (segments.length === 1) {
5111
- return [getByDotPath(root, path13)];
5027
+ return [getByDotPath(root, path12)];
5112
5028
  }
5113
5029
  const recurse = (value, idx) => {
5114
5030
  if (value === null || value === void 0) return [];
@@ -5134,8 +5050,8 @@ function resolveWildcardPath(root, path13) {
5134
5050
  function extractSearchableFromPaths(record, paths) {
5135
5051
  const parts = [];
5136
5052
  const perPath = [];
5137
- for (const path13 of paths) {
5138
- const values = resolveWildcardPath(record, path13);
5053
+ for (const path12 of paths) {
5054
+ const values = resolveWildcardPath(record, path12);
5139
5055
  const collected = [];
5140
5056
  const absorb = (v) => {
5141
5057
  if (v === null || v === void 0) return;
@@ -5151,9 +5067,9 @@ function extractSearchableFromPaths(record, paths) {
5151
5067
  for (const v of values) absorb(v);
5152
5068
  if (collected.length > 0) {
5153
5069
  parts.push(...collected);
5154
- perPath.push({ path: path13, found: true, sample: collected.join(" ").slice(0, 80) });
5070
+ perPath.push({ path: path12, found: true, sample: collected.join(" ").slice(0, 80) });
5155
5071
  } else {
5156
- perPath.push({ path: path13, found: false, sample: "" });
5072
+ perPath.push({ path: path12, found: false, sample: "" });
5157
5073
  }
5158
5074
  }
5159
5075
  const text5 = parts.join(" ").replace(/\s+/g, " ").trim();
@@ -5332,8 +5248,8 @@ function sleep(ms) {
5332
5248
  return new Promise((resolve) => setTimeout(resolve, ms));
5333
5249
  }
5334
5250
  function interpolate(template, record) {
5335
- return template.replace(/\{?\{(\w+(?:\.\w+)*)\}\}?/g, (_, path13) => {
5336
- const parts = path13.split(".");
5251
+ return template.replace(/\{?\{(\w+(?:\.\w+)*)\}\}?/g, (_, path12) => {
5252
+ const parts = path12.split(".");
5337
5253
  let value = record;
5338
5254
  for (const part of parts) {
5339
5255
  if (typeof value !== "object" || value === null) return "";
@@ -5361,8 +5277,8 @@ function deepMerge(target, source) {
5361
5277
  }
5362
5278
  return result;
5363
5279
  }
5364
- function getByDotPath2(obj, path13) {
5365
- const parts = path13.split(".");
5280
+ function getByDotPath2(obj, path12) {
5281
+ const parts = path12.split(".");
5366
5282
  let current = obj;
5367
5283
  for (const part of parts) {
5368
5284
  if (current === null || current === void 0 || typeof current !== "object") return void 0;
@@ -5371,8 +5287,8 @@ function getByDotPath2(obj, path13) {
5371
5287
  return current;
5372
5288
  }
5373
5289
  function stripExcludedFields(obj, paths) {
5374
- for (const path13 of paths) {
5375
- stripOnePath(obj, path13.replace(/\[\]/g, ".*").split("."));
5290
+ for (const path12 of paths) {
5291
+ stripOnePath(obj, path12.replace(/\[\]/g, ".*").split("."));
5376
5292
  }
5377
5293
  }
5378
5294
  function stripOnePath(obj, parts) {
@@ -5441,7 +5357,7 @@ async function enrichPhase(api, db, config2, model, idField, connectionKey, plat
5441
5357
  }
5442
5358
  let detailAction;
5443
5359
  try {
5444
- detailAction = await api.getActionDetails(config2.actionId);
5360
+ detailAction = (await resolveActionDetails(api, config2.actionId)).details;
5445
5361
  } catch (err) {
5446
5362
  throw new Error(
5447
5363
  `Enrich: could not load action ${config2.actionId}: ${err instanceof Error ? err.message : String(err)}`
@@ -5702,8 +5618,8 @@ function sleep2(ms) {
5702
5618
  return new Promise((resolve) => setTimeout(resolve, ms));
5703
5619
  }
5704
5620
  function stripFields(record, paths) {
5705
- for (const path13 of paths) {
5706
- stripOnePath2(record, path13.split("."));
5621
+ for (const path12 of paths) {
5622
+ stripOnePath2(record, path12.split("."));
5707
5623
  }
5708
5624
  }
5709
5625
  function stripOnePath2(obj, parts) {
@@ -5793,7 +5709,7 @@ async function syncModel(api, profile, options) {
5793
5709
  updateModelState(platform, model, { status: "failed", pagesProcessed, lastCursor }),
5794
5710
  (async () => {
5795
5711
  try {
5796
- const { getBackend: getBackend2 } = await import("./runtime-RVXAPQAZ.js");
5712
+ const { getBackend: getBackend2 } = await import("./runtime-3NDWRLXL.js");
5797
5713
  const backend = await getBackend2();
5798
5714
  await Promise.race([
5799
5715
  backend.close(),
@@ -5870,7 +5786,7 @@ async function syncModel(api, profile, options) {
5870
5786
  queryParams[param] = dateValue;
5871
5787
  }
5872
5788
  }
5873
- const actionDetails = await api.getActionDetails(profile.actionId);
5789
+ const { details: actionDetails } = await resolveActionDetails(api, profile.actionId);
5874
5790
  if (actionDetails.tags?.includes("custom")) {
5875
5791
  throw new Error(
5876
5792
  `Sync does not support custom actions. Action ${profile.actionId} is tagged "custom". Use a passthrough action \u2014 run 'one actions search ${platform} "${model}"' to find one, or compose a flow that chains passthrough calls if the logic is complex.`
@@ -6148,7 +6064,7 @@ async function syncModel(api, profile, options) {
6148
6064
  db.exec(`DROP TABLE IF EXISTS _seen_ids`);
6149
6065
  }
6150
6066
  if (options.toMemory !== false) {
6151
- const backend = await (await import("./runtime-RVXAPQAZ.js")).getBackend();
6067
+ const backend = await (await import("./runtime-3NDWRLXL.js")).getBackend();
6152
6068
  const type = `${platform}/${model}`;
6153
6069
  const existing = await backend.listKeysByType(type);
6154
6070
  const sourcePrefix = `${type}:`;
@@ -6228,7 +6144,7 @@ async function syncModel(api, profile, options) {
6228
6144
  let statusCounts;
6229
6145
  if (options.toMemory !== false) {
6230
6146
  try {
6231
- const backend = await (await import("./runtime-RVXAPQAZ.js")).getBackend();
6147
+ const backend = await (await import("./runtime-3NDWRLXL.js")).getBackend();
6232
6148
  const typeName = `${platform}/${model}`;
6233
6149
  const [active, archived] = await Promise.all([
6234
6150
  backend.count(typeName, { status: "active" }),
@@ -6724,20 +6640,20 @@ function inferProfileFromKnowledge(knowledge, modelName, platform) {
6724
6640
 
6725
6641
  // src/lib/memory/sync/schedule.ts
6726
6642
  import { spawnSync as spawnSync2 } from "child_process";
6727
- import fs11 from "fs";
6728
- import os6 from "os";
6729
- import path11 from "path";
6730
-
6731
- // src/lib/memory/sync/schedule-registry.ts
6732
6643
  import fs10 from "fs";
6733
6644
  import os5 from "os";
6734
6645
  import path10 from "path";
6735
- var REGISTRY_DIR = path10.join(os5.homedir(), ".one", "sync");
6736
- var REGISTRY_FILE = path10.join(REGISTRY_DIR, "schedules.json");
6646
+
6647
+ // src/lib/memory/sync/schedule-registry.ts
6648
+ import fs9 from "fs";
6649
+ import os4 from "os";
6650
+ import path9 from "path";
6651
+ var REGISTRY_DIR = path9.join(os4.homedir(), ".one", "sync");
6652
+ var REGISTRY_FILE = path9.join(REGISTRY_DIR, "schedules.json");
6737
6653
  function readRaw() {
6738
6654
  try {
6739
- if (!fs10.existsSync(REGISTRY_FILE)) return { schedules: [] };
6740
- const raw = fs10.readFileSync(REGISTRY_FILE, "utf-8");
6655
+ if (!fs9.existsSync(REGISTRY_FILE)) return { schedules: [] };
6656
+ const raw = fs9.readFileSync(REGISTRY_FILE, "utf-8");
6741
6657
  const parsed = JSON.parse(raw);
6742
6658
  if (!parsed || !Array.isArray(parsed.schedules)) return { schedules: [] };
6743
6659
  return parsed;
@@ -6746,13 +6662,13 @@ function readRaw() {
6746
6662
  }
6747
6663
  }
6748
6664
  function writeRaw(file) {
6749
- fs10.mkdirSync(REGISTRY_DIR, { recursive: true });
6665
+ fs9.mkdirSync(REGISTRY_DIR, { recursive: true });
6750
6666
  const tmp = REGISTRY_FILE + ".tmp";
6751
- fs10.writeFileSync(tmp, JSON.stringify(file, null, 2));
6752
- fs10.renameSync(tmp, REGISTRY_FILE);
6667
+ fs9.writeFileSync(tmp, JSON.stringify(file, null, 2));
6668
+ fs9.renameSync(tmp, REGISTRY_FILE);
6753
6669
  }
6754
6670
  function makeScheduleId(platform, cwd) {
6755
- const slug = path10.basename(cwd).replace(/[^a-zA-Z0-9_-]/g, "-").toLowerCase();
6671
+ const slug = path9.basename(cwd).replace(/[^a-zA-Z0-9_-]/g, "-").toLowerCase();
6756
6672
  return `${platform}-${slug}`;
6757
6673
  }
6758
6674
  function listRegistered() {
@@ -6786,7 +6702,7 @@ function removeRegistered(id) {
6786
6702
 
6787
6703
  // src/lib/memory/sync/schedule.ts
6788
6704
  var MARKER = "# one-sync";
6789
- var LOG_DIR_REL = path11.join(".one", "sync", "logs");
6705
+ var LOG_DIR_REL = path10.join(".one", "sync", "logs");
6790
6706
  function durationToCron(every) {
6791
6707
  const match = every.match(/^(\d+)([mhd])$/);
6792
6708
  if (!match) return null;
@@ -6819,13 +6735,13 @@ function cronExprToDuration(expr) {
6819
6735
  return null;
6820
6736
  }
6821
6737
  function isWindows() {
6822
- return os6.platform() === "win32";
6738
+ return os5.platform() === "win32";
6823
6739
  }
6824
6740
  function resolveOneBinary() {
6825
6741
  try {
6826
6742
  const entry = process.argv[1];
6827
- if (entry && fs11.existsSync(entry)) {
6828
- return fs11.realpathSync(entry);
6743
+ if (entry && fs10.existsSync(entry)) {
6744
+ return fs10.realpathSync(entry);
6829
6745
  }
6830
6746
  } catch {
6831
6747
  }
@@ -6903,7 +6819,7 @@ function migrateLegacyCronEntries() {
6903
6819
  const modelsMatch = command.match(/--models\s+(\S+)/);
6904
6820
  const models = modelsMatch ? modelsMatch[1].split(",") : void 0;
6905
6821
  const logMatch = command.match(/>>\s+"([^"]+)"/);
6906
- const logFile = logMatch ? logMatch[1] : path11.resolve(cwd, LOG_DIR_REL, `${platform}.log`);
6822
+ const logFile = logMatch ? logMatch[1] : path10.resolve(cwd, LOG_DIR_REL, `${platform}.log`);
6907
6823
  const id = makeScheduleId(platform, cwd);
6908
6824
  if (registeredIds.has(id)) continue;
6909
6825
  upsertRegistered({
@@ -6937,9 +6853,9 @@ function addSchedule(opts) {
6937
6853
  const cwd = process.cwd();
6938
6854
  const id = makeScheduleId(opts.platform, cwd);
6939
6855
  const replaced = getRegistered(id) !== void 0;
6940
- const logDir = path11.join(cwd, LOG_DIR_REL);
6941
- fs11.mkdirSync(logDir, { recursive: true });
6942
- const logFile = path11.join(logDir, `${opts.platform}.log`);
6856
+ const logDir = path10.join(cwd, LOG_DIR_REL);
6857
+ fs10.mkdirSync(logDir, { recursive: true });
6858
+ const logFile = path10.join(logDir, `${opts.platform}.log`);
6943
6859
  const entry = {
6944
6860
  id,
6945
6861
  platform: opts.platform,
@@ -6993,15 +6909,15 @@ function removeSchedule(idOrPlatform, options) {
6993
6909
  function scheduleStatus() {
6994
6910
  const entries = listSchedules();
6995
6911
  return entries.map((entry) => {
6996
- const logExists = fs11.existsSync(entry.logFile);
6997
- const logSize = logExists ? fs11.statSync(entry.logFile).size : 0;
6912
+ const logExists = fs10.existsSync(entry.logFile);
6913
+ const logSize = logExists ? fs10.statSync(entry.logFile).size : 0;
6998
6914
  let logTail = [];
6999
6915
  let lastRunAt = null;
7000
6916
  if (logExists) {
7001
6917
  try {
7002
- lastRunAt = fs11.statSync(entry.logFile).mtime.toISOString();
6918
+ lastRunAt = fs10.statSync(entry.logFile).mtime.toISOString();
7003
6919
  if (logSize > 0) {
7004
- const content = fs11.readFileSync(entry.logFile, "utf-8");
6920
+ const content = fs10.readFileSync(entry.logFile, "utf-8");
7005
6921
  logTail = content.trim().split("\n").slice(-10);
7006
6922
  }
7007
6923
  } catch {
@@ -7009,8 +6925,8 @@ function scheduleStatus() {
7009
6925
  }
7010
6926
  let drift = "ok";
7011
6927
  if (!entry.cronInstalled) drift = "missing-cron";
7012
- else if (!fs11.existsSync(entry.nodeBin)) drift = "stale-node-bin";
7013
- else if (!fs11.existsSync(entry.cliBin)) drift = "stale-cli-bin";
6928
+ else if (!fs10.existsSync(entry.nodeBin)) drift = "stale-node-bin";
6929
+ else if (!fs10.existsSync(entry.cliBin)) drift = "stale-cli-bin";
7014
6930
  return { entry, logExists, logSize, logTail, lastRunAt, drift };
7015
6931
  });
7016
6932
  }
@@ -7283,11 +7199,11 @@ function isNoise(s) {
7283
7199
  if (/^-?\d+(\.\d+)?([eE][-+]?\d+)?$/.test(s)) return true;
7284
7200
  return false;
7285
7201
  }
7286
- function recordSample(stats, path13, value, jsType, recordIndex, totalSamples) {
7287
- let s = stats.get(path13);
7202
+ function recordSample(stats, path12, value, jsType, recordIndex, totalSamples) {
7203
+ let s = stats.get(path12);
7288
7204
  if (!s) {
7289
7205
  s = {
7290
- path: path13,
7206
+ path: path12,
7291
7207
  total: totalSamples,
7292
7208
  recordIndices: /* @__PURE__ */ new Set(),
7293
7209
  lenSum: 0,
@@ -7296,7 +7212,7 @@ function recordSample(stats, path13, value, jsType, recordIndex, totalSamples) {
7296
7212
  primaryType: jsType,
7297
7213
  examples: []
7298
7214
  };
7299
- stats.set(path13, s);
7215
+ stats.set(path12, s);
7300
7216
  }
7301
7217
  s.recordIndices.add(recordIndex);
7302
7218
  s.lenSum += value.length;
@@ -7305,28 +7221,28 @@ function recordSample(stats, path13, value, jsType, recordIndex, totalSamples) {
7305
7221
  if (s.primaryType !== jsType) s.primaryType = "mixed";
7306
7222
  if (s.examples.length < 3 && value.length < 200) s.examples.push(value);
7307
7223
  }
7308
- function walkRecord(record, path13, stats, recordIndex, totalSamples) {
7224
+ function walkRecord(record, path12, stats, recordIndex, totalSamples) {
7309
7225
  if (record === null || record === void 0) return;
7310
7226
  if (typeof record === "string") {
7311
7227
  const trimmed = record.trim();
7312
- if (trimmed) recordSample(stats, path13, trimmed, "string", recordIndex, totalSamples);
7228
+ if (trimmed) recordSample(stats, path12, trimmed, "string", recordIndex, totalSamples);
7313
7229
  return;
7314
7230
  }
7315
7231
  if (typeof record === "number" || typeof record === "boolean") {
7316
7232
  const str = String(record);
7317
7233
  const kind = typeof record === "number" ? "number" : "boolean";
7318
- if (str) recordSample(stats, path13, str, kind, recordIndex, totalSamples);
7234
+ if (str) recordSample(stats, path12, str, kind, recordIndex, totalSamples);
7319
7235
  return;
7320
7236
  }
7321
7237
  if (Array.isArray(record)) {
7322
- const childPath = path13 ? `${path13}[]` : "[]";
7238
+ const childPath = path12 ? `${path12}[]` : "[]";
7323
7239
  for (const item of record) walkRecord(item, childPath, stats, recordIndex, totalSamples);
7324
7240
  return;
7325
7241
  }
7326
7242
  if (typeof record === "object") {
7327
7243
  for (const [key, value] of Object.entries(record)) {
7328
7244
  if (key.startsWith("_")) continue;
7329
- const childPath = path13 ? `${path13}.${key}` : key;
7245
+ const childPath = path12 ? `${path12}.${key}` : key;
7330
7246
  walkRecord(value, childPath, stats, recordIndex, totalSamples);
7331
7247
  }
7332
7248
  }
@@ -7535,8 +7451,8 @@ async function syncInitCommand(platform, model, options) {
7535
7451
  }
7536
7452
  if (actionId && !builtin) {
7537
7453
  try {
7538
- const knowledgeResp = await api.getActionKnowledge(actionId);
7539
- inferred = inferProfileFromKnowledge(knowledgeResp?.knowledge, model, platform);
7454
+ const { details } = await resolveActionDetails(api, actionId);
7455
+ inferred = inferProfileFromKnowledge(details.knowledge, model, platform);
7540
7456
  if (inferred.pagination) template.pagination = inferred.pagination;
7541
7457
  if (inferred.resultsPath) template.resultsPath = inferred.resultsPath;
7542
7458
  if (inferred.idField) template.idField = inferred.idField;
@@ -7732,7 +7648,7 @@ function buildSearchablePreview(profile, samples) {
7732
7648
  const first = samples[0];
7733
7649
  const paths = getSearchablePaths(profile);
7734
7650
  if (paths) {
7735
- const perPathAgg = paths.map((path13) => ({ path: path13, hits: 0, total: samples.length, sample: "" }));
7651
+ const perPathAgg = paths.map((path12) => ({ path: path12, hits: 0, total: samples.length, sample: "" }));
7736
7652
  for (const record of samples) {
7737
7653
  const { paths: perPath } = extractSearchableFromPaths(record, paths);
7738
7654
  perPath.forEach((p10, i) => {
@@ -7861,7 +7777,7 @@ ${result.total} results`);
7861
7777
  }
7862
7778
  }
7863
7779
  async function syncSqlCommand(platformModel, sql) {
7864
- const { syncSqlCommand: runSyncSql } = await import("./sql-V44IVBHX.js");
7780
+ const { syncSqlCommand: runSyncSql } = await import("./sql-ZABEXIXW.js");
7865
7781
  await runSyncSql(platformModel, sql);
7866
7782
  }
7867
7783
  async function syncDeleteCommand(platformModel, options) {
@@ -7939,7 +7855,7 @@ async function syncDeleteCommand(platformModel, options) {
7939
7855
  async function maybeAutoMigrateLegacy(platform, models) {
7940
7856
  const dbSize = getDatabaseSize(platform);
7941
7857
  if (!dbSize || dbSize === "0 B") return;
7942
- const { getBackend: getBackend2 } = await import("./runtime-RVXAPQAZ.js");
7858
+ const { getBackend: getBackend2 } = await import("./runtime-3NDWRLXL.js");
7943
7859
  const backend = await getBackend2();
7944
7860
  let memoryHasData = false;
7945
7861
  for (const model of models) {
@@ -7955,7 +7871,7 @@ async function maybeAutoMigrateLegacy(platform, models) {
7955
7871
  ` detected legacy .one/sync/data/${platform}.db (${dbSize}) \u2014 auto-migrating into memory before sync.
7956
7872
  `
7957
7873
  );
7958
- const { memMigrateCommand: memMigrateCommand3 } = await import("./migrate-J2ZRDEFB.js");
7874
+ const { memMigrateCommand: memMigrateCommand3 } = await import("./migrate-VV3VOXWJ.js");
7959
7875
  await memMigrateCommand3({ platform, yes: true });
7960
7876
  return;
7961
7877
  }
@@ -7964,7 +7880,7 @@ async function maybeAutoMigrateLegacy(platform, models) {
7964
7880
  initialValue: true
7965
7881
  });
7966
7882
  if (p7.isCancel(shouldMigrate) || !shouldMigrate) return;
7967
- const { memMigrateCommand: memMigrateCommand2 } = await import("./migrate-J2ZRDEFB.js");
7883
+ const { memMigrateCommand: memMigrateCommand2 } = await import("./migrate-VV3VOXWJ.js");
7968
7884
  await memMigrateCommand2({ platform, yes: true });
7969
7885
  }
7970
7886
  async function syncSuggestSearchableCommand(platformModel, options = {}) {
@@ -8025,7 +7941,7 @@ async function syncSuggestSearchableCommand(platformModel, options = {}) {
8025
7941
  async function syncListCommand(platform) {
8026
7942
  const profiles = listProfiles(platform);
8027
7943
  const state = await readSyncState();
8028
- const { getBackend: getBackend2 } = await import("./runtime-RVXAPQAZ.js");
7944
+ const { getBackend: getBackend2 } = await import("./runtime-3NDWRLXL.js");
8029
7945
  const backend = await getBackend2();
8030
7946
  const syncs = await Promise.all(profiles.map(async (p10) => {
8031
7947
  const modelState = state[p10.platform]?.[p10.model];
@@ -8663,16 +8579,16 @@ function projectEmbeddingApiKey(cfg) {
8663
8579
  }
8664
8580
  function redactSecrets(cfg) {
8665
8581
  const copy = JSON.parse(JSON.stringify(cfg));
8666
- for (const path13 of SECRET_PATHS) {
8667
- const val = getPath(copy, path13);
8582
+ for (const path12 of SECRET_PATHS) {
8583
+ const val = getPath(copy, path12);
8668
8584
  if (typeof val === "string" && val.length > 0) {
8669
- setPath(copy, path13, `${val.slice(0, 6)}\u2026(redacted, use --show-secrets)`);
8585
+ setPath(copy, path12, `${val.slice(0, 6)}\u2026(redacted, use --show-secrets)`);
8670
8586
  }
8671
8587
  }
8672
8588
  return copy;
8673
8589
  }
8674
- function getPath(obj, path13) {
8675
- const parts = path13.split(".");
8590
+ function getPath(obj, path12) {
8591
+ const parts = path12.split(".");
8676
8592
  let cur = obj;
8677
8593
  for (const part of parts) {
8678
8594
  if (cur == null || typeof cur !== "object") return void 0;
@@ -8680,8 +8596,8 @@ function getPath(obj, path13) {
8680
8596
  }
8681
8597
  return cur;
8682
8598
  }
8683
- function setPath(obj, path13, value) {
8684
- const parts = path13.split(".");
8599
+ function setPath(obj, path12, value) {
8600
+ const parts = path12.split(".");
8685
8601
  let cur = obj;
8686
8602
  for (let i = 0; i < parts.length - 1; i++) {
8687
8603
  const part = parts[i];
@@ -8691,8 +8607,8 @@ function setPath(obj, path13, value) {
8691
8607
  cur[parts[parts.length - 1]] = value;
8692
8608
  return obj;
8693
8609
  }
8694
- function unsetPath(obj, path13) {
8695
- const parts = path13.split(".");
8610
+ function unsetPath(obj, path12) {
8611
+ const parts = path12.split(".");
8696
8612
  let cur = obj;
8697
8613
  for (let i = 0; i < parts.length - 1; i++) {
8698
8614
  const part = parts[i];
@@ -8943,7 +8859,7 @@ async function memDoctorCommand() {
8943
8859
  }
8944
8860
  if (cfg.embedding.provider === "openai") {
8945
8861
  try {
8946
- const { embed: embed2 } = await import("./embedding-GZGDGIUA.js");
8862
+ const { embed: embed2 } = await import("./embedding-C3E4EAQ7.js");
8947
8863
  const result = await embed2("connectivity check");
8948
8864
  checks.push({
8949
8865
  name: "OpenAI embedding provider reachable",
@@ -9001,7 +8917,7 @@ ${pc10.dim(line)}`);
9001
8917
  }
9002
8918
 
9003
8919
  // src/commands/mem/export.ts
9004
- import fs12 from "fs";
8920
+ import fs11 from "fs";
9005
8921
  async function memExportCommand(outfile) {
9006
8922
  requireMemoryInit();
9007
8923
  const backend = await getBackend();
@@ -9034,14 +8950,14 @@ async function memExportCommand(outfile) {
9034
8950
  }
9035
8951
  return;
9036
8952
  }
9037
- fs12.writeFileSync(outfile, lines, "utf-8");
8953
+ fs11.writeFileSync(outfile, lines, "utf-8");
9038
8954
  okJson({ status: "ok", file: outfile, recordsWritten: records.length, storeTotal: stats.recordCount });
9039
8955
  }
9040
8956
  async function memImportCommand(file) {
9041
8957
  requireMemoryInit();
9042
- if (!fs12.existsSync(file)) error(`File not found: ${file}`);
8958
+ if (!fs11.existsSync(file)) error(`File not found: ${file}`);
9043
8959
  const backend = await getBackend();
9044
- const raw = fs12.readFileSync(file, "utf-8");
8960
+ const raw = fs11.readFileSync(file, "utf-8");
9045
8961
  const lines = raw.split("\n").filter((l) => l.trim().length > 0);
9046
8962
  let inserted = 0;
9047
8963
  let updated = 0;
@@ -9305,13 +9221,13 @@ async function cacheUpdateAllCommand() {
9305
9221
  for (const e of entries) {
9306
9222
  try {
9307
9223
  if (e.type === "knowledge") {
9308
- const result = await api.getActionKnowledgeWithMeta(e.entry.key);
9224
+ const result = await api.getActionDetailsWithMeta(e.entry.key);
9309
9225
  const newEntry = makeCacheEntry(e.entry.key, result.data, result.etag);
9310
- writeCache2(e.filePath, newEntry);
9226
+ writeCache(e.filePath, newEntry);
9311
9227
  updated++;
9312
9228
  } else {
9313
9229
  const refreshed = { ...e.entry, cachedAt: (/* @__PURE__ */ new Date()).toISOString() };
9314
- writeCache2(e.filePath, refreshed);
9230
+ writeCache(e.filePath, refreshed);
9315
9231
  updated++;
9316
9232
  }
9317
9233
  } catch (err) {
@@ -9397,6 +9313,7 @@ one --agent actions execute <platform> <actionId> <key> -d '{}' # Execute it
9397
9313
  - \`--mock\` \u2014 Return example response without making an API call (useful for building UI against a response shape)
9398
9314
  - \`--skip-validation\` \u2014 Skip input validation against the action schema
9399
9315
  - \`--output <path>\` \u2014 Save response to a file (for binary downloads like PDFs, images, documents)
9316
+ - \`--no-cache\` \u2014 Fetch action details fresh instead of from the local cache (execution itself is never cached)
9400
9317
 
9401
9318
  The CLI validates required parameters against the action schema before executing. If you're missing a required path variable, query param, or body field, you'll get a clear error listing what's missing and which flag to use. Pass \`--skip-validation\` to bypass.
9402
9319
 
@@ -9522,6 +9439,9 @@ one --agent actions execute <platform> <actionId> <connectionKey> [options]
9522
9439
  - \`--mock\` \u2014 Return example response without making an API call
9523
9440
  - \`--skip-validation\` \u2014 Skip input validation against the action schema
9524
9441
  - \`--output <path>\` \u2014 Save response to a file (for binary downloads like PDFs, images, documents)
9442
+ - \`--no-cache\` \u2014 Fetch action details fresh instead of from the local cache (execution itself is never cached)
9443
+
9444
+ Execute reuses the action details cached by \`actions knowledge\` (method, path, schema), so in the standard search \u2192 knowledge \u2192 execute flow it makes a single API call \u2014 the action being executed. The live response is never cached. In \`--agent\` mode the response includes \`"_preflight": {"cache": "hit"|"miss"}\` showing whether the lookup was served from disk.
9525
9445
 
9526
9446
  **Do NOT** pass path or query parameters in \`-d\`. Use the correct flags.
9527
9447
 
@@ -9536,13 +9456,13 @@ one --agent actions execute --parallel \\
9536
9456
  -- google-sheets append-row conn789 -d '{"values":["x"]}'
9537
9457
  \`\`\`
9538
9458
 
9539
- Each segment separated by \`--\` follows the same format: \`<platform> <actionId> <connectionKey> [-d ...] [--path-vars ...] [--query-params ...]\`. Global flags (\`--dry-run\`, \`--mock\`, \`--skip-validation\`) apply to all segments.
9459
+ Each segment separated by \`--\` follows the same format: \`<platform> <actionId> <connectionKey> [-d ...] [--path-vars ...] [--query-params ...]\`. Global flags (\`--dry-run\`, \`--mock\`, \`--skip-validation\`, \`--no-cache\`) apply to all segments.
9540
9460
 
9541
9461
  All segments are validated upfront before any execution starts \u2014 if one segment has bad params, nothing runs. Execution uses \`Promise.allSettled\` so if one action fails the rest still complete. Use \`--max-concurrency <n>\` (default 5) to control batch size.
9542
9462
 
9543
- Agent-mode output:
9463
+ Agent-mode output (each result carries its own \`_preflight\` showing whether that action's details were served from cache):
9544
9464
  \`\`\`json
9545
- {"parallel":true,"totalDurationMs":1234,"succeeded":2,"failed":0,"results":[{"segment":1,"platform":"gmail","actionId":"send-email","status":"success","durationMs":800,"response":{...}},{"segment":2,"platform":"slack","actionId":"post-message","status":"success","durationMs":600,"response":{...}}]}
9465
+ {"parallel":true,"totalDurationMs":1234,"succeeded":2,"failed":0,"results":[{"segment":1,"platform":"gmail","actionId":"send-email","status":"success","durationMs":800,"response":{...},"_preflight":{"cache":"hit"}},{"segment":2,"platform":"slack","actionId":"post-message","status":"success","durationMs":600,"response":{...},"_preflight":{"cache":"miss"}}]}
9546
9466
  \`\`\`
9547
9467
 
9548
9468
  ## Input Validation
@@ -9675,7 +9595,7 @@ var GUIDE_CACHE = `# One Cache \u2014 Reference
9675
9595
 
9676
9596
  ## Overview
9677
9597
 
9678
- The One CLI caches \`actions knowledge\` and \`actions search\` responses locally so repeated calls serve instantly from disk instead of hitting the API. This is the single biggest latency win for agents who call knowledge for the same actions repeatedly.
9598
+ The One CLI caches \`actions knowledge\` and \`actions search\` responses locally so repeated calls serve instantly from disk instead of hitting the API. The knowledge cache stores the action's full details (docs, method, path, schema), so \`actions execute\` reuses it for its preflight lookup \u2014 in the standard search \u2192 knowledge \u2192 execute flow, execute makes exactly one API call: the action itself.
9679
9599
 
9680
9600
  Cache location: \`~/.one/cache/knowledge/\` and \`~/.one/cache/search/\`
9681
9601
 
@@ -9685,6 +9605,7 @@ Cache location: \`~/.one/cache/knowledge/\` and \`~/.one/cache/search/\`
9685
9605
  - **Subsequent calls (within TTL)**: serves from cache instantly, no API call
9686
9606
  - **After TTL expires**: makes a conditional request (ETag). If content unchanged, refreshes the cache timestamp. If changed, writes fresh data.
9687
9607
  - **Network failure with stale cache**: serves the stale cache with a warning \u2014 never fails hard when a cache exists
9608
+ - **Shared preflight**: \`actions execute\`, flow action steps, and \`sync\` all read action details (method, path, validation schema) from the same cache and warm it on a miss \u2014 so a knowledge call, a flow run, and a later execute of the same action all reuse one cached lookup
9688
9609
 
9689
9610
  Default TTL: 3600 seconds (1 hour). Configure via \`ONE_CACHE_TTL\` env var or \`cacheTtl\` in \`~/.one/config.json\`.
9690
9611
 
@@ -9692,8 +9613,9 @@ Default TTL: 3600 seconds (1 hour). Configure via \`ONE_CACHE_TTL\` env var or \
9692
9613
 
9693
9614
  | Cached | Not Cached |
9694
9615
  |--------|-----------|
9695
- | \`actions knowledge\` (API docs, change infrequently) | \`actions execute\` (live data, always fresh) |
9616
+ | \`actions knowledge\` (API docs, change infrequently) | \`actions execute\` responses (live data, always fresh) |
9696
9617
  | \`actions search\` results | \`connection list\` (changes with add/remove) |
9618
+ | Action details used by execute / flow / sync preflight (method, path, schema) | |
9697
9619
 
9698
9620
  ## Agent Mode \`_cache\` Metadata
9699
9621
 
@@ -9724,8 +9646,13 @@ one --agent actions knowledge <platform> <actionId> --cache-status
9724
9646
 
9725
9647
  # Same for search
9726
9648
  one --agent actions search <platform> "<query>" --no-cache
9649
+
9650
+ # Same for execute's action-details preflight (the action itself always runs live)
9651
+ one --agent actions execute <platform> <actionId> <key> --no-cache
9727
9652
  \`\`\`
9728
9653
 
9654
+ In \`--agent\` mode, execute responses include \`"_preflight": {"cache": "hit"|"miss"}\` showing whether the action details came from disk.
9655
+
9729
9656
  ## Cache Management Commands
9730
9657
 
9731
9658
  \`\`\`bash
@@ -10637,7 +10564,7 @@ function buildWorkflowIdeas(connections) {
10637
10564
  }
10638
10565
 
10639
10566
  // src/commands/logout.ts
10640
- import fs13 from "fs";
10567
+ import fs12 from "fs";
10641
10568
  import * as p9 from "@clack/prompts";
10642
10569
  function formatWhoami(config2, apiKey, pc13) {
10643
10570
  const whoami = config2.whoami;
@@ -10670,12 +10597,12 @@ async function logoutCommand() {
10670
10597
  const globalPath = getGlobalConfigPath();
10671
10598
  const projectPath = getProjectConfigPath();
10672
10599
  let cleared = false;
10673
- if (fs13.existsSync(projectPath)) {
10674
- fs13.unlinkSync(projectPath);
10600
+ if (fs12.existsSync(projectPath)) {
10601
+ fs12.unlinkSync(projectPath);
10675
10602
  cleared = true;
10676
10603
  }
10677
- if (fs13.existsSync(globalPath)) {
10678
- fs13.unlinkSync(globalPath);
10604
+ if (fs12.existsSync(globalPath)) {
10605
+ fs12.unlinkSync(globalPath);
10679
10606
  cleared = true;
10680
10607
  }
10681
10608
  json({ status: cleared ? "logged_out" : "not_logged_in", message: cleared ? "Credentials cleared." : "No config found." });
@@ -10744,11 +10671,11 @@ async function logoutCommand() {
10744
10671
  }
10745
10672
  if (targetScope === "project" || targetScope === "both") {
10746
10673
  const projectPath = getProjectConfigPath();
10747
- if (fs13.existsSync(projectPath)) fs13.unlinkSync(projectPath);
10674
+ if (fs12.existsSync(projectPath)) fs12.unlinkSync(projectPath);
10748
10675
  }
10749
10676
  if (targetScope === "global" || targetScope === "both") {
10750
10677
  const globalPath = getGlobalConfigPath();
10751
- if (fs13.existsSync(globalPath)) fs13.unlinkSync(globalPath);
10678
+ if (fs12.existsSync(globalPath)) fs12.unlinkSync(globalPath);
10752
10679
  }
10753
10680
  p9.log.success("Credentials cleared.");
10754
10681
  p9.log.info("Your API key is still active. Manage keys at app.withone.ai/settings");
@@ -10966,8 +10893,8 @@ config.command("reset").description("Remove the project config for the current d
10966
10893
  return;
10967
10894
  }
10968
10895
  }
10969
- const fs15 = await import("fs");
10970
- fs15.unlinkSync(globalPath);
10896
+ const fs14 = await import("fs");
10897
+ fs14.unlinkSync(globalPath);
10971
10898
  if (isAgentMode()) {
10972
10899
  json({ deleted: true, scope: "global" });
10973
10900
  } else {
@@ -10984,15 +10911,15 @@ config.command("reset").description("Remove the project config for the current d
10984
10911
  }
10985
10912
  return;
10986
10913
  }
10987
- const fs14 = await import("fs");
10988
- const configContent = fs14.readFileSync(resolved.path, "utf-8");
10989
- fs14.unlinkSync(resolved.path);
10914
+ const fs13 = await import("fs");
10915
+ const configContent = fs13.readFileSync(resolved.path, "utf-8");
10916
+ fs13.unlinkSync(resolved.path);
10990
10917
  const next = resolveConfig();
10991
- fs14.mkdirSync(path12.dirname(resolved.path), { recursive: true });
10992
- fs14.writeFileSync(resolved.path, configContent);
10918
+ fs13.mkdirSync(path11.dirname(resolved.path), { recursive: true });
10919
+ fs13.writeFileSync(resolved.path, configContent);
10993
10920
  let fallbackLabel;
10994
10921
  if (next.scope === "project") {
10995
- fallbackLabel = `parent project config (${path12.basename(next.projectRoot)})`;
10922
+ fallbackLabel = `parent project config (${path11.basename(next.projectRoot)})`;
10996
10923
  } else if (next.scope === "global") {
10997
10924
  fallbackLabel = "global config";
10998
10925
  } else {
@@ -11001,7 +10928,7 @@ config.command("reset").description("Remove the project config for the current d
11001
10928
  if (!isAgentMode()) {
11002
10929
  const p10 = await import("@clack/prompts");
11003
10930
  const confirmed = await p10.confirm({
11004
- message: `Delete project config for ${path12.basename(resolved.projectRoot)}? Will fall back to ${fallbackLabel}.`,
10931
+ message: `Delete project config for ${path11.basename(resolved.projectRoot)}? Will fall back to ${fallbackLabel}.`,
11005
10932
  initialValue: false
11006
10933
  });
11007
10934
  if (p10.isCancel(confirmed) || !confirmed) {
@@ -11009,9 +10936,9 @@ config.command("reset").description("Remove the project config for the current d
11009
10936
  return;
11010
10937
  }
11011
10938
  }
11012
- fs14.unlinkSync(resolved.path);
10939
+ fs13.unlinkSync(resolved.path);
11013
10940
  try {
11014
- fs14.rmdirSync(path12.dirname(resolved.path));
10941
+ fs13.rmdirSync(path11.dirname(resolved.path));
11015
10942
  } catch {
11016
10943
  }
11017
10944
  if (isAgentMode()) {
@@ -11040,7 +10967,7 @@ actions.command("search <platform> <query>").description('Search for actions on
11040
10967
  actions.command("knowledge <platform> <actionId>").alias("k").description("Get full docs for an action \u2014 MUST call before execute to know required params").option("--no-cache", "Skip cache, fetch fresh from API").option("--cache-status", "Print cache metadata without fetching").action(async (platform, actionId, options) => {
11041
10968
  await actionsKnowledgeCommand(platform, actionId, options);
11042
10969
  });
11043
- actions.command("execute [platform] [actionId] [connectionKey]").alias("x").allowUnknownOption(true).allowExcessArguments(true).description("Execute an action (or multiple with --parallel, separated by --)").option("-d, --data <json>", "Request body as JSON").option("--path-vars <json>", "Path variables as JSON").option("--query-params <json>", "Query parameters as JSON").option("--headers <json>", "Additional headers as JSON").option("--form-data", "Send as multipart/form-data").option("--form-url-encoded", "Send as application/x-www-form-urlencoded").option("--dry-run", "Show request that would be sent without executing").option("--mock", "Return example response without making an API call").option("--skip-validation", "Skip input validation against the action schema").option("--output <path>", "Save binary response to a file (for non-JSON responses like file downloads)").option("--parallel", "Execute multiple actions concurrently (separate actions with --)").option("--max-concurrency <n>", "Max concurrent actions when using --parallel (default: 5)", "5").action(async (platform, actionId, connectionKey, options) => {
10970
+ actions.command("execute [platform] [actionId] [connectionKey]").alias("x").allowUnknownOption(true).allowExcessArguments(true).description("Execute an action (or multiple with --parallel, separated by --)").option("-d, --data <json>", "Request body as JSON").option("--path-vars <json>", "Path variables as JSON").option("--query-params <json>", "Query parameters as JSON").option("--headers <json>", "Additional headers as JSON").option("--form-data", "Send as multipart/form-data").option("--form-url-encoded", "Send as application/x-www-form-urlencoded").option("--dry-run", "Show request that would be sent without executing").option("--mock", "Return example response without making an API call").option("--skip-validation", "Skip input validation against the action schema").option("--no-cache", "Fetch action details fresh instead of using the local cache (execution itself is never cached)").option("--output <path>", "Save binary response to a file (for non-JSON responses like file downloads)").option("--parallel", "Execute multiple actions concurrently (separate actions with --)").option("--max-concurrency <n>", "Max concurrent actions when using --parallel (default: 5)", "5").action(async (platform, actionId, connectionKey, options) => {
11044
10971
  if (options.parallel) {
11045
10972
  await actionsExecuteParallelCommand();
11046
10973
  return;
@@ -11058,7 +10985,8 @@ actions.command("execute [platform] [actionId] [connectionKey]").alias("x").allo
11058
10985
  dryRun: options.dryRun,
11059
10986
  mock: options.mock,
11060
10987
  skipValidation: options.skipValidation,
11061
- output: options.output
10988
+ output: options.output,
10989
+ cache: options.cache
11062
10990
  });
11063
10991
  });
11064
10992
  var flow = program.command("flow").alias("f").description("Create, execute, and manage multi-step workflows");
@@ -11135,7 +11063,7 @@ program.command("guide [topic]").description("Full CLI usage guide for agents (t
11135
11063
  program.command("onboard").description("Agent onboarding \u2014 teaches your agent what the One CLI can do").option("--step <number>", "Run a specific onboarding step (1, 2, or 3)").action(async (options) => {
11136
11064
  await onboardCommand(options.step ? parseInt(options.step, 10) : void 0);
11137
11065
  });
11138
- program.command("update").description("Update the One CLI to the latest version").action(async () => {
11066
+ program.command("update").description("Update the One CLI to the latest version (background auto-update can be disabled with ONE_NO_AUTO_UPDATE=1)").action(async () => {
11139
11067
  await updateCommand();
11140
11068
  });
11141
11069
  program.command("whoami").description("Show the user, organization, and project for the current API key").action(async () => {