@withone/cli 1.44.2 → 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
@@ -644,14 +658,14 @@ async function fetchLatestVersionInfo() {
644
658
  return null;
645
659
  }
646
660
  }
647
- function readCache() {
661
+ function readCache2() {
648
662
  try {
649
663
  return JSON.parse(readFileSync(CACHE_PATH, "utf8"));
650
664
  } catch {
651
665
  return null;
652
666
  }
653
667
  }
654
- function writeCache(latestVersion, publishedAt) {
668
+ function writeCache2(latestVersion, publishedAt) {
655
669
  try {
656
670
  mkdirSync(join(homedir(), ".one"), { recursive: true });
657
671
  writeFileSync(CACHE_PATH, JSON.stringify({ lastCheck: Date.now(), latestVersion, publishedAt }));
@@ -660,16 +674,16 @@ function writeCache(latestVersion, publishedAt) {
660
674
  }
661
675
  async function checkLatestVersion() {
662
676
  const info = await fetchLatestVersionInfo();
663
- if (info) writeCache(info.version, info.publishedAt);
677
+ if (info) writeCache2(info.version, info.publishedAt);
664
678
  return info?.version ?? null;
665
679
  }
666
680
  async function checkLatestVersionCached() {
667
- const cache2 = readCache();
681
+ const cache2 = readCache2();
668
682
  if (cache2 && Date.now() - cache2.lastCheck < CHECK_INTERVAL_MS) {
669
683
  return { version: cache2.latestVersion, publishedAt: cache2.publishedAt ?? null };
670
684
  }
671
685
  const info = await fetchLatestVersionInfo();
672
- if (info) writeCache(info.version, info.publishedAt);
686
+ if (info) writeCache2(info.version, info.publishedAt);
673
687
  return info;
674
688
  }
675
689
  function getCurrentVersion() {
@@ -2340,123 +2354,6 @@ async function platformsCommand(options) {
2340
2354
  // src/commands/actions.ts
2341
2355
  import * as p6 from "@clack/prompts";
2342
2356
  import pc6 from "picocolors";
2343
-
2344
- // src/lib/cache.ts
2345
- import fs4 from "fs";
2346
- import path4 from "path";
2347
- import os4 from "os";
2348
- var CACHE_BASE = path4.join(os4.homedir(), ".one", "cache");
2349
- var KNOWLEDGE_DIR = path4.join(CACHE_BASE, "knowledge");
2350
- var SEARCH_DIR = path4.join(CACHE_BASE, "search");
2351
- function sanitizeFilename(input) {
2352
- return input.replace(/[^a-zA-Z0-9_\-\.]/g, "_");
2353
- }
2354
- function knowledgeCachePath(actionId) {
2355
- return path4.join(KNOWLEDGE_DIR, `${sanitizeFilename(actionId)}.json`);
2356
- }
2357
- function searchCachePath(platform, query, type) {
2358
- const key = `${platform}_${sanitizeFilename(query)}_${type || "knowledge"}`;
2359
- return path4.join(SEARCH_DIR, `${key}.json`);
2360
- }
2361
- function readCache2(filePath) {
2362
- try {
2363
- const content = fs4.readFileSync(filePath, "utf-8");
2364
- return JSON.parse(content);
2365
- } catch {
2366
- return null;
2367
- }
2368
- }
2369
- function writeCache2(filePath, entry) {
2370
- try {
2371
- const dir = path4.dirname(filePath);
2372
- fs4.mkdirSync(dir, { recursive: true });
2373
- fs4.writeFileSync(filePath, JSON.stringify(entry, null, 2));
2374
- } catch {
2375
- }
2376
- }
2377
- function isFresh(entry) {
2378
- const cachedTime = new Date(entry.cachedAt).getTime();
2379
- const now = Date.now();
2380
- return now - cachedTime < entry.ttl * 1e3;
2381
- }
2382
- function getAge(entry) {
2383
- return Math.floor((Date.now() - new Date(entry.cachedAt).getTime()) / 1e3);
2384
- }
2385
- function buildCacheMeta(entry, hit) {
2386
- if (!entry) {
2387
- return { hit: false, age: 0, fresh: false };
2388
- }
2389
- return {
2390
- hit,
2391
- age: getAge(entry),
2392
- fresh: isFresh(entry)
2393
- };
2394
- }
2395
- function formatAge(seconds) {
2396
- if (seconds < 60) return `${seconds}s`;
2397
- if (seconds < 3600) return `${Math.floor(seconds / 60)}m`;
2398
- if (seconds < 86400) {
2399
- const h2 = Math.floor(seconds / 3600);
2400
- const m = Math.floor(seconds % 3600 / 60);
2401
- return m > 0 ? `${h2}h ${m}m` : `${h2}h`;
2402
- }
2403
- const d = Math.floor(seconds / 86400);
2404
- const h = Math.floor(seconds % 86400 / 3600);
2405
- return h > 0 ? `${d}d ${h}h` : `${d}d`;
2406
- }
2407
- function listCacheEntries() {
2408
- const entries = [];
2409
- for (const [dir, type] of [[KNOWLEDGE_DIR, "knowledge"], [SEARCH_DIR, "search"]]) {
2410
- try {
2411
- const files = fs4.readdirSync(dir);
2412
- for (const file of files) {
2413
- if (!file.endsWith(".json")) continue;
2414
- const filePath = path4.join(dir, file);
2415
- const entry = readCache2(filePath);
2416
- if (entry) {
2417
- entries.push({ type, filePath, entry });
2418
- }
2419
- }
2420
- } catch {
2421
- }
2422
- }
2423
- return entries;
2424
- }
2425
- function clearAll() {
2426
- let count = 0;
2427
- for (const dir of [KNOWLEDGE_DIR, SEARCH_DIR]) {
2428
- try {
2429
- const files = fs4.readdirSync(dir);
2430
- for (const file of files) {
2431
- fs4.unlinkSync(path4.join(dir, file));
2432
- count++;
2433
- }
2434
- fs4.rmdirSync(dir);
2435
- } catch {
2436
- }
2437
- }
2438
- return count;
2439
- }
2440
- function clearEntry(actionId) {
2441
- const filePath = knowledgeCachePath(actionId);
2442
- try {
2443
- fs4.unlinkSync(filePath);
2444
- return true;
2445
- } catch {
2446
- return false;
2447
- }
2448
- }
2449
- function makeCacheEntry(key, data, etag) {
2450
- return {
2451
- key,
2452
- etag,
2453
- cachedAt: (/* @__PURE__ */ new Date()).toISOString(),
2454
- ttl: getCacheTtl(),
2455
- data
2456
- };
2457
- }
2458
-
2459
- // src/commands/actions.ts
2460
2357
  function getConfig() {
2461
2358
  const apiKey = getApiKey();
2462
2359
  if (!apiKey) {
@@ -2486,7 +2383,7 @@ async function actionsSearchCommand(platform, query, options) {
2486
2383
  const agentType = knowledgeAgent ? "knowledge" : options.type || "execute";
2487
2384
  const useCache = options.cache !== false;
2488
2385
  const cachePath = searchCachePath(platform, query, agentType || "knowledge");
2489
- const cached = useCache ? readCache2(cachePath) : null;
2386
+ const cached = useCache ? readCache(cachePath) : null;
2490
2387
  let cleanedActions;
2491
2388
  let cacheHit = false;
2492
2389
  if (cached && isFresh(cached)) {
@@ -2502,7 +2399,7 @@ async function actionsSearchCommand(platform, query, options) {
2502
2399
  );
2503
2400
  if (result.status === 304 && cached) {
2504
2401
  cached.cachedAt = (/* @__PURE__ */ new Date()).toISOString();
2505
- writeCache2(cachePath, cached);
2402
+ writeCache(cachePath, cached);
2506
2403
  cleanedActions = cached.data.actions;
2507
2404
  cacheHit = true;
2508
2405
  } else {
@@ -2515,7 +2412,7 @@ async function actionsSearchCommand(platform, query, options) {
2515
2412
  method: action.method,
2516
2413
  path: action.path
2517
2414
  }));
2518
- writeCache2(cachePath, makeCacheEntry(
2415
+ writeCache(cachePath, makeCacheEntry(
2519
2416
  `${platform}_${query}_${agentType || "knowledge"}`,
2520
2417
  { actions: cleanedActions },
2521
2418
  result.etag
@@ -2539,7 +2436,7 @@ async function actionsSearchCommand(platform, query, options) {
2539
2436
  if (cacheHit && cached) {
2540
2437
  response._cache = buildCacheMeta(cached, true);
2541
2438
  } else {
2542
- const freshEntry = readCache2(cachePath);
2439
+ const freshEntry = readCache(cachePath);
2543
2440
  response._cache = buildCacheMeta(freshEntry, false);
2544
2441
  }
2545
2442
  json(response);
@@ -2599,7 +2496,7 @@ Execute: ${pc6.cyan(`one actions execute ${platform} <actionId> <connectionK
2599
2496
  async function actionsKnowledgeCommand(platform, actionId, options) {
2600
2497
  const cachePath = knowledgeCachePath(actionId);
2601
2498
  if (options.cacheStatus) {
2602
- const entry = readCache2(cachePath);
2499
+ const entry = readCache(cachePath);
2603
2500
  if (!entry) {
2604
2501
  json({
2605
2502
  cached: false,
@@ -2646,44 +2543,13 @@ async function actionsKnowledgeCommand(platform, actionId, options) {
2646
2543
  const spinner5 = createSpinner();
2647
2544
  spinner5.start(`Loading knowledge for action ${pc6.dim(actionId)}...`);
2648
2545
  try {
2649
- const useCache = options.cache !== false;
2650
- const cached = useCache ? readCache2(cachePath) : null;
2651
- let knowledgeData;
2652
- let cacheHit = false;
2653
- let cacheEntry = cached;
2654
- if (cached && isFresh(cached) && useCache) {
2655
- knowledgeData = cached.data;
2656
- cacheHit = true;
2657
- } else {
2658
- try {
2659
- const result = await api.getActionKnowledgeWithMeta(
2660
- actionId,
2661
- cached?.etag ?? void 0
2662
- );
2663
- if (result.status === 304 && cached) {
2664
- cached.cachedAt = (/* @__PURE__ */ new Date()).toISOString();
2665
- writeCache2(cachePath, cached);
2666
- knowledgeData = cached.data;
2667
- cacheHit = true;
2668
- } else {
2669
- knowledgeData = result.data;
2670
- const newEntry = makeCacheEntry(actionId, knowledgeData, result.etag);
2671
- writeCache2(cachePath, newEntry);
2672
- cacheEntry = newEntry;
2673
- }
2674
- } catch (fetchError) {
2675
- if (cached) {
2676
- process.stderr.write(
2677
- `Warning: serving cached knowledge (network unavailable, cached ${formatAge(getAge(cached))} ago)
2678
- `
2679
- );
2680
- knowledgeData = cached.data;
2681
- cacheHit = true;
2682
- } else {
2683
- throw fetchError;
2684
- }
2685
- }
2686
- }
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
+ };
2687
2553
  const knowledgeWithGuidance = buildActionKnowledgeWithGuidance(
2688
2554
  knowledgeData.knowledge,
2689
2555
  knowledgeData.method,
@@ -2694,7 +2560,7 @@ async function actionsKnowledgeCommand(platform, actionId, options) {
2694
2560
  const response = {
2695
2561
  knowledge: knowledgeWithGuidance,
2696
2562
  method: knowledgeData.method,
2697
- _cache: buildCacheMeta(cacheEntry, cacheHit)
2563
+ _cache: buildCacheMeta(entry, cacheHit)
2698
2564
  };
2699
2565
  json(response);
2700
2566
  return;
@@ -2732,7 +2598,7 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
2732
2598
  const spinner5 = createSpinner();
2733
2599
  spinner5.start("Loading action details...");
2734
2600
  try {
2735
- const actionDetails = await api.getActionDetails(actionId);
2601
+ const { details: actionDetails, cacheHit: preflightCacheHit } = await resolveActionDetails(api, actionId, { useCache: options.cache !== false });
2736
2602
  if (!isMethodAllowed(actionDetails.method, permissions)) {
2737
2603
  spinner5.stop("Permission denied");
2738
2604
  error(
@@ -2778,7 +2644,8 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
2778
2644
  url: actionDetails.path
2779
2645
  },
2780
2646
  response: mockResponse,
2781
- ...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" }
2782
2649
  });
2783
2650
  return;
2784
2651
  }
@@ -2819,7 +2686,8 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
2819
2686
  headers: options.dryRun ? result.requestConfig.headers : void 0,
2820
2687
  data: options.dryRun ? result.requestConfig.data : void 0
2821
2688
  },
2822
- response: options.dryRun ? void 0 : result.responseData
2689
+ response: options.dryRun ? void 0 : result.responseData,
2690
+ _preflight: { cache: preflightCacheHit ? "hit" : "miss" }
2823
2691
  });
2824
2692
  return;
2825
2693
  }
@@ -2863,7 +2731,7 @@ function parseParallelSegments() {
2863
2731
  error('Could not locate "actions execute" in argv');
2864
2732
  }
2865
2733
  const raw = argv.slice(execIdx + 1);
2866
- const flags = { dryRun: false, mock: false, skipValidation: false, maxConcurrency: 5 };
2734
+ const flags = { dryRun: false, mock: false, skipValidation: false, maxConcurrency: 5, useCache: true };
2867
2735
  const cleaned = [];
2868
2736
  for (let i = 0; i < raw.length; i++) {
2869
2737
  const t = raw[i];
@@ -2880,6 +2748,10 @@ function parseParallelSegments() {
2880
2748
  flags.skipValidation = true;
2881
2749
  continue;
2882
2750
  }
2751
+ if (t === "--no-cache") {
2752
+ flags.useCache = false;
2753
+ continue;
2754
+ }
2883
2755
  if (t === "--max-concurrency") {
2884
2756
  flags.maxConcurrency = parseInt(raw[++i], 10) || 5;
2885
2757
  continue;
@@ -2969,8 +2841,11 @@ async function actionsExecuteParallelCommand() {
2969
2841
  segErrors.push(`Connection key "${seg.connectionKey}" is not allowed`);
2970
2842
  }
2971
2843
  let actionDetails;
2844
+ let preflightCacheHit = false;
2972
2845
  try {
2973
- 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;
2974
2849
  } catch (err) {
2975
2850
  segErrors.push(`Action not found: ${err instanceof Error ? err.message : String(err)}`);
2976
2851
  }
@@ -3016,7 +2891,7 @@ async function actionsExecuteParallelCommand() {
3016
2891
  if (segErrors.length > 0) {
3017
2892
  errors.push({ segment: i + 1, label, messages: segErrors });
3018
2893
  } else if (actionDetails) {
3019
- prepared.push({ segment: seg, index: i, actionDetails, data, pathVariables, queryParams, headers });
2894
+ prepared.push({ segment: seg, index: i, actionDetails, preflightCacheHit, data, pathVariables, queryParams, headers });
3020
2895
  }
3021
2896
  }
3022
2897
  if (errors.length > 0) {
@@ -3054,7 +2929,8 @@ async function actionsExecuteParallelCommand() {
3054
2929
  durationMs: Date.now() - start,
3055
2930
  mock: true,
3056
2931
  request: { method: action.actionDetails.method, url: action.actionDetails.path },
3057
- response: mockResponse
2932
+ response: mockResponse,
2933
+ _preflight: { cache: action.preflightCacheHit ? "hit" : "miss" }
3058
2934
  };
3059
2935
  }
3060
2936
  const result = await api.executePassthroughRequest({
@@ -3081,7 +2957,8 @@ async function actionsExecuteParallelCommand() {
3081
2957
  url: result.requestConfig.url,
3082
2958
  ...flags.dryRun ? { headers: result.requestConfig.headers, data: result.requestConfig.data } : {}
3083
2959
  },
3084
- response: flags.dryRun ? void 0 : result.responseData
2960
+ response: flags.dryRun ? void 0 : result.responseData,
2961
+ _preflight: { cache: action.preflightCacheHit ? "hit" : "miss" }
3085
2962
  };
3086
2963
  })
3087
2964
  );
@@ -3162,8 +3039,8 @@ function colorMethod(method) {
3162
3039
  import pc7 from "picocolors";
3163
3040
 
3164
3041
  // src/lib/flow-validator.ts
3165
- import fs5 from "fs";
3166
- import path5 from "path";
3042
+ import fs4 from "fs";
3043
+ import path4 from "path";
3167
3044
  import { spawnSync } from "child_process";
3168
3045
  function validateFlowSchema(flow2) {
3169
3046
  const errors = [];
@@ -3228,32 +3105,32 @@ function validateStepsArray(steps, pathPrefix, errors) {
3228
3105
  const validTypes = FLOW_SCHEMA.stepTypes.map((st) => st.type);
3229
3106
  for (let i = 0; i < steps.length; i++) {
3230
3107
  const step = steps[i];
3231
- const path13 = `${pathPrefix}[${i}]`;
3108
+ const path12 = `${pathPrefix}[${i}]`;
3232
3109
  if (!step || typeof step !== "object" || Array.isArray(step)) {
3233
- errors.push({ path: path13, message: "Step must be an object" });
3110
+ errors.push({ path: path12, message: "Step must be an object" });
3234
3111
  continue;
3235
3112
  }
3236
3113
  const s = step;
3237
3114
  if (!s.id || typeof s.id !== "string") {
3238
- 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"' });
3239
3116
  }
3240
3117
  if (!s.name || typeof s.name !== "string") {
3241
- 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"' });
3242
3119
  }
3243
3120
  if (!s.type || !validTypes.includes(s.type)) {
3244
- 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(", ")}` });
3245
3122
  continue;
3246
3123
  }
3247
3124
  if (s.requires !== void 0) {
3248
3125
  if (!Array.isArray(s.requires)) {
3249
- 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"])' });
3250
3127
  } else {
3251
3128
  for (let r = 0; r < s.requires.length; r++) {
3252
3129
  const sel = s.requires[r];
3253
3130
  if (typeof sel !== "string") {
3254
- 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' });
3255
3132
  } else if (!sel.startsWith("$.")) {
3256
- 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")` });
3257
3134
  }
3258
3135
  }
3259
3136
  }
@@ -3261,7 +3138,7 @@ function validateStepsArray(steps, pathPrefix, errors) {
3261
3138
  if (s.onError && typeof s.onError === "object") {
3262
3139
  const oe = s.onError;
3263
3140
  if (!FLOW_SCHEMA.errorStrategies.includes(oe.strategy)) {
3264
- 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(", ")}` });
3265
3142
  }
3266
3143
  }
3267
3144
  const descriptor = getStepTypeDescriptor(s.type);
@@ -3271,14 +3148,14 @@ function validateStepsArray(steps, pathPrefix, errors) {
3271
3148
  if (!configObj || typeof configObj !== "object") {
3272
3149
  const hint = detectFlatConfigHint(s, descriptor);
3273
3150
  errors.push({
3274
- path: `${path13}.${configKey}`,
3151
+ path: `${path12}.${configKey}`,
3275
3152
  message: `${capitalize(descriptor.type)} step must have a "${configKey}" config object${hint}`
3276
3153
  });
3277
3154
  continue;
3278
3155
  }
3279
3156
  const config2 = configObj;
3280
3157
  for (const [fieldName, fd] of Object.entries(descriptor.fields)) {
3281
- const fieldPath = `${path13}.${configKey}.${fieldName}`;
3158
+ const fieldPath = `${path12}.${configKey}.${fieldName}`;
3282
3159
  const value = config2[fieldName];
3283
3160
  if (fd.required && (value === void 0 || value === null || value === "")) {
3284
3161
  errors.push({ path: fieldPath, message: `${capitalize(descriptor.type)} must have ${fd.type === "string" ? "a string" : fd.type === "array" ? "a" : "a"} "${fieldName}"` });
@@ -3311,30 +3188,30 @@ function validateStepsArray(steps, pathPrefix, errors) {
3311
3188
  }
3312
3189
  }
3313
3190
  if (descriptor.type === "action") {
3314
- validateConnectionForm(config2, `${path13}.${configKey}`, errors);
3191
+ validateConnectionForm(config2, `${path12}.${configKey}`, errors);
3315
3192
  }
3316
3193
  if (descriptor.type === "code") {
3317
3194
  const hasSource = typeof config2.source === "string" && config2.source.length > 0;
3318
3195
  const hasModule = typeof config2.module === "string" && config2.module.length > 0;
3319
3196
  if (!hasSource && !hasModule) {
3320
- 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)' });
3321
3198
  } else if (hasSource && hasModule) {
3322
- 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' });
3323
3200
  }
3324
3201
  if (hasModule) {
3325
3202
  const m = config2.module;
3326
3203
  if (m.startsWith("/") || /^[a-zA-Z]:[\\/]/.test(m)) {
3327
- 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)" });
3328
3205
  } else if (m.split(/[\\/]/).includes("..")) {
3329
- 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 ("..")' });
3330
3207
  } else if (!m.endsWith(".mjs")) {
3331
- 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" });
3332
3209
  }
3333
3210
  }
3334
3211
  if (hasSource) {
3335
3212
  const syntaxError = checkCodeSourceSyntax(config2.source);
3336
3213
  if (syntaxError) {
3337
- 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}` });
3338
3215
  }
3339
3216
  }
3340
3217
  }
@@ -3406,16 +3283,16 @@ function validateStepIds(flow2) {
3406
3283
  function collectIds(steps, pathPrefix) {
3407
3284
  for (let i = 0; i < steps.length; i++) {
3408
3285
  const step = steps[i];
3409
- const path13 = `${pathPrefix}[${i}]`;
3286
+ const path12 = `${pathPrefix}[${i}]`;
3410
3287
  if (seen.has(step.id)) {
3411
- errors.push({ path: `${path13}.id`, message: `Duplicate step ID: "${step.id}"` });
3288
+ errors.push({ path: `${path12}.id`, message: `Duplicate step ID: "${step.id}"` });
3412
3289
  } else {
3413
3290
  seen.add(step.id);
3414
3291
  }
3415
3292
  for (const { configKey, fieldName } of nestedKeys) {
3416
3293
  const config2 = step[configKey];
3417
3294
  if (config2 && Array.isArray(config2[fieldName])) {
3418
- collectIds(config2[fieldName], `${path13}.${configKey}.${fieldName}`);
3295
+ collectIds(config2[fieldName], `${path12}.${configKey}.${fieldName}`);
3419
3296
  }
3420
3297
  }
3421
3298
  }
@@ -3463,7 +3340,7 @@ function validateSelectorReferences(flow2) {
3463
3340
  }
3464
3341
  return selectors;
3465
3342
  }
3466
- function checkSelectors(selectors, path13, precedingStepIds) {
3343
+ function checkSelectors(selectors, path12, precedingStepIds) {
3467
3344
  for (const selector of selectors) {
3468
3345
  const parts = selector.split(".");
3469
3346
  if (parts.length < 3) continue;
@@ -3471,15 +3348,15 @@ function validateSelectorReferences(flow2) {
3471
3348
  if (root === "input") {
3472
3349
  const inputName = parts[2];
3473
3350
  if (!inputNames.has(inputName)) {
3474
- errors.push({ path: path13, message: `Selector "${selector}" references undefined input "${inputName}"` });
3351
+ errors.push({ path: path12, message: `Selector "${selector}" references undefined input "${inputName}"` });
3475
3352
  }
3476
3353
  } else if (root === "steps") {
3477
3354
  const stepId = parts[2].replace(/[\[\]]/g, "").split(/[\[\]]/)[0];
3478
3355
  if (!allStepIds.has(stepId)) {
3479
- errors.push({ path: path13, message: `Selector "${selector}" references undefined step "${stepId}"` });
3356
+ errors.push({ path: path12, message: `Selector "${selector}" references undefined step "${stepId}"` });
3480
3357
  } else if (precedingStepIds && !precedingStepIds.has(stepId)) {
3481
3358
  errors.push({
3482
- path: path13,
3359
+ path: path12,
3483
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.`
3484
3361
  });
3485
3362
  }
@@ -3487,20 +3364,20 @@ function validateSelectorReferences(flow2) {
3487
3364
  }
3488
3365
  }
3489
3366
  const EXPRESSION_FIELDS = /* @__PURE__ */ new Set(["condition.expression", "while.condition"]);
3490
- function checkOperatorsInSelectorField(value, path13) {
3367
+ function checkOperatorsInSelectorField(value, path12) {
3491
3368
  if (typeof value === "string" && value.startsWith("$.")) {
3492
3369
  if (value.includes("||")) {
3493
- 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.` });
3494
3371
  } else if (value.includes("&&")) {
3495
- 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.` });
3496
3373
  }
3497
3374
  } else if (value && typeof value === "object" && !Array.isArray(value)) {
3498
3375
  for (const [k, v] of Object.entries(value)) {
3499
- checkOperatorsInSelectorField(v, `${path13}.${k}`);
3376
+ checkOperatorsInSelectorField(v, `${path12}.${k}`);
3500
3377
  }
3501
3378
  } else if (Array.isArray(value)) {
3502
3379
  for (let i = 0; i < value.length; i++) {
3503
- checkOperatorsInSelectorField(value[i], `${path13}[${i}]`);
3380
+ checkOperatorsInSelectorField(value[i], `${path12}[${i}]`);
3504
3381
  }
3505
3382
  }
3506
3383
  }
@@ -3568,10 +3445,10 @@ var VALID_OUTPUT_SCHEMA_TYPES = /* @__PURE__ */ new Set(["string", "number", "bo
3568
3445
  function isOutputSchemaObject(v) {
3569
3446
  return !!v && typeof v === "object" && !Array.isArray(v);
3570
3447
  }
3571
- function walkOutputSchema(schema, path13) {
3448
+ function walkOutputSchema(schema, path12) {
3572
3449
  let current = schema;
3573
- for (let i = 0; i < path13.length; i++) {
3574
- const seg = path13[i];
3450
+ for (let i = 0; i < path12.length; i++) {
3451
+ const seg = path12[i];
3575
3452
  if (typeof current === "string") {
3576
3453
  return current === "unknown" || current === "object" || current === "array" ? "opaque" : "opaque";
3577
3454
  }
@@ -3722,8 +3599,8 @@ function validateCodeModules(flow2, rootDir) {
3722
3599
  const stepPath = `${pathPrefix}[${i}]`;
3723
3600
  if (step.type === "code" && step.code?.module) {
3724
3601
  const m = step.code.module;
3725
- const abs = path5.resolve(rootDir, m);
3726
- if (!fs5.existsSync(abs)) {
3602
+ const abs = path4.resolve(rootDir, m);
3603
+ if (!fs4.existsSync(abs)) {
3727
3604
  errors.push({
3728
3605
  path: `${stepPath}.code.module`,
3729
3606
  message: `Code module "${m}" not found at ${abs}`
@@ -3752,8 +3629,8 @@ function validateCodeModules(flow2, rootDir) {
3752
3629
  }
3753
3630
 
3754
3631
  // src/commands/flow.ts
3755
- import fs6 from "fs";
3756
- import path6 from "path";
3632
+ import fs5 from "fs";
3633
+ import path5 from "path";
3757
3634
  function getConfig2() {
3758
3635
  const apiKey = getApiKey();
3759
3636
  if (!apiKey) {
@@ -3811,7 +3688,7 @@ async function flowCreateCommand(key, options) {
3811
3688
  if (raw.startsWith("@")) {
3812
3689
  const filePath = raw.slice(1);
3813
3690
  try {
3814
- raw = fs6.readFileSync(filePath, "utf-8");
3691
+ raw = fs5.readFileSync(filePath, "utf-8");
3815
3692
  } catch (err) {
3816
3693
  error(`Cannot read file "${filePath}": ${err.message}`);
3817
3694
  }
@@ -4041,9 +3918,9 @@ async function flowValidateCommand(keyOrPath) {
4041
3918
  rootDir = loaded.rootDir;
4042
3919
  } catch {
4043
3920
  const flowPath = resolveFlowPath(keyOrPath);
4044
- const content = fs6.readFileSync(flowPath, "utf-8");
3921
+ const content = fs5.readFileSync(flowPath, "utf-8");
4045
3922
  flowData = JSON.parse(content);
4046
- rootDir = path6.dirname(flowPath);
3923
+ rootDir = path5.dirname(flowPath);
4047
3924
  }
4048
3925
  } catch (err) {
4049
3926
  spinner5.stop("Validation failed");
@@ -4866,11 +4743,11 @@ function handleId(response, config2, records) {
4866
4743
  }
4867
4744
 
4868
4745
  // src/lib/memory/sync/state.ts
4869
- import fs7 from "fs";
4870
- import path7 from "path";
4871
- var SYNC_DIR = path7.join(".one", "sync");
4872
- var STATE_DIR = path7.join(SYNC_DIR, "state");
4873
- 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");
4874
4751
  var legacyMigrationDone = false;
4875
4752
  function rowToState(row) {
4876
4753
  return {
@@ -4898,9 +4775,9 @@ function stateToRow(platform, model, state, lastError) {
4898
4775
  async function migrateLegacyOnce() {
4899
4776
  if (legacyMigrationDone) return;
4900
4777
  legacyMigrationDone = true;
4901
- if (fs7.existsSync(LEGACY_SINGLE_FILE)) {
4778
+ if (fs6.existsSync(LEGACY_SINGLE_FILE)) {
4902
4779
  try {
4903
- const raw = fs7.readFileSync(LEGACY_SINGLE_FILE, "utf-8");
4780
+ const raw = fs6.readFileSync(LEGACY_SINGLE_FILE, "utf-8");
4904
4781
  const legacy = JSON.parse(raw);
4905
4782
  const backend = await getBackend();
4906
4783
  for (const [platform, models] of Object.entries(legacy)) {
@@ -4910,32 +4787,32 @@ async function migrateLegacyOnce() {
4910
4787
  await backend.setSyncState(stateToRow(platform, model, modelState));
4911
4788
  }
4912
4789
  }
4913
- fs7.unlinkSync(LEGACY_SINGLE_FILE);
4790
+ fs6.unlinkSync(LEGACY_SINGLE_FILE);
4914
4791
  } catch {
4915
4792
  try {
4916
- fs7.unlinkSync(LEGACY_SINGLE_FILE);
4793
+ fs6.unlinkSync(LEGACY_SINGLE_FILE);
4917
4794
  } catch {
4918
4795
  }
4919
4796
  }
4920
4797
  }
4921
- if (fs7.existsSync(STATE_DIR)) {
4798
+ if (fs6.existsSync(STATE_DIR)) {
4922
4799
  try {
4923
4800
  const backend = await getBackend();
4924
- const platforms = fs7.readdirSync(STATE_DIR);
4801
+ const platforms = fs6.readdirSync(STATE_DIR);
4925
4802
  for (const platform of platforms) {
4926
- const platformDir = path7.join(STATE_DIR, platform);
4803
+ const platformDir = path6.join(STATE_DIR, platform);
4927
4804
  let entries;
4928
4805
  try {
4929
- entries = fs7.readdirSync(platformDir);
4806
+ entries = fs6.readdirSync(platformDir);
4930
4807
  } catch {
4931
4808
  continue;
4932
4809
  }
4933
4810
  for (const entry of entries) {
4934
4811
  if (!entry.endsWith(".json")) continue;
4935
4812
  const model = entry.slice(0, -".json".length);
4936
- const filePath = path7.join(platformDir, entry);
4813
+ const filePath = path6.join(platformDir, entry);
4937
4814
  try {
4938
- const raw = fs7.readFileSync(filePath, "utf-8");
4815
+ const raw = fs6.readFileSync(filePath, "utf-8");
4939
4816
  const modelState = JSON.parse(raw);
4940
4817
  const existing = await backend.getSyncState(platform, model);
4941
4818
  if (!existing) {
@@ -4945,7 +4822,7 @@ async function migrateLegacyOnce() {
4945
4822
  }
4946
4823
  }
4947
4824
  }
4948
- fs7.rmSync(STATE_DIR, { recursive: true, force: true });
4825
+ fs6.rmSync(STATE_DIR, { recursive: true, force: true });
4949
4826
  } catch {
4950
4827
  }
4951
4828
  }
@@ -4989,12 +4866,12 @@ async function removeModelState(platform, model) {
4989
4866
  }
4990
4867
 
4991
4868
  // src/lib/memory/sync/lock.ts
4992
- import fs8 from "fs";
4993
- import path8 from "path";
4994
- 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");
4995
4872
  var STALE_MS = 30 * 60 * 1e3;
4996
4873
  function lockPath(platform, model) {
4997
- return path8.join(LOCK_DIR_REL, `${platform}_${model}`);
4874
+ return path7.join(LOCK_DIR_REL, `${platform}_${model}`);
4998
4875
  }
4999
4876
  function isProcessAlive(pid) {
5000
4877
  try {
@@ -5011,15 +4888,15 @@ var SyncLockError = class extends Error {
5011
4888
  }
5012
4889
  };
5013
4890
  function acquireSyncLock(platform, model) {
5014
- fs8.mkdirSync(LOCK_DIR_REL, { recursive: true });
4891
+ fs7.mkdirSync(LOCK_DIR_REL, { recursive: true });
5015
4892
  const dir = lockPath(platform, model);
5016
- const pidFile = path8.join(dir, "pid");
4893
+ const pidFile = path7.join(dir, "pid");
5017
4894
  try {
5018
- fs8.mkdirSync(dir);
4895
+ fs7.mkdirSync(dir);
5019
4896
  } catch (err) {
5020
4897
  const stat = (() => {
5021
4898
  try {
5022
- return fs8.statSync(dir);
4899
+ return fs7.statSync(dir);
5023
4900
  } catch {
5024
4901
  return null;
5025
4902
  }
@@ -5028,7 +4905,7 @@ function acquireSyncLock(platform, model) {
5028
4905
  const age = Date.now() - stat.mtimeMs;
5029
4906
  let ownerPid = null;
5030
4907
  try {
5031
- const raw = fs8.readFileSync(pidFile, "utf-8");
4908
+ const raw = fs7.readFileSync(pidFile, "utf-8");
5032
4909
  const parsed = parseInt(raw.trim(), 10);
5033
4910
  if (!isNaN(parsed)) ownerPid = parsed;
5034
4911
  } catch {
@@ -5037,8 +4914,8 @@ function acquireSyncLock(platform, model) {
5037
4914
  const veryOld = age > STALE_MS;
5038
4915
  if (ownerDead || veryOld) {
5039
4916
  try {
5040
- fs8.rmSync(dir, { recursive: true, force: true });
5041
- fs8.mkdirSync(dir);
4917
+ fs7.rmSync(dir, { recursive: true, force: true });
4918
+ fs7.mkdirSync(dir);
5042
4919
  } catch {
5043
4920
  throw new SyncLockError(
5044
4921
  `Could not take over stale lock at ${dir}. Remove it manually if no sync is running.`
@@ -5055,13 +4932,13 @@ function acquireSyncLock(platform, model) {
5055
4932
  }
5056
4933
  }
5057
4934
  try {
5058
- fs8.writeFileSync(pidFile, String(process.pid));
4935
+ fs7.writeFileSync(pidFile, String(process.pid));
5059
4936
  } catch {
5060
4937
  }
5061
4938
  return {
5062
4939
  release() {
5063
4940
  try {
5064
- fs8.rmSync(dir, { recursive: true, force: true });
4941
+ fs7.rmSync(dir, { recursive: true, force: true });
5065
4942
  } catch {
5066
4943
  }
5067
4944
  }
@@ -5070,9 +4947,9 @@ function acquireSyncLock(platform, model) {
5070
4947
 
5071
4948
  // src/lib/memory/sync/hooks.ts
5072
4949
  import { spawn as spawn2 } from "child_process";
5073
- import fs9 from "fs";
5074
- import path9 from "path";
5075
- 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");
5076
4953
  function classifyRecords(db, model, records, idField, tableExists2) {
5077
4954
  if (!tableExists2 || records.length === 0) {
5078
4955
  return { inserts: records, updates: [] };
@@ -5118,10 +4995,10 @@ async function fireHooks(hookCommand, events) {
5118
4995
  function appendEventLog(events) {
5119
4996
  if (events.length === 0) return;
5120
4997
  const { platform, model } = events[0];
5121
- fs9.mkdirSync(EVENTS_DIR, { recursive: true });
5122
- 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`);
5123
5000
  const lines = events.map((e) => JSON.stringify(e)).join("\n") + "\n";
5124
- fs9.appendFileSync(logPath, lines);
5001
+ fs8.appendFileSync(logPath, lines);
5125
5002
  }
5126
5003
  function runShellHook(command, events) {
5127
5004
  return new Promise((resolve) => {
@@ -5144,10 +5021,10 @@ function runShellHook(command, events) {
5144
5021
  }
5145
5022
 
5146
5023
  // src/lib/memory/sync/mem-writer.ts
5147
- function resolveWildcardPath(root, path13) {
5148
- const segments = path13.split("[]");
5024
+ function resolveWildcardPath(root, path12) {
5025
+ const segments = path12.split("[]");
5149
5026
  if (segments.length === 1) {
5150
- return [getByDotPath(root, path13)];
5027
+ return [getByDotPath(root, path12)];
5151
5028
  }
5152
5029
  const recurse = (value, idx) => {
5153
5030
  if (value === null || value === void 0) return [];
@@ -5173,8 +5050,8 @@ function resolveWildcardPath(root, path13) {
5173
5050
  function extractSearchableFromPaths(record, paths) {
5174
5051
  const parts = [];
5175
5052
  const perPath = [];
5176
- for (const path13 of paths) {
5177
- const values = resolveWildcardPath(record, path13);
5053
+ for (const path12 of paths) {
5054
+ const values = resolveWildcardPath(record, path12);
5178
5055
  const collected = [];
5179
5056
  const absorb = (v) => {
5180
5057
  if (v === null || v === void 0) return;
@@ -5190,9 +5067,9 @@ function extractSearchableFromPaths(record, paths) {
5190
5067
  for (const v of values) absorb(v);
5191
5068
  if (collected.length > 0) {
5192
5069
  parts.push(...collected);
5193
- 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) });
5194
5071
  } else {
5195
- perPath.push({ path: path13, found: false, sample: "" });
5072
+ perPath.push({ path: path12, found: false, sample: "" });
5196
5073
  }
5197
5074
  }
5198
5075
  const text5 = parts.join(" ").replace(/\s+/g, " ").trim();
@@ -5371,8 +5248,8 @@ function sleep(ms) {
5371
5248
  return new Promise((resolve) => setTimeout(resolve, ms));
5372
5249
  }
5373
5250
  function interpolate(template, record) {
5374
- return template.replace(/\{?\{(\w+(?:\.\w+)*)\}\}?/g, (_, path13) => {
5375
- const parts = path13.split(".");
5251
+ return template.replace(/\{?\{(\w+(?:\.\w+)*)\}\}?/g, (_, path12) => {
5252
+ const parts = path12.split(".");
5376
5253
  let value = record;
5377
5254
  for (const part of parts) {
5378
5255
  if (typeof value !== "object" || value === null) return "";
@@ -5400,8 +5277,8 @@ function deepMerge(target, source) {
5400
5277
  }
5401
5278
  return result;
5402
5279
  }
5403
- function getByDotPath2(obj, path13) {
5404
- const parts = path13.split(".");
5280
+ function getByDotPath2(obj, path12) {
5281
+ const parts = path12.split(".");
5405
5282
  let current = obj;
5406
5283
  for (const part of parts) {
5407
5284
  if (current === null || current === void 0 || typeof current !== "object") return void 0;
@@ -5410,8 +5287,8 @@ function getByDotPath2(obj, path13) {
5410
5287
  return current;
5411
5288
  }
5412
5289
  function stripExcludedFields(obj, paths) {
5413
- for (const path13 of paths) {
5414
- stripOnePath(obj, path13.replace(/\[\]/g, ".*").split("."));
5290
+ for (const path12 of paths) {
5291
+ stripOnePath(obj, path12.replace(/\[\]/g, ".*").split("."));
5415
5292
  }
5416
5293
  }
5417
5294
  function stripOnePath(obj, parts) {
@@ -5480,7 +5357,7 @@ async function enrichPhase(api, db, config2, model, idField, connectionKey, plat
5480
5357
  }
5481
5358
  let detailAction;
5482
5359
  try {
5483
- detailAction = await api.getActionDetails(config2.actionId);
5360
+ detailAction = (await resolveActionDetails(api, config2.actionId)).details;
5484
5361
  } catch (err) {
5485
5362
  throw new Error(
5486
5363
  `Enrich: could not load action ${config2.actionId}: ${err instanceof Error ? err.message : String(err)}`
@@ -5741,8 +5618,8 @@ function sleep2(ms) {
5741
5618
  return new Promise((resolve) => setTimeout(resolve, ms));
5742
5619
  }
5743
5620
  function stripFields(record, paths) {
5744
- for (const path13 of paths) {
5745
- stripOnePath2(record, path13.split("."));
5621
+ for (const path12 of paths) {
5622
+ stripOnePath2(record, path12.split("."));
5746
5623
  }
5747
5624
  }
5748
5625
  function stripOnePath2(obj, parts) {
@@ -5832,7 +5709,7 @@ async function syncModel(api, profile, options) {
5832
5709
  updateModelState(platform, model, { status: "failed", pagesProcessed, lastCursor }),
5833
5710
  (async () => {
5834
5711
  try {
5835
- const { getBackend: getBackend2 } = await import("./runtime-RVXAPQAZ.js");
5712
+ const { getBackend: getBackend2 } = await import("./runtime-3NDWRLXL.js");
5836
5713
  const backend = await getBackend2();
5837
5714
  await Promise.race([
5838
5715
  backend.close(),
@@ -5909,7 +5786,7 @@ async function syncModel(api, profile, options) {
5909
5786
  queryParams[param] = dateValue;
5910
5787
  }
5911
5788
  }
5912
- const actionDetails = await api.getActionDetails(profile.actionId);
5789
+ const { details: actionDetails } = await resolveActionDetails(api, profile.actionId);
5913
5790
  if (actionDetails.tags?.includes("custom")) {
5914
5791
  throw new Error(
5915
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.`
@@ -6187,7 +6064,7 @@ async function syncModel(api, profile, options) {
6187
6064
  db.exec(`DROP TABLE IF EXISTS _seen_ids`);
6188
6065
  }
6189
6066
  if (options.toMemory !== false) {
6190
- const backend = await (await import("./runtime-RVXAPQAZ.js")).getBackend();
6067
+ const backend = await (await import("./runtime-3NDWRLXL.js")).getBackend();
6191
6068
  const type = `${platform}/${model}`;
6192
6069
  const existing = await backend.listKeysByType(type);
6193
6070
  const sourcePrefix = `${type}:`;
@@ -6267,7 +6144,7 @@ async function syncModel(api, profile, options) {
6267
6144
  let statusCounts;
6268
6145
  if (options.toMemory !== false) {
6269
6146
  try {
6270
- const backend = await (await import("./runtime-RVXAPQAZ.js")).getBackend();
6147
+ const backend = await (await import("./runtime-3NDWRLXL.js")).getBackend();
6271
6148
  const typeName = `${platform}/${model}`;
6272
6149
  const [active, archived] = await Promise.all([
6273
6150
  backend.count(typeName, { status: "active" }),
@@ -6763,20 +6640,20 @@ function inferProfileFromKnowledge(knowledge, modelName, platform) {
6763
6640
 
6764
6641
  // src/lib/memory/sync/schedule.ts
6765
6642
  import { spawnSync as spawnSync2 } from "child_process";
6766
- import fs11 from "fs";
6767
- import os6 from "os";
6768
- import path11 from "path";
6769
-
6770
- // src/lib/memory/sync/schedule-registry.ts
6771
6643
  import fs10 from "fs";
6772
6644
  import os5 from "os";
6773
6645
  import path10 from "path";
6774
- var REGISTRY_DIR = path10.join(os5.homedir(), ".one", "sync");
6775
- 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");
6776
6653
  function readRaw() {
6777
6654
  try {
6778
- if (!fs10.existsSync(REGISTRY_FILE)) return { schedules: [] };
6779
- 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");
6780
6657
  const parsed = JSON.parse(raw);
6781
6658
  if (!parsed || !Array.isArray(parsed.schedules)) return { schedules: [] };
6782
6659
  return parsed;
@@ -6785,13 +6662,13 @@ function readRaw() {
6785
6662
  }
6786
6663
  }
6787
6664
  function writeRaw(file) {
6788
- fs10.mkdirSync(REGISTRY_DIR, { recursive: true });
6665
+ fs9.mkdirSync(REGISTRY_DIR, { recursive: true });
6789
6666
  const tmp = REGISTRY_FILE + ".tmp";
6790
- fs10.writeFileSync(tmp, JSON.stringify(file, null, 2));
6791
- fs10.renameSync(tmp, REGISTRY_FILE);
6667
+ fs9.writeFileSync(tmp, JSON.stringify(file, null, 2));
6668
+ fs9.renameSync(tmp, REGISTRY_FILE);
6792
6669
  }
6793
6670
  function makeScheduleId(platform, cwd) {
6794
- 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();
6795
6672
  return `${platform}-${slug}`;
6796
6673
  }
6797
6674
  function listRegistered() {
@@ -6825,7 +6702,7 @@ function removeRegistered(id) {
6825
6702
 
6826
6703
  // src/lib/memory/sync/schedule.ts
6827
6704
  var MARKER = "# one-sync";
6828
- var LOG_DIR_REL = path11.join(".one", "sync", "logs");
6705
+ var LOG_DIR_REL = path10.join(".one", "sync", "logs");
6829
6706
  function durationToCron(every) {
6830
6707
  const match = every.match(/^(\d+)([mhd])$/);
6831
6708
  if (!match) return null;
@@ -6858,13 +6735,13 @@ function cronExprToDuration(expr) {
6858
6735
  return null;
6859
6736
  }
6860
6737
  function isWindows() {
6861
- return os6.platform() === "win32";
6738
+ return os5.platform() === "win32";
6862
6739
  }
6863
6740
  function resolveOneBinary() {
6864
6741
  try {
6865
6742
  const entry = process.argv[1];
6866
- if (entry && fs11.existsSync(entry)) {
6867
- return fs11.realpathSync(entry);
6743
+ if (entry && fs10.existsSync(entry)) {
6744
+ return fs10.realpathSync(entry);
6868
6745
  }
6869
6746
  } catch {
6870
6747
  }
@@ -6942,7 +6819,7 @@ function migrateLegacyCronEntries() {
6942
6819
  const modelsMatch = command.match(/--models\s+(\S+)/);
6943
6820
  const models = modelsMatch ? modelsMatch[1].split(",") : void 0;
6944
6821
  const logMatch = command.match(/>>\s+"([^"]+)"/);
6945
- 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`);
6946
6823
  const id = makeScheduleId(platform, cwd);
6947
6824
  if (registeredIds.has(id)) continue;
6948
6825
  upsertRegistered({
@@ -6976,9 +6853,9 @@ function addSchedule(opts) {
6976
6853
  const cwd = process.cwd();
6977
6854
  const id = makeScheduleId(opts.platform, cwd);
6978
6855
  const replaced = getRegistered(id) !== void 0;
6979
- const logDir = path11.join(cwd, LOG_DIR_REL);
6980
- fs11.mkdirSync(logDir, { recursive: true });
6981
- 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`);
6982
6859
  const entry = {
6983
6860
  id,
6984
6861
  platform: opts.platform,
@@ -7032,15 +6909,15 @@ function removeSchedule(idOrPlatform, options) {
7032
6909
  function scheduleStatus() {
7033
6910
  const entries = listSchedules();
7034
6911
  return entries.map((entry) => {
7035
- const logExists = fs11.existsSync(entry.logFile);
7036
- 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;
7037
6914
  let logTail = [];
7038
6915
  let lastRunAt = null;
7039
6916
  if (logExists) {
7040
6917
  try {
7041
- lastRunAt = fs11.statSync(entry.logFile).mtime.toISOString();
6918
+ lastRunAt = fs10.statSync(entry.logFile).mtime.toISOString();
7042
6919
  if (logSize > 0) {
7043
- const content = fs11.readFileSync(entry.logFile, "utf-8");
6920
+ const content = fs10.readFileSync(entry.logFile, "utf-8");
7044
6921
  logTail = content.trim().split("\n").slice(-10);
7045
6922
  }
7046
6923
  } catch {
@@ -7048,8 +6925,8 @@ function scheduleStatus() {
7048
6925
  }
7049
6926
  let drift = "ok";
7050
6927
  if (!entry.cronInstalled) drift = "missing-cron";
7051
- else if (!fs11.existsSync(entry.nodeBin)) drift = "stale-node-bin";
7052
- 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";
7053
6930
  return { entry, logExists, logSize, logTail, lastRunAt, drift };
7054
6931
  });
7055
6932
  }
@@ -7322,11 +7199,11 @@ function isNoise(s) {
7322
7199
  if (/^-?\d+(\.\d+)?([eE][-+]?\d+)?$/.test(s)) return true;
7323
7200
  return false;
7324
7201
  }
7325
- function recordSample(stats, path13, value, jsType, recordIndex, totalSamples) {
7326
- let s = stats.get(path13);
7202
+ function recordSample(stats, path12, value, jsType, recordIndex, totalSamples) {
7203
+ let s = stats.get(path12);
7327
7204
  if (!s) {
7328
7205
  s = {
7329
- path: path13,
7206
+ path: path12,
7330
7207
  total: totalSamples,
7331
7208
  recordIndices: /* @__PURE__ */ new Set(),
7332
7209
  lenSum: 0,
@@ -7335,7 +7212,7 @@ function recordSample(stats, path13, value, jsType, recordIndex, totalSamples) {
7335
7212
  primaryType: jsType,
7336
7213
  examples: []
7337
7214
  };
7338
- stats.set(path13, s);
7215
+ stats.set(path12, s);
7339
7216
  }
7340
7217
  s.recordIndices.add(recordIndex);
7341
7218
  s.lenSum += value.length;
@@ -7344,28 +7221,28 @@ function recordSample(stats, path13, value, jsType, recordIndex, totalSamples) {
7344
7221
  if (s.primaryType !== jsType) s.primaryType = "mixed";
7345
7222
  if (s.examples.length < 3 && value.length < 200) s.examples.push(value);
7346
7223
  }
7347
- function walkRecord(record, path13, stats, recordIndex, totalSamples) {
7224
+ function walkRecord(record, path12, stats, recordIndex, totalSamples) {
7348
7225
  if (record === null || record === void 0) return;
7349
7226
  if (typeof record === "string") {
7350
7227
  const trimmed = record.trim();
7351
- if (trimmed) recordSample(stats, path13, trimmed, "string", recordIndex, totalSamples);
7228
+ if (trimmed) recordSample(stats, path12, trimmed, "string", recordIndex, totalSamples);
7352
7229
  return;
7353
7230
  }
7354
7231
  if (typeof record === "number" || typeof record === "boolean") {
7355
7232
  const str = String(record);
7356
7233
  const kind = typeof record === "number" ? "number" : "boolean";
7357
- if (str) recordSample(stats, path13, str, kind, recordIndex, totalSamples);
7234
+ if (str) recordSample(stats, path12, str, kind, recordIndex, totalSamples);
7358
7235
  return;
7359
7236
  }
7360
7237
  if (Array.isArray(record)) {
7361
- const childPath = path13 ? `${path13}[]` : "[]";
7238
+ const childPath = path12 ? `${path12}[]` : "[]";
7362
7239
  for (const item of record) walkRecord(item, childPath, stats, recordIndex, totalSamples);
7363
7240
  return;
7364
7241
  }
7365
7242
  if (typeof record === "object") {
7366
7243
  for (const [key, value] of Object.entries(record)) {
7367
7244
  if (key.startsWith("_")) continue;
7368
- const childPath = path13 ? `${path13}.${key}` : key;
7245
+ const childPath = path12 ? `${path12}.${key}` : key;
7369
7246
  walkRecord(value, childPath, stats, recordIndex, totalSamples);
7370
7247
  }
7371
7248
  }
@@ -7574,8 +7451,8 @@ async function syncInitCommand(platform, model, options) {
7574
7451
  }
7575
7452
  if (actionId && !builtin) {
7576
7453
  try {
7577
- const knowledgeResp = await api.getActionKnowledge(actionId);
7578
- inferred = inferProfileFromKnowledge(knowledgeResp?.knowledge, model, platform);
7454
+ const { details } = await resolveActionDetails(api, actionId);
7455
+ inferred = inferProfileFromKnowledge(details.knowledge, model, platform);
7579
7456
  if (inferred.pagination) template.pagination = inferred.pagination;
7580
7457
  if (inferred.resultsPath) template.resultsPath = inferred.resultsPath;
7581
7458
  if (inferred.idField) template.idField = inferred.idField;
@@ -7771,7 +7648,7 @@ function buildSearchablePreview(profile, samples) {
7771
7648
  const first = samples[0];
7772
7649
  const paths = getSearchablePaths(profile);
7773
7650
  if (paths) {
7774
- 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: "" }));
7775
7652
  for (const record of samples) {
7776
7653
  const { paths: perPath } = extractSearchableFromPaths(record, paths);
7777
7654
  perPath.forEach((p10, i) => {
@@ -7900,7 +7777,7 @@ ${result.total} results`);
7900
7777
  }
7901
7778
  }
7902
7779
  async function syncSqlCommand(platformModel, sql) {
7903
- const { syncSqlCommand: runSyncSql } = await import("./sql-V44IVBHX.js");
7780
+ const { syncSqlCommand: runSyncSql } = await import("./sql-ZABEXIXW.js");
7904
7781
  await runSyncSql(platformModel, sql);
7905
7782
  }
7906
7783
  async function syncDeleteCommand(platformModel, options) {
@@ -7978,7 +7855,7 @@ async function syncDeleteCommand(platformModel, options) {
7978
7855
  async function maybeAutoMigrateLegacy(platform, models) {
7979
7856
  const dbSize = getDatabaseSize(platform);
7980
7857
  if (!dbSize || dbSize === "0 B") return;
7981
- const { getBackend: getBackend2 } = await import("./runtime-RVXAPQAZ.js");
7858
+ const { getBackend: getBackend2 } = await import("./runtime-3NDWRLXL.js");
7982
7859
  const backend = await getBackend2();
7983
7860
  let memoryHasData = false;
7984
7861
  for (const model of models) {
@@ -7994,7 +7871,7 @@ async function maybeAutoMigrateLegacy(platform, models) {
7994
7871
  ` detected legacy .one/sync/data/${platform}.db (${dbSize}) \u2014 auto-migrating into memory before sync.
7995
7872
  `
7996
7873
  );
7997
- const { memMigrateCommand: memMigrateCommand3 } = await import("./migrate-J2ZRDEFB.js");
7874
+ const { memMigrateCommand: memMigrateCommand3 } = await import("./migrate-VV3VOXWJ.js");
7998
7875
  await memMigrateCommand3({ platform, yes: true });
7999
7876
  return;
8000
7877
  }
@@ -8003,7 +7880,7 @@ async function maybeAutoMigrateLegacy(platform, models) {
8003
7880
  initialValue: true
8004
7881
  });
8005
7882
  if (p7.isCancel(shouldMigrate) || !shouldMigrate) return;
8006
- const { memMigrateCommand: memMigrateCommand2 } = await import("./migrate-J2ZRDEFB.js");
7883
+ const { memMigrateCommand: memMigrateCommand2 } = await import("./migrate-VV3VOXWJ.js");
8007
7884
  await memMigrateCommand2({ platform, yes: true });
8008
7885
  }
8009
7886
  async function syncSuggestSearchableCommand(platformModel, options = {}) {
@@ -8064,7 +7941,7 @@ async function syncSuggestSearchableCommand(platformModel, options = {}) {
8064
7941
  async function syncListCommand(platform) {
8065
7942
  const profiles = listProfiles(platform);
8066
7943
  const state = await readSyncState();
8067
- const { getBackend: getBackend2 } = await import("./runtime-RVXAPQAZ.js");
7944
+ const { getBackend: getBackend2 } = await import("./runtime-3NDWRLXL.js");
8068
7945
  const backend = await getBackend2();
8069
7946
  const syncs = await Promise.all(profiles.map(async (p10) => {
8070
7947
  const modelState = state[p10.platform]?.[p10.model];
@@ -8702,16 +8579,16 @@ function projectEmbeddingApiKey(cfg) {
8702
8579
  }
8703
8580
  function redactSecrets(cfg) {
8704
8581
  const copy = JSON.parse(JSON.stringify(cfg));
8705
- for (const path13 of SECRET_PATHS) {
8706
- const val = getPath(copy, path13);
8582
+ for (const path12 of SECRET_PATHS) {
8583
+ const val = getPath(copy, path12);
8707
8584
  if (typeof val === "string" && val.length > 0) {
8708
- 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)`);
8709
8586
  }
8710
8587
  }
8711
8588
  return copy;
8712
8589
  }
8713
- function getPath(obj, path13) {
8714
- const parts = path13.split(".");
8590
+ function getPath(obj, path12) {
8591
+ const parts = path12.split(".");
8715
8592
  let cur = obj;
8716
8593
  for (const part of parts) {
8717
8594
  if (cur == null || typeof cur !== "object") return void 0;
@@ -8719,8 +8596,8 @@ function getPath(obj, path13) {
8719
8596
  }
8720
8597
  return cur;
8721
8598
  }
8722
- function setPath(obj, path13, value) {
8723
- const parts = path13.split(".");
8599
+ function setPath(obj, path12, value) {
8600
+ const parts = path12.split(".");
8724
8601
  let cur = obj;
8725
8602
  for (let i = 0; i < parts.length - 1; i++) {
8726
8603
  const part = parts[i];
@@ -8730,8 +8607,8 @@ function setPath(obj, path13, value) {
8730
8607
  cur[parts[parts.length - 1]] = value;
8731
8608
  return obj;
8732
8609
  }
8733
- function unsetPath(obj, path13) {
8734
- const parts = path13.split(".");
8610
+ function unsetPath(obj, path12) {
8611
+ const parts = path12.split(".");
8735
8612
  let cur = obj;
8736
8613
  for (let i = 0; i < parts.length - 1; i++) {
8737
8614
  const part = parts[i];
@@ -8982,7 +8859,7 @@ async function memDoctorCommand() {
8982
8859
  }
8983
8860
  if (cfg.embedding.provider === "openai") {
8984
8861
  try {
8985
- const { embed: embed2 } = await import("./embedding-GZGDGIUA.js");
8862
+ const { embed: embed2 } = await import("./embedding-C3E4EAQ7.js");
8986
8863
  const result = await embed2("connectivity check");
8987
8864
  checks.push({
8988
8865
  name: "OpenAI embedding provider reachable",
@@ -9040,7 +8917,7 @@ ${pc10.dim(line)}`);
9040
8917
  }
9041
8918
 
9042
8919
  // src/commands/mem/export.ts
9043
- import fs12 from "fs";
8920
+ import fs11 from "fs";
9044
8921
  async function memExportCommand(outfile) {
9045
8922
  requireMemoryInit();
9046
8923
  const backend = await getBackend();
@@ -9073,14 +8950,14 @@ async function memExportCommand(outfile) {
9073
8950
  }
9074
8951
  return;
9075
8952
  }
9076
- fs12.writeFileSync(outfile, lines, "utf-8");
8953
+ fs11.writeFileSync(outfile, lines, "utf-8");
9077
8954
  okJson({ status: "ok", file: outfile, recordsWritten: records.length, storeTotal: stats.recordCount });
9078
8955
  }
9079
8956
  async function memImportCommand(file) {
9080
8957
  requireMemoryInit();
9081
- if (!fs12.existsSync(file)) error(`File not found: ${file}`);
8958
+ if (!fs11.existsSync(file)) error(`File not found: ${file}`);
9082
8959
  const backend = await getBackend();
9083
- const raw = fs12.readFileSync(file, "utf-8");
8960
+ const raw = fs11.readFileSync(file, "utf-8");
9084
8961
  const lines = raw.split("\n").filter((l) => l.trim().length > 0);
9085
8962
  let inserted = 0;
9086
8963
  let updated = 0;
@@ -9344,13 +9221,13 @@ async function cacheUpdateAllCommand() {
9344
9221
  for (const e of entries) {
9345
9222
  try {
9346
9223
  if (e.type === "knowledge") {
9347
- const result = await api.getActionKnowledgeWithMeta(e.entry.key);
9224
+ const result = await api.getActionDetailsWithMeta(e.entry.key);
9348
9225
  const newEntry = makeCacheEntry(e.entry.key, result.data, result.etag);
9349
- writeCache2(e.filePath, newEntry);
9226
+ writeCache(e.filePath, newEntry);
9350
9227
  updated++;
9351
9228
  } else {
9352
9229
  const refreshed = { ...e.entry, cachedAt: (/* @__PURE__ */ new Date()).toISOString() };
9353
- writeCache2(e.filePath, refreshed);
9230
+ writeCache(e.filePath, refreshed);
9354
9231
  updated++;
9355
9232
  }
9356
9233
  } catch (err) {
@@ -9436,6 +9313,7 @@ one --agent actions execute <platform> <actionId> <key> -d '{}' # Execute it
9436
9313
  - \`--mock\` \u2014 Return example response without making an API call (useful for building UI against a response shape)
9437
9314
  - \`--skip-validation\` \u2014 Skip input validation against the action schema
9438
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)
9439
9317
 
9440
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.
9441
9319
 
@@ -9561,6 +9439,9 @@ one --agent actions execute <platform> <actionId> <connectionKey> [options]
9561
9439
  - \`--mock\` \u2014 Return example response without making an API call
9562
9440
  - \`--skip-validation\` \u2014 Skip input validation against the action schema
9563
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.
9564
9445
 
9565
9446
  **Do NOT** pass path or query parameters in \`-d\`. Use the correct flags.
9566
9447
 
@@ -9575,13 +9456,13 @@ one --agent actions execute --parallel \\
9575
9456
  -- google-sheets append-row conn789 -d '{"values":["x"]}'
9576
9457
  \`\`\`
9577
9458
 
9578
- 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.
9579
9460
 
9580
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.
9581
9462
 
9582
- Agent-mode output:
9463
+ Agent-mode output (each result carries its own \`_preflight\` showing whether that action's details were served from cache):
9583
9464
  \`\`\`json
9584
- {"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"}}]}
9585
9466
  \`\`\`
9586
9467
 
9587
9468
  ## Input Validation
@@ -9714,7 +9595,7 @@ var GUIDE_CACHE = `# One Cache \u2014 Reference
9714
9595
 
9715
9596
  ## Overview
9716
9597
 
9717
- 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.
9718
9599
 
9719
9600
  Cache location: \`~/.one/cache/knowledge/\` and \`~/.one/cache/search/\`
9720
9601
 
@@ -9724,6 +9605,7 @@ Cache location: \`~/.one/cache/knowledge/\` and \`~/.one/cache/search/\`
9724
9605
  - **Subsequent calls (within TTL)**: serves from cache instantly, no API call
9725
9606
  - **After TTL expires**: makes a conditional request (ETag). If content unchanged, refreshes the cache timestamp. If changed, writes fresh data.
9726
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
9727
9609
 
9728
9610
  Default TTL: 3600 seconds (1 hour). Configure via \`ONE_CACHE_TTL\` env var or \`cacheTtl\` in \`~/.one/config.json\`.
9729
9611
 
@@ -9731,8 +9613,9 @@ Default TTL: 3600 seconds (1 hour). Configure via \`ONE_CACHE_TTL\` env var or \
9731
9613
 
9732
9614
  | Cached | Not Cached |
9733
9615
  |--------|-----------|
9734
- | \`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) |
9735
9617
  | \`actions search\` results | \`connection list\` (changes with add/remove) |
9618
+ | Action details used by execute / flow / sync preflight (method, path, schema) | |
9736
9619
 
9737
9620
  ## Agent Mode \`_cache\` Metadata
9738
9621
 
@@ -9763,8 +9646,13 @@ one --agent actions knowledge <platform> <actionId> --cache-status
9763
9646
 
9764
9647
  # Same for search
9765
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
9766
9652
  \`\`\`
9767
9653
 
9654
+ In \`--agent\` mode, execute responses include \`"_preflight": {"cache": "hit"|"miss"}\` showing whether the action details came from disk.
9655
+
9768
9656
  ## Cache Management Commands
9769
9657
 
9770
9658
  \`\`\`bash
@@ -10676,7 +10564,7 @@ function buildWorkflowIdeas(connections) {
10676
10564
  }
10677
10565
 
10678
10566
  // src/commands/logout.ts
10679
- import fs13 from "fs";
10567
+ import fs12 from "fs";
10680
10568
  import * as p9 from "@clack/prompts";
10681
10569
  function formatWhoami(config2, apiKey, pc13) {
10682
10570
  const whoami = config2.whoami;
@@ -10709,12 +10597,12 @@ async function logoutCommand() {
10709
10597
  const globalPath = getGlobalConfigPath();
10710
10598
  const projectPath = getProjectConfigPath();
10711
10599
  let cleared = false;
10712
- if (fs13.existsSync(projectPath)) {
10713
- fs13.unlinkSync(projectPath);
10600
+ if (fs12.existsSync(projectPath)) {
10601
+ fs12.unlinkSync(projectPath);
10714
10602
  cleared = true;
10715
10603
  }
10716
- if (fs13.existsSync(globalPath)) {
10717
- fs13.unlinkSync(globalPath);
10604
+ if (fs12.existsSync(globalPath)) {
10605
+ fs12.unlinkSync(globalPath);
10718
10606
  cleared = true;
10719
10607
  }
10720
10608
  json({ status: cleared ? "logged_out" : "not_logged_in", message: cleared ? "Credentials cleared." : "No config found." });
@@ -10783,11 +10671,11 @@ async function logoutCommand() {
10783
10671
  }
10784
10672
  if (targetScope === "project" || targetScope === "both") {
10785
10673
  const projectPath = getProjectConfigPath();
10786
- if (fs13.existsSync(projectPath)) fs13.unlinkSync(projectPath);
10674
+ if (fs12.existsSync(projectPath)) fs12.unlinkSync(projectPath);
10787
10675
  }
10788
10676
  if (targetScope === "global" || targetScope === "both") {
10789
10677
  const globalPath = getGlobalConfigPath();
10790
- if (fs13.existsSync(globalPath)) fs13.unlinkSync(globalPath);
10678
+ if (fs12.existsSync(globalPath)) fs12.unlinkSync(globalPath);
10791
10679
  }
10792
10680
  p9.log.success("Credentials cleared.");
10793
10681
  p9.log.info("Your API key is still active. Manage keys at app.withone.ai/settings");
@@ -11005,8 +10893,8 @@ config.command("reset").description("Remove the project config for the current d
11005
10893
  return;
11006
10894
  }
11007
10895
  }
11008
- const fs15 = await import("fs");
11009
- fs15.unlinkSync(globalPath);
10896
+ const fs14 = await import("fs");
10897
+ fs14.unlinkSync(globalPath);
11010
10898
  if (isAgentMode()) {
11011
10899
  json({ deleted: true, scope: "global" });
11012
10900
  } else {
@@ -11023,15 +10911,15 @@ config.command("reset").description("Remove the project config for the current d
11023
10911
  }
11024
10912
  return;
11025
10913
  }
11026
- const fs14 = await import("fs");
11027
- const configContent = fs14.readFileSync(resolved.path, "utf-8");
11028
- fs14.unlinkSync(resolved.path);
10914
+ const fs13 = await import("fs");
10915
+ const configContent = fs13.readFileSync(resolved.path, "utf-8");
10916
+ fs13.unlinkSync(resolved.path);
11029
10917
  const next = resolveConfig();
11030
- fs14.mkdirSync(path12.dirname(resolved.path), { recursive: true });
11031
- fs14.writeFileSync(resolved.path, configContent);
10918
+ fs13.mkdirSync(path11.dirname(resolved.path), { recursive: true });
10919
+ fs13.writeFileSync(resolved.path, configContent);
11032
10920
  let fallbackLabel;
11033
10921
  if (next.scope === "project") {
11034
- fallbackLabel = `parent project config (${path12.basename(next.projectRoot)})`;
10922
+ fallbackLabel = `parent project config (${path11.basename(next.projectRoot)})`;
11035
10923
  } else if (next.scope === "global") {
11036
10924
  fallbackLabel = "global config";
11037
10925
  } else {
@@ -11040,7 +10928,7 @@ config.command("reset").description("Remove the project config for the current d
11040
10928
  if (!isAgentMode()) {
11041
10929
  const p10 = await import("@clack/prompts");
11042
10930
  const confirmed = await p10.confirm({
11043
- 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}.`,
11044
10932
  initialValue: false
11045
10933
  });
11046
10934
  if (p10.isCancel(confirmed) || !confirmed) {
@@ -11048,9 +10936,9 @@ config.command("reset").description("Remove the project config for the current d
11048
10936
  return;
11049
10937
  }
11050
10938
  }
11051
- fs14.unlinkSync(resolved.path);
10939
+ fs13.unlinkSync(resolved.path);
11052
10940
  try {
11053
- fs14.rmdirSync(path12.dirname(resolved.path));
10941
+ fs13.rmdirSync(path11.dirname(resolved.path));
11054
10942
  } catch {
11055
10943
  }
11056
10944
  if (isAgentMode()) {
@@ -11079,7 +10967,7 @@ actions.command("search <platform> <query>").description('Search for actions on
11079
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) => {
11080
10968
  await actionsKnowledgeCommand(platform, actionId, options);
11081
10969
  });
11082
- 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) => {
11083
10971
  if (options.parallel) {
11084
10972
  await actionsExecuteParallelCommand();
11085
10973
  return;
@@ -11097,7 +10985,8 @@ actions.command("execute [platform] [actionId] [connectionKey]").alias("x").allo
11097
10985
  dryRun: options.dryRun,
11098
10986
  mock: options.mock,
11099
10987
  skipValidation: options.skipValidation,
11100
- output: options.output
10988
+ output: options.output,
10989
+ cache: options.cache
11101
10990
  });
11102
10991
  });
11103
10992
  var flow = program.command("flow").alias("f").description("Create, execute, and manage multi-step workflows");