@withone/cli 1.44.2 → 1.45.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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-DZK56R5R.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) {
@@ -2485,8 +2382,9 @@ async function actionsSearchCommand(platform, query, options) {
2485
2382
  try {
2486
2383
  const agentType = knowledgeAgent ? "knowledge" : options.type || "execute";
2487
2384
  const useCache = options.cache !== false;
2488
- const cachePath = searchCachePath(platform, query, agentType || "knowledge");
2489
- const cached = useCache ? readCache2(cachePath) : null;
2385
+ const searchType = agentType || "knowledge";
2386
+ const cachePath = searchCachePath(platform, query, searchType);
2387
+ const cached = useCache ? readCache(cachePath) : null;
2490
2388
  let cleanedActions;
2491
2389
  let cacheHit = false;
2492
2390
  if (cached && isFresh(cached)) {
@@ -2502,7 +2400,7 @@ async function actionsSearchCommand(platform, query, options) {
2502
2400
  );
2503
2401
  if (result.status === 304 && cached) {
2504
2402
  cached.cachedAt = (/* @__PURE__ */ new Date()).toISOString();
2505
- writeCache2(cachePath, cached);
2403
+ writeCache(cachePath, cached);
2506
2404
  cleanedActions = cached.data.actions;
2507
2405
  cacheHit = true;
2508
2406
  } else {
@@ -2515,9 +2413,9 @@ async function actionsSearchCommand(platform, query, options) {
2515
2413
  method: action.method,
2516
2414
  path: action.path
2517
2415
  }));
2518
- writeCache2(cachePath, makeCacheEntry(
2519
- `${platform}_${query}_${agentType || "knowledge"}`,
2520
- { actions: cleanedActions },
2416
+ writeCache(cachePath, makeCacheEntry(
2417
+ `${platform}_${query}_${searchType}`,
2418
+ { actions: cleanedActions, platform, query, searchType },
2521
2419
  result.etag
2522
2420
  ));
2523
2421
  }
@@ -2539,7 +2437,7 @@ async function actionsSearchCommand(platform, query, options) {
2539
2437
  if (cacheHit && cached) {
2540
2438
  response._cache = buildCacheMeta(cached, true);
2541
2439
  } else {
2542
- const freshEntry = readCache2(cachePath);
2440
+ const freshEntry = readCache(cachePath);
2543
2441
  response._cache = buildCacheMeta(freshEntry, false);
2544
2442
  }
2545
2443
  json(response);
@@ -2599,7 +2497,7 @@ Execute: ${pc6.cyan(`one actions execute ${platform} <actionId> <connectionK
2599
2497
  async function actionsKnowledgeCommand(platform, actionId, options) {
2600
2498
  const cachePath = knowledgeCachePath(actionId);
2601
2499
  if (options.cacheStatus) {
2602
- const entry = readCache2(cachePath);
2500
+ const entry = readCache(cachePath);
2603
2501
  if (!entry) {
2604
2502
  json({
2605
2503
  cached: false,
@@ -2646,44 +2544,13 @@ async function actionsKnowledgeCommand(platform, actionId, options) {
2646
2544
  const spinner5 = createSpinner();
2647
2545
  spinner5.start(`Loading knowledge for action ${pc6.dim(actionId)}...`);
2648
2546
  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
- }
2547
+ const { details, cacheHit, entry } = await resolveActionDetails(api, actionId, {
2548
+ useCache: options.cache !== false
2549
+ });
2550
+ const knowledgeData = {
2551
+ knowledge: details.knowledge || "No knowledge was found",
2552
+ method: details.method || "No method was found"
2553
+ };
2687
2554
  const knowledgeWithGuidance = buildActionKnowledgeWithGuidance(
2688
2555
  knowledgeData.knowledge,
2689
2556
  knowledgeData.method,
@@ -2694,7 +2561,7 @@ async function actionsKnowledgeCommand(platform, actionId, options) {
2694
2561
  const response = {
2695
2562
  knowledge: knowledgeWithGuidance,
2696
2563
  method: knowledgeData.method,
2697
- _cache: buildCacheMeta(cacheEntry, cacheHit)
2564
+ _cache: buildCacheMeta(entry, cacheHit)
2698
2565
  };
2699
2566
  json(response);
2700
2567
  return;
@@ -2730,16 +2597,18 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
2730
2597
  }
2731
2598
  const api = new OneApi(apiKey, getApiBase());
2732
2599
  const spinner5 = createSpinner();
2733
- spinner5.start("Loading action details...");
2600
+ spinner5.start("Resolving action details...");
2734
2601
  try {
2735
- const actionDetails = await api.getActionDetails(actionId);
2602
+ const { details: actionDetails, cacheHit: preflightCacheHit } = await resolveActionDetails(api, actionId, { useCache: options.cache !== false });
2736
2603
  if (!isMethodAllowed(actionDetails.method, permissions)) {
2737
2604
  spinner5.stop("Permission denied");
2738
2605
  error(
2739
2606
  `Method "${actionDetails.method}" is not allowed under "${permissions}" permission level.`
2740
2607
  );
2741
2608
  }
2742
- spinner5.stop(`Action: ${actionDetails.title} [${actionDetails.method}]`);
2609
+ spinner5.stop(
2610
+ `Action: ${actionDetails.title} [${actionDetails.method}]` + (preflightCacheHit ? pc6.dim(" (cached)") : "")
2611
+ );
2743
2612
  const data = options.data ? parseJsonArg2(options.data, "--data") : void 0;
2744
2613
  const pathVariables = options.pathVars ? parseJsonArg2(options.pathVars, "--path-vars") : void 0;
2745
2614
  const queryParams = options.queryParams ? parseJsonArg2(options.queryParams, "--query-params") : void 0;
@@ -2778,7 +2647,8 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
2778
2647
  url: actionDetails.path
2779
2648
  },
2780
2649
  response: mockResponse,
2781
- ...mockResponse === null ? { message: "No example output available for this action" } : {}
2650
+ ...mockResponse === null ? { message: "No example output available for this action" } : {},
2651
+ _preflight: { cache: preflightCacheHit ? "hit" : "miss" }
2782
2652
  });
2783
2653
  return;
2784
2654
  }
@@ -2819,7 +2689,8 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
2819
2689
  headers: options.dryRun ? result.requestConfig.headers : void 0,
2820
2690
  data: options.dryRun ? result.requestConfig.data : void 0
2821
2691
  },
2822
- response: options.dryRun ? void 0 : result.responseData
2692
+ response: options.dryRun ? void 0 : result.responseData,
2693
+ _preflight: { cache: preflightCacheHit ? "hit" : "miss" }
2823
2694
  });
2824
2695
  return;
2825
2696
  }
@@ -2863,7 +2734,7 @@ function parseParallelSegments() {
2863
2734
  error('Could not locate "actions execute" in argv');
2864
2735
  }
2865
2736
  const raw = argv.slice(execIdx + 1);
2866
- const flags = { dryRun: false, mock: false, skipValidation: false, maxConcurrency: 5 };
2737
+ const flags = { dryRun: false, mock: false, skipValidation: false, maxConcurrency: 5, useCache: true };
2867
2738
  const cleaned = [];
2868
2739
  for (let i = 0; i < raw.length; i++) {
2869
2740
  const t = raw[i];
@@ -2880,6 +2751,10 @@ function parseParallelSegments() {
2880
2751
  flags.skipValidation = true;
2881
2752
  continue;
2882
2753
  }
2754
+ if (t === "--no-cache") {
2755
+ flags.useCache = false;
2756
+ continue;
2757
+ }
2883
2758
  if (t === "--max-concurrency") {
2884
2759
  flags.maxConcurrency = parseInt(raw[++i], 10) || 5;
2885
2760
  continue;
@@ -2958,6 +2833,7 @@ async function actionsExecuteParallelCommand() {
2958
2833
  const api = new OneApi(apiKey, getApiBase());
2959
2834
  const prepared = [];
2960
2835
  const errors = [];
2836
+ const staleWarned = /* @__PURE__ */ new Set();
2961
2837
  for (let i = 0; i < segments.length; i++) {
2962
2838
  const seg = segments[i];
2963
2839
  const label = `${seg.platform}/${seg.actionId}`;
@@ -2969,8 +2845,18 @@ async function actionsExecuteParallelCommand() {
2969
2845
  segErrors.push(`Connection key "${seg.connectionKey}" is not allowed`);
2970
2846
  }
2971
2847
  let actionDetails;
2848
+ let preflightCacheHit = false;
2972
2849
  try {
2973
- actionDetails = await api.getActionDetails(seg.actionId);
2850
+ const resolved = await resolveActionDetails(api, seg.actionId, {
2851
+ useCache: flags.useCache,
2852
+ warn: (msg) => {
2853
+ if (staleWarned.has(seg.actionId)) return;
2854
+ staleWarned.add(seg.actionId);
2855
+ process.stderr.write(msg);
2856
+ }
2857
+ });
2858
+ actionDetails = resolved.details;
2859
+ preflightCacheHit = resolved.cacheHit;
2974
2860
  } catch (err) {
2975
2861
  segErrors.push(`Action not found: ${err instanceof Error ? err.message : String(err)}`);
2976
2862
  }
@@ -3016,7 +2902,7 @@ async function actionsExecuteParallelCommand() {
3016
2902
  if (segErrors.length > 0) {
3017
2903
  errors.push({ segment: i + 1, label, messages: segErrors });
3018
2904
  } else if (actionDetails) {
3019
- prepared.push({ segment: seg, index: i, actionDetails, data, pathVariables, queryParams, headers });
2905
+ prepared.push({ segment: seg, index: i, actionDetails, preflightCacheHit, data, pathVariables, queryParams, headers });
3020
2906
  }
3021
2907
  }
3022
2908
  if (errors.length > 0) {
@@ -3054,7 +2940,8 @@ async function actionsExecuteParallelCommand() {
3054
2940
  durationMs: Date.now() - start,
3055
2941
  mock: true,
3056
2942
  request: { method: action.actionDetails.method, url: action.actionDetails.path },
3057
- response: mockResponse
2943
+ response: mockResponse,
2944
+ _preflight: { cache: action.preflightCacheHit ? "hit" : "miss" }
3058
2945
  };
3059
2946
  }
3060
2947
  const result = await api.executePassthroughRequest({
@@ -3081,7 +2968,8 @@ async function actionsExecuteParallelCommand() {
3081
2968
  url: result.requestConfig.url,
3082
2969
  ...flags.dryRun ? { headers: result.requestConfig.headers, data: result.requestConfig.data } : {}
3083
2970
  },
3084
- response: flags.dryRun ? void 0 : result.responseData
2971
+ response: flags.dryRun ? void 0 : result.responseData,
2972
+ _preflight: { cache: action.preflightCacheHit ? "hit" : "miss" }
3085
2973
  };
3086
2974
  })
3087
2975
  );
@@ -3162,8 +3050,8 @@ function colorMethod(method) {
3162
3050
  import pc7 from "picocolors";
3163
3051
 
3164
3052
  // src/lib/flow-validator.ts
3165
- import fs5 from "fs";
3166
- import path5 from "path";
3053
+ import fs4 from "fs";
3054
+ import path4 from "path";
3167
3055
  import { spawnSync } from "child_process";
3168
3056
  function validateFlowSchema(flow2) {
3169
3057
  const errors = [];
@@ -3228,32 +3116,32 @@ function validateStepsArray(steps, pathPrefix, errors) {
3228
3116
  const validTypes = FLOW_SCHEMA.stepTypes.map((st) => st.type);
3229
3117
  for (let i = 0; i < steps.length; i++) {
3230
3118
  const step = steps[i];
3231
- const path13 = `${pathPrefix}[${i}]`;
3119
+ const path12 = `${pathPrefix}[${i}]`;
3232
3120
  if (!step || typeof step !== "object" || Array.isArray(step)) {
3233
- errors.push({ path: path13, message: "Step must be an object" });
3121
+ errors.push({ path: path12, message: "Step must be an object" });
3234
3122
  continue;
3235
3123
  }
3236
3124
  const s = step;
3237
3125
  if (!s.id || typeof s.id !== "string") {
3238
- errors.push({ path: `${path13}.id`, message: 'Step must have a string "id"' });
3126
+ errors.push({ path: `${path12}.id`, message: 'Step must have a string "id"' });
3239
3127
  }
3240
3128
  if (!s.name || typeof s.name !== "string") {
3241
- errors.push({ path: `${path13}.name`, message: 'Step must have a string "name"' });
3129
+ errors.push({ path: `${path12}.name`, message: 'Step must have a string "name"' });
3242
3130
  }
3243
3131
  if (!s.type || !validTypes.includes(s.type)) {
3244
- errors.push({ path: `${path13}.type`, message: `Step type must be one of: ${validTypes.join(", ")}` });
3132
+ errors.push({ path: `${path12}.type`, message: `Step type must be one of: ${validTypes.join(", ")}` });
3245
3133
  continue;
3246
3134
  }
3247
3135
  if (s.requires !== void 0) {
3248
3136
  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"])' });
3137
+ errors.push({ path: `${path12}.requires`, message: '"requires" must be an array of selector strings (e.g. ["$.steps.foo.output.bar"])' });
3250
3138
  } else {
3251
3139
  for (let r = 0; r < s.requires.length; r++) {
3252
3140
  const sel = s.requires[r];
3253
3141
  if (typeof sel !== "string") {
3254
- errors.push({ path: `${path13}.requires[${r}]`, message: '"requires" entry must be a selector string' });
3142
+ errors.push({ path: `${path12}.requires[${r}]`, message: '"requires" entry must be a selector string' });
3255
3143
  } 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")` });
3144
+ errors.push({ path: `${path12}.requires[${r}]`, message: `"requires" entry "${sel}" must be a selector starting with "$." (e.g. "$.steps.foo.output.bar")` });
3257
3145
  }
3258
3146
  }
3259
3147
  }
@@ -3261,7 +3149,7 @@ function validateStepsArray(steps, pathPrefix, errors) {
3261
3149
  if (s.onError && typeof s.onError === "object") {
3262
3150
  const oe = s.onError;
3263
3151
  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(", ")}` });
3152
+ errors.push({ path: `${path12}.onError.strategy`, message: `Error strategy must be one of: ${FLOW_SCHEMA.errorStrategies.join(", ")}` });
3265
3153
  }
3266
3154
  }
3267
3155
  const descriptor = getStepTypeDescriptor(s.type);
@@ -3271,14 +3159,14 @@ function validateStepsArray(steps, pathPrefix, errors) {
3271
3159
  if (!configObj || typeof configObj !== "object") {
3272
3160
  const hint = detectFlatConfigHint(s, descriptor);
3273
3161
  errors.push({
3274
- path: `${path13}.${configKey}`,
3162
+ path: `${path12}.${configKey}`,
3275
3163
  message: `${capitalize(descriptor.type)} step must have a "${configKey}" config object${hint}`
3276
3164
  });
3277
3165
  continue;
3278
3166
  }
3279
3167
  const config2 = configObj;
3280
3168
  for (const [fieldName, fd] of Object.entries(descriptor.fields)) {
3281
- const fieldPath = `${path13}.${configKey}.${fieldName}`;
3169
+ const fieldPath = `${path12}.${configKey}.${fieldName}`;
3282
3170
  const value = config2[fieldName];
3283
3171
  if (fd.required && (value === void 0 || value === null || value === "")) {
3284
3172
  errors.push({ path: fieldPath, message: `${capitalize(descriptor.type)} must have ${fd.type === "string" ? "a string" : fd.type === "array" ? "a" : "a"} "${fieldName}"` });
@@ -3311,30 +3199,30 @@ function validateStepsArray(steps, pathPrefix, errors) {
3311
3199
  }
3312
3200
  }
3313
3201
  if (descriptor.type === "action") {
3314
- validateConnectionForm(config2, `${path13}.${configKey}`, errors);
3202
+ validateConnectionForm(config2, `${path12}.${configKey}`, errors);
3315
3203
  }
3316
3204
  if (descriptor.type === "code") {
3317
3205
  const hasSource = typeof config2.source === "string" && config2.source.length > 0;
3318
3206
  const hasModule = typeof config2.module === "string" && config2.module.length > 0;
3319
3207
  if (!hasSource && !hasModule) {
3320
- errors.push({ path: `${path13}.${configKey}`, message: 'Code step must define either "source" (inline JS) or "module" (path to .mjs file)' });
3208
+ errors.push({ path: `${path12}.${configKey}`, message: 'Code step must define either "source" (inline JS) or "module" (path to .mjs file)' });
3321
3209
  } else if (hasSource && hasModule) {
3322
- errors.push({ path: `${path13}.${configKey}`, message: 'Code step cannot define both "source" and "module" \u2014 pick one' });
3210
+ errors.push({ path: `${path12}.${configKey}`, message: 'Code step cannot define both "source" and "module" \u2014 pick one' });
3323
3211
  }
3324
3212
  if (hasModule) {
3325
3213
  const m = config2.module;
3326
3214
  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)" });
3215
+ errors.push({ path: `${path12}.${configKey}.module`, message: "Code module path must be relative to the flow folder (no absolute paths)" });
3328
3216
  } else if (m.split(/[\\/]/).includes("..")) {
3329
- errors.push({ path: `${path13}.${configKey}.module`, message: 'Code module path must not escape the flow folder ("..")' });
3217
+ errors.push({ path: `${path12}.${configKey}.module`, message: 'Code module path must not escape the flow folder ("..")' });
3330
3218
  } else if (!m.endsWith(".mjs")) {
3331
- errors.push({ path: `${path13}.${configKey}.module`, message: "Code module must be a .mjs file" });
3219
+ errors.push({ path: `${path12}.${configKey}.module`, message: "Code module must be a .mjs file" });
3332
3220
  }
3333
3221
  }
3334
3222
  if (hasSource) {
3335
3223
  const syntaxError = checkCodeSourceSyntax(config2.source);
3336
3224
  if (syntaxError) {
3337
- errors.push({ path: `${path13}.${configKey}.source`, message: `Syntax error in code step: ${syntaxError}` });
3225
+ errors.push({ path: `${path12}.${configKey}.source`, message: `Syntax error in code step: ${syntaxError}` });
3338
3226
  }
3339
3227
  }
3340
3228
  }
@@ -3406,16 +3294,16 @@ function validateStepIds(flow2) {
3406
3294
  function collectIds(steps, pathPrefix) {
3407
3295
  for (let i = 0; i < steps.length; i++) {
3408
3296
  const step = steps[i];
3409
- const path13 = `${pathPrefix}[${i}]`;
3297
+ const path12 = `${pathPrefix}[${i}]`;
3410
3298
  if (seen.has(step.id)) {
3411
- errors.push({ path: `${path13}.id`, message: `Duplicate step ID: "${step.id}"` });
3299
+ errors.push({ path: `${path12}.id`, message: `Duplicate step ID: "${step.id}"` });
3412
3300
  } else {
3413
3301
  seen.add(step.id);
3414
3302
  }
3415
3303
  for (const { configKey, fieldName } of nestedKeys) {
3416
3304
  const config2 = step[configKey];
3417
3305
  if (config2 && Array.isArray(config2[fieldName])) {
3418
- collectIds(config2[fieldName], `${path13}.${configKey}.${fieldName}`);
3306
+ collectIds(config2[fieldName], `${path12}.${configKey}.${fieldName}`);
3419
3307
  }
3420
3308
  }
3421
3309
  }
@@ -3463,7 +3351,7 @@ function validateSelectorReferences(flow2) {
3463
3351
  }
3464
3352
  return selectors;
3465
3353
  }
3466
- function checkSelectors(selectors, path13, precedingStepIds) {
3354
+ function checkSelectors(selectors, path12, precedingStepIds) {
3467
3355
  for (const selector of selectors) {
3468
3356
  const parts = selector.split(".");
3469
3357
  if (parts.length < 3) continue;
@@ -3471,15 +3359,15 @@ function validateSelectorReferences(flow2) {
3471
3359
  if (root === "input") {
3472
3360
  const inputName = parts[2];
3473
3361
  if (!inputNames.has(inputName)) {
3474
- errors.push({ path: path13, message: `Selector "${selector}" references undefined input "${inputName}"` });
3362
+ errors.push({ path: path12, message: `Selector "${selector}" references undefined input "${inputName}"` });
3475
3363
  }
3476
3364
  } else if (root === "steps") {
3477
3365
  const stepId = parts[2].replace(/[\[\]]/g, "").split(/[\[\]]/)[0];
3478
3366
  if (!allStepIds.has(stepId)) {
3479
- errors.push({ path: path13, message: `Selector "${selector}" references undefined step "${stepId}"` });
3367
+ errors.push({ path: path12, message: `Selector "${selector}" references undefined step "${stepId}"` });
3480
3368
  } else if (precedingStepIds && !precedingStepIds.has(stepId)) {
3481
3369
  errors.push({
3482
- path: path13,
3370
+ path: path12,
3483
3371
  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
3372
  });
3485
3373
  }
@@ -3487,20 +3375,20 @@ function validateSelectorReferences(flow2) {
3487
3375
  }
3488
3376
  }
3489
3377
  const EXPRESSION_FIELDS = /* @__PURE__ */ new Set(["condition.expression", "while.condition"]);
3490
- function checkOperatorsInSelectorField(value, path13) {
3378
+ function checkOperatorsInSelectorField(value, path12) {
3491
3379
  if (typeof value === "string" && value.startsWith("$.")) {
3492
3380
  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.` });
3381
+ 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
3382
  } 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.` });
3383
+ 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
3384
  }
3497
3385
  } else if (value && typeof value === "object" && !Array.isArray(value)) {
3498
3386
  for (const [k, v] of Object.entries(value)) {
3499
- checkOperatorsInSelectorField(v, `${path13}.${k}`);
3387
+ checkOperatorsInSelectorField(v, `${path12}.${k}`);
3500
3388
  }
3501
3389
  } else if (Array.isArray(value)) {
3502
3390
  for (let i = 0; i < value.length; i++) {
3503
- checkOperatorsInSelectorField(value[i], `${path13}[${i}]`);
3391
+ checkOperatorsInSelectorField(value[i], `${path12}[${i}]`);
3504
3392
  }
3505
3393
  }
3506
3394
  }
@@ -3568,10 +3456,10 @@ var VALID_OUTPUT_SCHEMA_TYPES = /* @__PURE__ */ new Set(["string", "number", "bo
3568
3456
  function isOutputSchemaObject(v) {
3569
3457
  return !!v && typeof v === "object" && !Array.isArray(v);
3570
3458
  }
3571
- function walkOutputSchema(schema, path13) {
3459
+ function walkOutputSchema(schema, path12) {
3572
3460
  let current = schema;
3573
- for (let i = 0; i < path13.length; i++) {
3574
- const seg = path13[i];
3461
+ for (let i = 0; i < path12.length; i++) {
3462
+ const seg = path12[i];
3575
3463
  if (typeof current === "string") {
3576
3464
  return current === "unknown" || current === "object" || current === "array" ? "opaque" : "opaque";
3577
3465
  }
@@ -3722,8 +3610,8 @@ function validateCodeModules(flow2, rootDir) {
3722
3610
  const stepPath = `${pathPrefix}[${i}]`;
3723
3611
  if (step.type === "code" && step.code?.module) {
3724
3612
  const m = step.code.module;
3725
- const abs = path5.resolve(rootDir, m);
3726
- if (!fs5.existsSync(abs)) {
3613
+ const abs = path4.resolve(rootDir, m);
3614
+ if (!fs4.existsSync(abs)) {
3727
3615
  errors.push({
3728
3616
  path: `${stepPath}.code.module`,
3729
3617
  message: `Code module "${m}" not found at ${abs}`
@@ -3752,8 +3640,8 @@ function validateCodeModules(flow2, rootDir) {
3752
3640
  }
3753
3641
 
3754
3642
  // src/commands/flow.ts
3755
- import fs6 from "fs";
3756
- import path6 from "path";
3643
+ import fs5 from "fs";
3644
+ import path5 from "path";
3757
3645
  function getConfig2() {
3758
3646
  const apiKey = getApiKey();
3759
3647
  if (!apiKey) {
@@ -3811,7 +3699,7 @@ async function flowCreateCommand(key, options) {
3811
3699
  if (raw.startsWith("@")) {
3812
3700
  const filePath = raw.slice(1);
3813
3701
  try {
3814
- raw = fs6.readFileSync(filePath, "utf-8");
3702
+ raw = fs5.readFileSync(filePath, "utf-8");
3815
3703
  } catch (err) {
3816
3704
  error(`Cannot read file "${filePath}": ${err.message}`);
3817
3705
  }
@@ -4041,9 +3929,9 @@ async function flowValidateCommand(keyOrPath) {
4041
3929
  rootDir = loaded.rootDir;
4042
3930
  } catch {
4043
3931
  const flowPath = resolveFlowPath(keyOrPath);
4044
- const content = fs6.readFileSync(flowPath, "utf-8");
3932
+ const content = fs5.readFileSync(flowPath, "utf-8");
4045
3933
  flowData = JSON.parse(content);
4046
- rootDir = path6.dirname(flowPath);
3934
+ rootDir = path5.dirname(flowPath);
4047
3935
  }
4048
3936
  } catch (err) {
4049
3937
  spinner5.stop("Validation failed");
@@ -4866,11 +4754,11 @@ function handleId(response, config2, records) {
4866
4754
  }
4867
4755
 
4868
4756
  // 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");
4757
+ import fs6 from "fs";
4758
+ import path6 from "path";
4759
+ var SYNC_DIR = path6.join(".one", "sync");
4760
+ var STATE_DIR = path6.join(SYNC_DIR, "state");
4761
+ var LEGACY_SINGLE_FILE = path6.join(SYNC_DIR, "sync_state.json");
4874
4762
  var legacyMigrationDone = false;
4875
4763
  function rowToState(row) {
4876
4764
  return {
@@ -4898,9 +4786,9 @@ function stateToRow(platform, model, state, lastError) {
4898
4786
  async function migrateLegacyOnce() {
4899
4787
  if (legacyMigrationDone) return;
4900
4788
  legacyMigrationDone = true;
4901
- if (fs7.existsSync(LEGACY_SINGLE_FILE)) {
4789
+ if (fs6.existsSync(LEGACY_SINGLE_FILE)) {
4902
4790
  try {
4903
- const raw = fs7.readFileSync(LEGACY_SINGLE_FILE, "utf-8");
4791
+ const raw = fs6.readFileSync(LEGACY_SINGLE_FILE, "utf-8");
4904
4792
  const legacy = JSON.parse(raw);
4905
4793
  const backend = await getBackend();
4906
4794
  for (const [platform, models] of Object.entries(legacy)) {
@@ -4910,32 +4798,32 @@ async function migrateLegacyOnce() {
4910
4798
  await backend.setSyncState(stateToRow(platform, model, modelState));
4911
4799
  }
4912
4800
  }
4913
- fs7.unlinkSync(LEGACY_SINGLE_FILE);
4801
+ fs6.unlinkSync(LEGACY_SINGLE_FILE);
4914
4802
  } catch {
4915
4803
  try {
4916
- fs7.unlinkSync(LEGACY_SINGLE_FILE);
4804
+ fs6.unlinkSync(LEGACY_SINGLE_FILE);
4917
4805
  } catch {
4918
4806
  }
4919
4807
  }
4920
4808
  }
4921
- if (fs7.existsSync(STATE_DIR)) {
4809
+ if (fs6.existsSync(STATE_DIR)) {
4922
4810
  try {
4923
4811
  const backend = await getBackend();
4924
- const platforms = fs7.readdirSync(STATE_DIR);
4812
+ const platforms = fs6.readdirSync(STATE_DIR);
4925
4813
  for (const platform of platforms) {
4926
- const platformDir = path7.join(STATE_DIR, platform);
4814
+ const platformDir = path6.join(STATE_DIR, platform);
4927
4815
  let entries;
4928
4816
  try {
4929
- entries = fs7.readdirSync(platformDir);
4817
+ entries = fs6.readdirSync(platformDir);
4930
4818
  } catch {
4931
4819
  continue;
4932
4820
  }
4933
4821
  for (const entry of entries) {
4934
4822
  if (!entry.endsWith(".json")) continue;
4935
4823
  const model = entry.slice(0, -".json".length);
4936
- const filePath = path7.join(platformDir, entry);
4824
+ const filePath = path6.join(platformDir, entry);
4937
4825
  try {
4938
- const raw = fs7.readFileSync(filePath, "utf-8");
4826
+ const raw = fs6.readFileSync(filePath, "utf-8");
4939
4827
  const modelState = JSON.parse(raw);
4940
4828
  const existing = await backend.getSyncState(platform, model);
4941
4829
  if (!existing) {
@@ -4945,7 +4833,7 @@ async function migrateLegacyOnce() {
4945
4833
  }
4946
4834
  }
4947
4835
  }
4948
- fs7.rmSync(STATE_DIR, { recursive: true, force: true });
4836
+ fs6.rmSync(STATE_DIR, { recursive: true, force: true });
4949
4837
  } catch {
4950
4838
  }
4951
4839
  }
@@ -4989,12 +4877,12 @@ async function removeModelState(platform, model) {
4989
4877
  }
4990
4878
 
4991
4879
  // 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");
4880
+ import fs7 from "fs";
4881
+ import path7 from "path";
4882
+ var LOCK_DIR_REL = path7.join(".one", "sync", "locks");
4995
4883
  var STALE_MS = 30 * 60 * 1e3;
4996
4884
  function lockPath(platform, model) {
4997
- return path8.join(LOCK_DIR_REL, `${platform}_${model}`);
4885
+ return path7.join(LOCK_DIR_REL, `${platform}_${model}`);
4998
4886
  }
4999
4887
  function isProcessAlive(pid) {
5000
4888
  try {
@@ -5011,15 +4899,15 @@ var SyncLockError = class extends Error {
5011
4899
  }
5012
4900
  };
5013
4901
  function acquireSyncLock(platform, model) {
5014
- fs8.mkdirSync(LOCK_DIR_REL, { recursive: true });
4902
+ fs7.mkdirSync(LOCK_DIR_REL, { recursive: true });
5015
4903
  const dir = lockPath(platform, model);
5016
- const pidFile = path8.join(dir, "pid");
4904
+ const pidFile = path7.join(dir, "pid");
5017
4905
  try {
5018
- fs8.mkdirSync(dir);
4906
+ fs7.mkdirSync(dir);
5019
4907
  } catch (err) {
5020
4908
  const stat = (() => {
5021
4909
  try {
5022
- return fs8.statSync(dir);
4910
+ return fs7.statSync(dir);
5023
4911
  } catch {
5024
4912
  return null;
5025
4913
  }
@@ -5028,7 +4916,7 @@ function acquireSyncLock(platform, model) {
5028
4916
  const age = Date.now() - stat.mtimeMs;
5029
4917
  let ownerPid = null;
5030
4918
  try {
5031
- const raw = fs8.readFileSync(pidFile, "utf-8");
4919
+ const raw = fs7.readFileSync(pidFile, "utf-8");
5032
4920
  const parsed = parseInt(raw.trim(), 10);
5033
4921
  if (!isNaN(parsed)) ownerPid = parsed;
5034
4922
  } catch {
@@ -5037,8 +4925,8 @@ function acquireSyncLock(platform, model) {
5037
4925
  const veryOld = age > STALE_MS;
5038
4926
  if (ownerDead || veryOld) {
5039
4927
  try {
5040
- fs8.rmSync(dir, { recursive: true, force: true });
5041
- fs8.mkdirSync(dir);
4928
+ fs7.rmSync(dir, { recursive: true, force: true });
4929
+ fs7.mkdirSync(dir);
5042
4930
  } catch {
5043
4931
  throw new SyncLockError(
5044
4932
  `Could not take over stale lock at ${dir}. Remove it manually if no sync is running.`
@@ -5055,13 +4943,13 @@ function acquireSyncLock(platform, model) {
5055
4943
  }
5056
4944
  }
5057
4945
  try {
5058
- fs8.writeFileSync(pidFile, String(process.pid));
4946
+ fs7.writeFileSync(pidFile, String(process.pid));
5059
4947
  } catch {
5060
4948
  }
5061
4949
  return {
5062
4950
  release() {
5063
4951
  try {
5064
- fs8.rmSync(dir, { recursive: true, force: true });
4952
+ fs7.rmSync(dir, { recursive: true, force: true });
5065
4953
  } catch {
5066
4954
  }
5067
4955
  }
@@ -5070,9 +4958,9 @@ function acquireSyncLock(platform, model) {
5070
4958
 
5071
4959
  // src/lib/memory/sync/hooks.ts
5072
4960
  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");
4961
+ import fs8 from "fs";
4962
+ import path8 from "path";
4963
+ var EVENTS_DIR = path8.join(".one", "sync", "events");
5076
4964
  function classifyRecords(db, model, records, idField, tableExists2) {
5077
4965
  if (!tableExists2 || records.length === 0) {
5078
4966
  return { inserts: records, updates: [] };
@@ -5118,10 +5006,10 @@ async function fireHooks(hookCommand, events) {
5118
5006
  function appendEventLog(events) {
5119
5007
  if (events.length === 0) return;
5120
5008
  const { platform, model } = events[0];
5121
- fs9.mkdirSync(EVENTS_DIR, { recursive: true });
5122
- const logPath = path9.join(EVENTS_DIR, `${platform}_${model}.jsonl`);
5009
+ fs8.mkdirSync(EVENTS_DIR, { recursive: true });
5010
+ const logPath = path8.join(EVENTS_DIR, `${platform}_${model}.jsonl`);
5123
5011
  const lines = events.map((e) => JSON.stringify(e)).join("\n") + "\n";
5124
- fs9.appendFileSync(logPath, lines);
5012
+ fs8.appendFileSync(logPath, lines);
5125
5013
  }
5126
5014
  function runShellHook(command, events) {
5127
5015
  return new Promise((resolve) => {
@@ -5144,10 +5032,10 @@ function runShellHook(command, events) {
5144
5032
  }
5145
5033
 
5146
5034
  // src/lib/memory/sync/mem-writer.ts
5147
- function resolveWildcardPath(root, path13) {
5148
- const segments = path13.split("[]");
5035
+ function resolveWildcardPath(root, path12) {
5036
+ const segments = path12.split("[]");
5149
5037
  if (segments.length === 1) {
5150
- return [getByDotPath(root, path13)];
5038
+ return [getByDotPath(root, path12)];
5151
5039
  }
5152
5040
  const recurse = (value, idx) => {
5153
5041
  if (value === null || value === void 0) return [];
@@ -5173,8 +5061,8 @@ function resolveWildcardPath(root, path13) {
5173
5061
  function extractSearchableFromPaths(record, paths) {
5174
5062
  const parts = [];
5175
5063
  const perPath = [];
5176
- for (const path13 of paths) {
5177
- const values = resolveWildcardPath(record, path13);
5064
+ for (const path12 of paths) {
5065
+ const values = resolveWildcardPath(record, path12);
5178
5066
  const collected = [];
5179
5067
  const absorb = (v) => {
5180
5068
  if (v === null || v === void 0) return;
@@ -5190,9 +5078,9 @@ function extractSearchableFromPaths(record, paths) {
5190
5078
  for (const v of values) absorb(v);
5191
5079
  if (collected.length > 0) {
5192
5080
  parts.push(...collected);
5193
- perPath.push({ path: path13, found: true, sample: collected.join(" ").slice(0, 80) });
5081
+ perPath.push({ path: path12, found: true, sample: collected.join(" ").slice(0, 80) });
5194
5082
  } else {
5195
- perPath.push({ path: path13, found: false, sample: "" });
5083
+ perPath.push({ path: path12, found: false, sample: "" });
5196
5084
  }
5197
5085
  }
5198
5086
  const text5 = parts.join(" ").replace(/\s+/g, " ").trim();
@@ -5371,8 +5259,8 @@ function sleep(ms) {
5371
5259
  return new Promise((resolve) => setTimeout(resolve, ms));
5372
5260
  }
5373
5261
  function interpolate(template, record) {
5374
- return template.replace(/\{?\{(\w+(?:\.\w+)*)\}\}?/g, (_, path13) => {
5375
- const parts = path13.split(".");
5262
+ return template.replace(/\{?\{(\w+(?:\.\w+)*)\}\}?/g, (_, path12) => {
5263
+ const parts = path12.split(".");
5376
5264
  let value = record;
5377
5265
  for (const part of parts) {
5378
5266
  if (typeof value !== "object" || value === null) return "";
@@ -5400,8 +5288,8 @@ function deepMerge(target, source) {
5400
5288
  }
5401
5289
  return result;
5402
5290
  }
5403
- function getByDotPath2(obj, path13) {
5404
- const parts = path13.split(".");
5291
+ function getByDotPath2(obj, path12) {
5292
+ const parts = path12.split(".");
5405
5293
  let current = obj;
5406
5294
  for (const part of parts) {
5407
5295
  if (current === null || current === void 0 || typeof current !== "object") return void 0;
@@ -5410,8 +5298,8 @@ function getByDotPath2(obj, path13) {
5410
5298
  return current;
5411
5299
  }
5412
5300
  function stripExcludedFields(obj, paths) {
5413
- for (const path13 of paths) {
5414
- stripOnePath(obj, path13.replace(/\[\]/g, ".*").split("."));
5301
+ for (const path12 of paths) {
5302
+ stripOnePath(obj, path12.replace(/\[\]/g, ".*").split("."));
5415
5303
  }
5416
5304
  }
5417
5305
  function stripOnePath(obj, parts) {
@@ -5480,7 +5368,7 @@ async function enrichPhase(api, db, config2, model, idField, connectionKey, plat
5480
5368
  }
5481
5369
  let detailAction;
5482
5370
  try {
5483
- detailAction = await api.getActionDetails(config2.actionId);
5371
+ detailAction = (await resolveActionDetails(api, config2.actionId)).details;
5484
5372
  } catch (err) {
5485
5373
  throw new Error(
5486
5374
  `Enrich: could not load action ${config2.actionId}: ${err instanceof Error ? err.message : String(err)}`
@@ -5741,8 +5629,8 @@ function sleep2(ms) {
5741
5629
  return new Promise((resolve) => setTimeout(resolve, ms));
5742
5630
  }
5743
5631
  function stripFields(record, paths) {
5744
- for (const path13 of paths) {
5745
- stripOnePath2(record, path13.split("."));
5632
+ for (const path12 of paths) {
5633
+ stripOnePath2(record, path12.split("."));
5746
5634
  }
5747
5635
  }
5748
5636
  function stripOnePath2(obj, parts) {
@@ -5832,7 +5720,7 @@ async function syncModel(api, profile, options) {
5832
5720
  updateModelState(platform, model, { status: "failed", pagesProcessed, lastCursor }),
5833
5721
  (async () => {
5834
5722
  try {
5835
- const { getBackend: getBackend2 } = await import("./runtime-RVXAPQAZ.js");
5723
+ const { getBackend: getBackend2 } = await import("./runtime-3NDWRLXL.js");
5836
5724
  const backend = await getBackend2();
5837
5725
  await Promise.race([
5838
5726
  backend.close(),
@@ -5909,7 +5797,7 @@ async function syncModel(api, profile, options) {
5909
5797
  queryParams[param] = dateValue;
5910
5798
  }
5911
5799
  }
5912
- const actionDetails = await api.getActionDetails(profile.actionId);
5800
+ const { details: actionDetails } = await resolveActionDetails(api, profile.actionId);
5913
5801
  if (actionDetails.tags?.includes("custom")) {
5914
5802
  throw new Error(
5915
5803
  `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 +6075,7 @@ async function syncModel(api, profile, options) {
6187
6075
  db.exec(`DROP TABLE IF EXISTS _seen_ids`);
6188
6076
  }
6189
6077
  if (options.toMemory !== false) {
6190
- const backend = await (await import("./runtime-RVXAPQAZ.js")).getBackend();
6078
+ const backend = await (await import("./runtime-3NDWRLXL.js")).getBackend();
6191
6079
  const type = `${platform}/${model}`;
6192
6080
  const existing = await backend.listKeysByType(type);
6193
6081
  const sourcePrefix = `${type}:`;
@@ -6267,7 +6155,7 @@ async function syncModel(api, profile, options) {
6267
6155
  let statusCounts;
6268
6156
  if (options.toMemory !== false) {
6269
6157
  try {
6270
- const backend = await (await import("./runtime-RVXAPQAZ.js")).getBackend();
6158
+ const backend = await (await import("./runtime-3NDWRLXL.js")).getBackend();
6271
6159
  const typeName = `${platform}/${model}`;
6272
6160
  const [active, archived] = await Promise.all([
6273
6161
  backend.count(typeName, { status: "active" }),
@@ -6763,20 +6651,20 @@ function inferProfileFromKnowledge(knowledge, modelName, platform) {
6763
6651
 
6764
6652
  // src/lib/memory/sync/schedule.ts
6765
6653
  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
6654
  import fs10 from "fs";
6772
6655
  import os5 from "os";
6773
6656
  import path10 from "path";
6774
- var REGISTRY_DIR = path10.join(os5.homedir(), ".one", "sync");
6775
- var REGISTRY_FILE = path10.join(REGISTRY_DIR, "schedules.json");
6657
+
6658
+ // src/lib/memory/sync/schedule-registry.ts
6659
+ import fs9 from "fs";
6660
+ import os4 from "os";
6661
+ import path9 from "path";
6662
+ var REGISTRY_DIR = path9.join(os4.homedir(), ".one", "sync");
6663
+ var REGISTRY_FILE = path9.join(REGISTRY_DIR, "schedules.json");
6776
6664
  function readRaw() {
6777
6665
  try {
6778
- if (!fs10.existsSync(REGISTRY_FILE)) return { schedules: [] };
6779
- const raw = fs10.readFileSync(REGISTRY_FILE, "utf-8");
6666
+ if (!fs9.existsSync(REGISTRY_FILE)) return { schedules: [] };
6667
+ const raw = fs9.readFileSync(REGISTRY_FILE, "utf-8");
6780
6668
  const parsed = JSON.parse(raw);
6781
6669
  if (!parsed || !Array.isArray(parsed.schedules)) return { schedules: [] };
6782
6670
  return parsed;
@@ -6785,13 +6673,13 @@ function readRaw() {
6785
6673
  }
6786
6674
  }
6787
6675
  function writeRaw(file) {
6788
- fs10.mkdirSync(REGISTRY_DIR, { recursive: true });
6676
+ fs9.mkdirSync(REGISTRY_DIR, { recursive: true });
6789
6677
  const tmp = REGISTRY_FILE + ".tmp";
6790
- fs10.writeFileSync(tmp, JSON.stringify(file, null, 2));
6791
- fs10.renameSync(tmp, REGISTRY_FILE);
6678
+ fs9.writeFileSync(tmp, JSON.stringify(file, null, 2));
6679
+ fs9.renameSync(tmp, REGISTRY_FILE);
6792
6680
  }
6793
6681
  function makeScheduleId(platform, cwd) {
6794
- const slug = path10.basename(cwd).replace(/[^a-zA-Z0-9_-]/g, "-").toLowerCase();
6682
+ const slug = path9.basename(cwd).replace(/[^a-zA-Z0-9_-]/g, "-").toLowerCase();
6795
6683
  return `${platform}-${slug}`;
6796
6684
  }
6797
6685
  function listRegistered() {
@@ -6825,7 +6713,7 @@ function removeRegistered(id) {
6825
6713
 
6826
6714
  // src/lib/memory/sync/schedule.ts
6827
6715
  var MARKER = "# one-sync";
6828
- var LOG_DIR_REL = path11.join(".one", "sync", "logs");
6716
+ var LOG_DIR_REL = path10.join(".one", "sync", "logs");
6829
6717
  function durationToCron(every) {
6830
6718
  const match = every.match(/^(\d+)([mhd])$/);
6831
6719
  if (!match) return null;
@@ -6858,13 +6746,13 @@ function cronExprToDuration(expr) {
6858
6746
  return null;
6859
6747
  }
6860
6748
  function isWindows() {
6861
- return os6.platform() === "win32";
6749
+ return os5.platform() === "win32";
6862
6750
  }
6863
6751
  function resolveOneBinary() {
6864
6752
  try {
6865
6753
  const entry = process.argv[1];
6866
- if (entry && fs11.existsSync(entry)) {
6867
- return fs11.realpathSync(entry);
6754
+ if (entry && fs10.existsSync(entry)) {
6755
+ return fs10.realpathSync(entry);
6868
6756
  }
6869
6757
  } catch {
6870
6758
  }
@@ -6942,7 +6830,7 @@ function migrateLegacyCronEntries() {
6942
6830
  const modelsMatch = command.match(/--models\s+(\S+)/);
6943
6831
  const models = modelsMatch ? modelsMatch[1].split(",") : void 0;
6944
6832
  const logMatch = command.match(/>>\s+"([^"]+)"/);
6945
- const logFile = logMatch ? logMatch[1] : path11.resolve(cwd, LOG_DIR_REL, `${platform}.log`);
6833
+ const logFile = logMatch ? logMatch[1] : path10.resolve(cwd, LOG_DIR_REL, `${platform}.log`);
6946
6834
  const id = makeScheduleId(platform, cwd);
6947
6835
  if (registeredIds.has(id)) continue;
6948
6836
  upsertRegistered({
@@ -6976,9 +6864,9 @@ function addSchedule(opts) {
6976
6864
  const cwd = process.cwd();
6977
6865
  const id = makeScheduleId(opts.platform, cwd);
6978
6866
  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`);
6867
+ const logDir = path10.join(cwd, LOG_DIR_REL);
6868
+ fs10.mkdirSync(logDir, { recursive: true });
6869
+ const logFile = path10.join(logDir, `${opts.platform}.log`);
6982
6870
  const entry = {
6983
6871
  id,
6984
6872
  platform: opts.platform,
@@ -7032,15 +6920,15 @@ function removeSchedule(idOrPlatform, options) {
7032
6920
  function scheduleStatus() {
7033
6921
  const entries = listSchedules();
7034
6922
  return entries.map((entry) => {
7035
- const logExists = fs11.existsSync(entry.logFile);
7036
- const logSize = logExists ? fs11.statSync(entry.logFile).size : 0;
6923
+ const logExists = fs10.existsSync(entry.logFile);
6924
+ const logSize = logExists ? fs10.statSync(entry.logFile).size : 0;
7037
6925
  let logTail = [];
7038
6926
  let lastRunAt = null;
7039
6927
  if (logExists) {
7040
6928
  try {
7041
- lastRunAt = fs11.statSync(entry.logFile).mtime.toISOString();
6929
+ lastRunAt = fs10.statSync(entry.logFile).mtime.toISOString();
7042
6930
  if (logSize > 0) {
7043
- const content = fs11.readFileSync(entry.logFile, "utf-8");
6931
+ const content = fs10.readFileSync(entry.logFile, "utf-8");
7044
6932
  logTail = content.trim().split("\n").slice(-10);
7045
6933
  }
7046
6934
  } catch {
@@ -7048,8 +6936,8 @@ function scheduleStatus() {
7048
6936
  }
7049
6937
  let drift = "ok";
7050
6938
  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";
6939
+ else if (!fs10.existsSync(entry.nodeBin)) drift = "stale-node-bin";
6940
+ else if (!fs10.existsSync(entry.cliBin)) drift = "stale-cli-bin";
7053
6941
  return { entry, logExists, logSize, logTail, lastRunAt, drift };
7054
6942
  });
7055
6943
  }
@@ -7322,11 +7210,11 @@ function isNoise(s) {
7322
7210
  if (/^-?\d+(\.\d+)?([eE][-+]?\d+)?$/.test(s)) return true;
7323
7211
  return false;
7324
7212
  }
7325
- function recordSample(stats, path13, value, jsType, recordIndex, totalSamples) {
7326
- let s = stats.get(path13);
7213
+ function recordSample(stats, path12, value, jsType, recordIndex, totalSamples) {
7214
+ let s = stats.get(path12);
7327
7215
  if (!s) {
7328
7216
  s = {
7329
- path: path13,
7217
+ path: path12,
7330
7218
  total: totalSamples,
7331
7219
  recordIndices: /* @__PURE__ */ new Set(),
7332
7220
  lenSum: 0,
@@ -7335,7 +7223,7 @@ function recordSample(stats, path13, value, jsType, recordIndex, totalSamples) {
7335
7223
  primaryType: jsType,
7336
7224
  examples: []
7337
7225
  };
7338
- stats.set(path13, s);
7226
+ stats.set(path12, s);
7339
7227
  }
7340
7228
  s.recordIndices.add(recordIndex);
7341
7229
  s.lenSum += value.length;
@@ -7344,28 +7232,28 @@ function recordSample(stats, path13, value, jsType, recordIndex, totalSamples) {
7344
7232
  if (s.primaryType !== jsType) s.primaryType = "mixed";
7345
7233
  if (s.examples.length < 3 && value.length < 200) s.examples.push(value);
7346
7234
  }
7347
- function walkRecord(record, path13, stats, recordIndex, totalSamples) {
7235
+ function walkRecord(record, path12, stats, recordIndex, totalSamples) {
7348
7236
  if (record === null || record === void 0) return;
7349
7237
  if (typeof record === "string") {
7350
7238
  const trimmed = record.trim();
7351
- if (trimmed) recordSample(stats, path13, trimmed, "string", recordIndex, totalSamples);
7239
+ if (trimmed) recordSample(stats, path12, trimmed, "string", recordIndex, totalSamples);
7352
7240
  return;
7353
7241
  }
7354
7242
  if (typeof record === "number" || typeof record === "boolean") {
7355
7243
  const str = String(record);
7356
7244
  const kind = typeof record === "number" ? "number" : "boolean";
7357
- if (str) recordSample(stats, path13, str, kind, recordIndex, totalSamples);
7245
+ if (str) recordSample(stats, path12, str, kind, recordIndex, totalSamples);
7358
7246
  return;
7359
7247
  }
7360
7248
  if (Array.isArray(record)) {
7361
- const childPath = path13 ? `${path13}[]` : "[]";
7249
+ const childPath = path12 ? `${path12}[]` : "[]";
7362
7250
  for (const item of record) walkRecord(item, childPath, stats, recordIndex, totalSamples);
7363
7251
  return;
7364
7252
  }
7365
7253
  if (typeof record === "object") {
7366
7254
  for (const [key, value] of Object.entries(record)) {
7367
7255
  if (key.startsWith("_")) continue;
7368
- const childPath = path13 ? `${path13}.${key}` : key;
7256
+ const childPath = path12 ? `${path12}.${key}` : key;
7369
7257
  walkRecord(value, childPath, stats, recordIndex, totalSamples);
7370
7258
  }
7371
7259
  }
@@ -7574,8 +7462,8 @@ async function syncInitCommand(platform, model, options) {
7574
7462
  }
7575
7463
  if (actionId && !builtin) {
7576
7464
  try {
7577
- const knowledgeResp = await api.getActionKnowledge(actionId);
7578
- inferred = inferProfileFromKnowledge(knowledgeResp?.knowledge, model, platform);
7465
+ const { details } = await resolveActionDetails(api, actionId);
7466
+ inferred = inferProfileFromKnowledge(details.knowledge, model, platform);
7579
7467
  if (inferred.pagination) template.pagination = inferred.pagination;
7580
7468
  if (inferred.resultsPath) template.resultsPath = inferred.resultsPath;
7581
7469
  if (inferred.idField) template.idField = inferred.idField;
@@ -7771,7 +7659,7 @@ function buildSearchablePreview(profile, samples) {
7771
7659
  const first = samples[0];
7772
7660
  const paths = getSearchablePaths(profile);
7773
7661
  if (paths) {
7774
- const perPathAgg = paths.map((path13) => ({ path: path13, hits: 0, total: samples.length, sample: "" }));
7662
+ const perPathAgg = paths.map((path12) => ({ path: path12, hits: 0, total: samples.length, sample: "" }));
7775
7663
  for (const record of samples) {
7776
7664
  const { paths: perPath } = extractSearchableFromPaths(record, paths);
7777
7665
  perPath.forEach((p10, i) => {
@@ -7900,7 +7788,7 @@ ${result.total} results`);
7900
7788
  }
7901
7789
  }
7902
7790
  async function syncSqlCommand(platformModel, sql) {
7903
- const { syncSqlCommand: runSyncSql } = await import("./sql-V44IVBHX.js");
7791
+ const { syncSqlCommand: runSyncSql } = await import("./sql-ZABEXIXW.js");
7904
7792
  await runSyncSql(platformModel, sql);
7905
7793
  }
7906
7794
  async function syncDeleteCommand(platformModel, options) {
@@ -7978,7 +7866,7 @@ async function syncDeleteCommand(platformModel, options) {
7978
7866
  async function maybeAutoMigrateLegacy(platform, models) {
7979
7867
  const dbSize = getDatabaseSize(platform);
7980
7868
  if (!dbSize || dbSize === "0 B") return;
7981
- const { getBackend: getBackend2 } = await import("./runtime-RVXAPQAZ.js");
7869
+ const { getBackend: getBackend2 } = await import("./runtime-3NDWRLXL.js");
7982
7870
  const backend = await getBackend2();
7983
7871
  let memoryHasData = false;
7984
7872
  for (const model of models) {
@@ -7994,7 +7882,7 @@ async function maybeAutoMigrateLegacy(platform, models) {
7994
7882
  ` detected legacy .one/sync/data/${platform}.db (${dbSize}) \u2014 auto-migrating into memory before sync.
7995
7883
  `
7996
7884
  );
7997
- const { memMigrateCommand: memMigrateCommand3 } = await import("./migrate-J2ZRDEFB.js");
7885
+ const { memMigrateCommand: memMigrateCommand3 } = await import("./migrate-VV3VOXWJ.js");
7998
7886
  await memMigrateCommand3({ platform, yes: true });
7999
7887
  return;
8000
7888
  }
@@ -8003,7 +7891,7 @@ async function maybeAutoMigrateLegacy(platform, models) {
8003
7891
  initialValue: true
8004
7892
  });
8005
7893
  if (p7.isCancel(shouldMigrate) || !shouldMigrate) return;
8006
- const { memMigrateCommand: memMigrateCommand2 } = await import("./migrate-J2ZRDEFB.js");
7894
+ const { memMigrateCommand: memMigrateCommand2 } = await import("./migrate-VV3VOXWJ.js");
8007
7895
  await memMigrateCommand2({ platform, yes: true });
8008
7896
  }
8009
7897
  async function syncSuggestSearchableCommand(platformModel, options = {}) {
@@ -8064,7 +7952,7 @@ async function syncSuggestSearchableCommand(platformModel, options = {}) {
8064
7952
  async function syncListCommand(platform) {
8065
7953
  const profiles = listProfiles(platform);
8066
7954
  const state = await readSyncState();
8067
- const { getBackend: getBackend2 } = await import("./runtime-RVXAPQAZ.js");
7955
+ const { getBackend: getBackend2 } = await import("./runtime-3NDWRLXL.js");
8068
7956
  const backend = await getBackend2();
8069
7957
  const syncs = await Promise.all(profiles.map(async (p10) => {
8070
7958
  const modelState = state[p10.platform]?.[p10.model];
@@ -8702,16 +8590,16 @@ function projectEmbeddingApiKey(cfg) {
8702
8590
  }
8703
8591
  function redactSecrets(cfg) {
8704
8592
  const copy = JSON.parse(JSON.stringify(cfg));
8705
- for (const path13 of SECRET_PATHS) {
8706
- const val = getPath(copy, path13);
8593
+ for (const path12 of SECRET_PATHS) {
8594
+ const val = getPath(copy, path12);
8707
8595
  if (typeof val === "string" && val.length > 0) {
8708
- setPath(copy, path13, `${val.slice(0, 6)}\u2026(redacted, use --show-secrets)`);
8596
+ setPath(copy, path12, `${val.slice(0, 6)}\u2026(redacted, use --show-secrets)`);
8709
8597
  }
8710
8598
  }
8711
8599
  return copy;
8712
8600
  }
8713
- function getPath(obj, path13) {
8714
- const parts = path13.split(".");
8601
+ function getPath(obj, path12) {
8602
+ const parts = path12.split(".");
8715
8603
  let cur = obj;
8716
8604
  for (const part of parts) {
8717
8605
  if (cur == null || typeof cur !== "object") return void 0;
@@ -8719,8 +8607,8 @@ function getPath(obj, path13) {
8719
8607
  }
8720
8608
  return cur;
8721
8609
  }
8722
- function setPath(obj, path13, value) {
8723
- const parts = path13.split(".");
8610
+ function setPath(obj, path12, value) {
8611
+ const parts = path12.split(".");
8724
8612
  let cur = obj;
8725
8613
  for (let i = 0; i < parts.length - 1; i++) {
8726
8614
  const part = parts[i];
@@ -8730,8 +8618,8 @@ function setPath(obj, path13, value) {
8730
8618
  cur[parts[parts.length - 1]] = value;
8731
8619
  return obj;
8732
8620
  }
8733
- function unsetPath(obj, path13) {
8734
- const parts = path13.split(".");
8621
+ function unsetPath(obj, path12) {
8622
+ const parts = path12.split(".");
8735
8623
  let cur = obj;
8736
8624
  for (let i = 0; i < parts.length - 1; i++) {
8737
8625
  const part = parts[i];
@@ -8982,7 +8870,7 @@ async function memDoctorCommand() {
8982
8870
  }
8983
8871
  if (cfg.embedding.provider === "openai") {
8984
8872
  try {
8985
- const { embed: embed2 } = await import("./embedding-GZGDGIUA.js");
8873
+ const { embed: embed2 } = await import("./embedding-C3E4EAQ7.js");
8986
8874
  const result = await embed2("connectivity check");
8987
8875
  checks.push({
8988
8876
  name: "OpenAI embedding provider reachable",
@@ -9040,7 +8928,7 @@ ${pc10.dim(line)}`);
9040
8928
  }
9041
8929
 
9042
8930
  // src/commands/mem/export.ts
9043
- import fs12 from "fs";
8931
+ import fs11 from "fs";
9044
8932
  async function memExportCommand(outfile) {
9045
8933
  requireMemoryInit();
9046
8934
  const backend = await getBackend();
@@ -9073,14 +8961,14 @@ async function memExportCommand(outfile) {
9073
8961
  }
9074
8962
  return;
9075
8963
  }
9076
- fs12.writeFileSync(outfile, lines, "utf-8");
8964
+ fs11.writeFileSync(outfile, lines, "utf-8");
9077
8965
  okJson({ status: "ok", file: outfile, recordsWritten: records.length, storeTotal: stats.recordCount });
9078
8966
  }
9079
8967
  async function memImportCommand(file) {
9080
8968
  requireMemoryInit();
9081
- if (!fs12.existsSync(file)) error(`File not found: ${file}`);
8969
+ if (!fs11.existsSync(file)) error(`File not found: ${file}`);
9082
8970
  const backend = await getBackend();
9083
- const raw = fs12.readFileSync(file, "utf-8");
8971
+ const raw = fs11.readFileSync(file, "utf-8");
9084
8972
  const lines = raw.split("\n").filter((l) => l.trim().length > 0);
9085
8973
  let inserted = 0;
9086
8974
  let updated = 0;
@@ -9327,6 +9215,9 @@ async function cacheUpdateAllCommand() {
9327
9215
  error("Not configured. Run `one init` first.");
9328
9216
  }
9329
9217
  const api = new OneApi(apiKey, getApiBase());
9218
+ const ac = getAccessControlFromAllSources();
9219
+ const permissions = ac.permissions || "admin";
9220
+ const actionIds = ac.actionIds || ["*"];
9330
9221
  const entries = listCacheEntries();
9331
9222
  if (entries.length === 0) {
9332
9223
  if (isAgentMode()) {
@@ -9344,13 +9235,41 @@ async function cacheUpdateAllCommand() {
9344
9235
  for (const e of entries) {
9345
9236
  try {
9346
9237
  if (e.type === "knowledge") {
9347
- const result = await api.getActionKnowledgeWithMeta(e.entry.key);
9238
+ const result = await api.getActionDetailsWithMeta(e.entry.key);
9348
9239
  const newEntry = makeCacheEntry(e.entry.key, result.data, result.etag);
9349
- writeCache2(e.filePath, newEntry);
9240
+ writeCache(e.filePath, newEntry);
9350
9241
  updated++;
9351
9242
  } else {
9352
- const refreshed = { ...e.entry, cachedAt: (/* @__PURE__ */ new Date()).toISOString() };
9353
- writeCache2(e.filePath, refreshed);
9243
+ const data = e.entry.data;
9244
+ if (data?.platform && data?.query) {
9245
+ const searchType = data.searchType ?? "knowledge";
9246
+ const result = await api.searchActionsWithMeta(
9247
+ data.platform,
9248
+ data.query,
9249
+ searchType,
9250
+ e.entry.etag ?? void 0
9251
+ );
9252
+ if (result.status === 304) {
9253
+ writeCache(e.filePath, { ...e.entry, cachedAt: (/* @__PURE__ */ new Date()).toISOString() });
9254
+ } else {
9255
+ let actions2 = result.data;
9256
+ actions2 = filterByPermissions(actions2, permissions);
9257
+ actions2 = actions2.filter((a) => isActionAllowed(a.systemId, actionIds));
9258
+ const cleaned = actions2.map((a) => ({
9259
+ actionId: a.systemId,
9260
+ title: a.title,
9261
+ method: a.method,
9262
+ path: a.path
9263
+ }));
9264
+ writeCache(e.filePath, makeCacheEntry(
9265
+ e.entry.key,
9266
+ { actions: cleaned, platform: data.platform, query: data.query, searchType },
9267
+ result.etag
9268
+ ));
9269
+ }
9270
+ } else {
9271
+ writeCache(e.filePath, { ...e.entry, cachedAt: (/* @__PURE__ */ new Date()).toISOString() });
9272
+ }
9354
9273
  updated++;
9355
9274
  }
9356
9275
  } catch (err) {
@@ -9436,6 +9355,7 @@ one --agent actions execute <platform> <actionId> <key> -d '{}' # Execute it
9436
9355
  - \`--mock\` \u2014 Return example response without making an API call (useful for building UI against a response shape)
9437
9356
  - \`--skip-validation\` \u2014 Skip input validation against the action schema
9438
9357
  - \`--output <path>\` \u2014 Save response to a file (for binary downloads like PDFs, images, documents)
9358
+ - \`--no-cache\` \u2014 Bypass the cached action details and re-fetch them; the fresh details still refresh the cache (execution itself is never cached)
9439
9359
 
9440
9360
  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
9361
 
@@ -9561,6 +9481,9 @@ one --agent actions execute <platform> <actionId> <connectionKey> [options]
9561
9481
  - \`--mock\` \u2014 Return example response without making an API call
9562
9482
  - \`--skip-validation\` \u2014 Skip input validation against the action schema
9563
9483
  - \`--output <path>\` \u2014 Save response to a file (for binary downloads like PDFs, images, documents)
9484
+ - \`--no-cache\` \u2014 Bypass the cached action details and re-fetch them; the fresh details still refresh the cache (execution itself is never cached)
9485
+
9486
+ 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
9487
 
9565
9488
  **Do NOT** pass path or query parameters in \`-d\`. Use the correct flags.
9566
9489
 
@@ -9575,13 +9498,13 @@ one --agent actions execute --parallel \\
9575
9498
  -- google-sheets append-row conn789 -d '{"values":["x"]}'
9576
9499
  \`\`\`
9577
9500
 
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.
9501
+ 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
9502
 
9580
9503
  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
9504
 
9582
- Agent-mode output:
9505
+ Agent-mode output (each result carries its own \`_preflight\` showing whether that action's details were served from cache):
9583
9506
  \`\`\`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":{...}}]}
9507
+ {"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
9508
  \`\`\`
9586
9509
 
9587
9510
  ## Input Validation
@@ -9714,7 +9637,7 @@ var GUIDE_CACHE = `# One Cache \u2014 Reference
9714
9637
 
9715
9638
  ## Overview
9716
9639
 
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.
9640
+ 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
9641
 
9719
9642
  Cache location: \`~/.one/cache/knowledge/\` and \`~/.one/cache/search/\`
9720
9643
 
@@ -9724,6 +9647,7 @@ Cache location: \`~/.one/cache/knowledge/\` and \`~/.one/cache/search/\`
9724
9647
  - **Subsequent calls (within TTL)**: serves from cache instantly, no API call
9725
9648
  - **After TTL expires**: makes a conditional request (ETag). If content unchanged, refreshes the cache timestamp. If changed, writes fresh data.
9726
9649
  - **Network failure with stale cache**: serves the stale cache with a warning \u2014 never fails hard when a cache exists
9650
+ - **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
9651
 
9728
9652
  Default TTL: 3600 seconds (1 hour). Configure via \`ONE_CACHE_TTL\` env var or \`cacheTtl\` in \`~/.one/config.json\`.
9729
9653
 
@@ -9731,8 +9655,9 @@ Default TTL: 3600 seconds (1 hour). Configure via \`ONE_CACHE_TTL\` env var or \
9731
9655
 
9732
9656
  | Cached | Not Cached |
9733
9657
  |--------|-----------|
9734
- | \`actions knowledge\` (API docs, change infrequently) | \`actions execute\` (live data, always fresh) |
9658
+ | \`actions knowledge\` (API docs, change infrequently) | \`actions execute\` responses (live data, always fresh) |
9735
9659
  | \`actions search\` results | \`connection list\` (changes with add/remove) |
9660
+ | Action details used by execute / flow / sync preflight (method, path, schema) | |
9736
9661
 
9737
9662
  ## Agent Mode \`_cache\` Metadata
9738
9663
 
@@ -9763,8 +9688,13 @@ one --agent actions knowledge <platform> <actionId> --cache-status
9763
9688
 
9764
9689
  # Same for search
9765
9690
  one --agent actions search <platform> "<query>" --no-cache
9691
+
9692
+ # Same for execute's action-details preflight (the action itself always runs live)
9693
+ one --agent actions execute <platform> <actionId> <key> --no-cache
9766
9694
  \`\`\`
9767
9695
 
9696
+ In \`--agent\` mode, execute responses include \`"_preflight": {"cache": "hit"|"miss"}\` showing whether the action details came from disk.
9697
+
9768
9698
  ## Cache Management Commands
9769
9699
 
9770
9700
  \`\`\`bash
@@ -10676,7 +10606,7 @@ function buildWorkflowIdeas(connections) {
10676
10606
  }
10677
10607
 
10678
10608
  // src/commands/logout.ts
10679
- import fs13 from "fs";
10609
+ import fs12 from "fs";
10680
10610
  import * as p9 from "@clack/prompts";
10681
10611
  function formatWhoami(config2, apiKey, pc13) {
10682
10612
  const whoami = config2.whoami;
@@ -10709,12 +10639,12 @@ async function logoutCommand() {
10709
10639
  const globalPath = getGlobalConfigPath();
10710
10640
  const projectPath = getProjectConfigPath();
10711
10641
  let cleared = false;
10712
- if (fs13.existsSync(projectPath)) {
10713
- fs13.unlinkSync(projectPath);
10642
+ if (fs12.existsSync(projectPath)) {
10643
+ fs12.unlinkSync(projectPath);
10714
10644
  cleared = true;
10715
10645
  }
10716
- if (fs13.existsSync(globalPath)) {
10717
- fs13.unlinkSync(globalPath);
10646
+ if (fs12.existsSync(globalPath)) {
10647
+ fs12.unlinkSync(globalPath);
10718
10648
  cleared = true;
10719
10649
  }
10720
10650
  json({ status: cleared ? "logged_out" : "not_logged_in", message: cleared ? "Credentials cleared." : "No config found." });
@@ -10783,11 +10713,11 @@ async function logoutCommand() {
10783
10713
  }
10784
10714
  if (targetScope === "project" || targetScope === "both") {
10785
10715
  const projectPath = getProjectConfigPath();
10786
- if (fs13.existsSync(projectPath)) fs13.unlinkSync(projectPath);
10716
+ if (fs12.existsSync(projectPath)) fs12.unlinkSync(projectPath);
10787
10717
  }
10788
10718
  if (targetScope === "global" || targetScope === "both") {
10789
10719
  const globalPath = getGlobalConfigPath();
10790
- if (fs13.existsSync(globalPath)) fs13.unlinkSync(globalPath);
10720
+ if (fs12.existsSync(globalPath)) fs12.unlinkSync(globalPath);
10791
10721
  }
10792
10722
  p9.log.success("Credentials cleared.");
10793
10723
  p9.log.info("Your API key is still active. Manage keys at app.withone.ai/settings");
@@ -11005,8 +10935,8 @@ config.command("reset").description("Remove the project config for the current d
11005
10935
  return;
11006
10936
  }
11007
10937
  }
11008
- const fs15 = await import("fs");
11009
- fs15.unlinkSync(globalPath);
10938
+ const fs14 = await import("fs");
10939
+ fs14.unlinkSync(globalPath);
11010
10940
  if (isAgentMode()) {
11011
10941
  json({ deleted: true, scope: "global" });
11012
10942
  } else {
@@ -11023,15 +10953,15 @@ config.command("reset").description("Remove the project config for the current d
11023
10953
  }
11024
10954
  return;
11025
10955
  }
11026
- const fs14 = await import("fs");
11027
- const configContent = fs14.readFileSync(resolved.path, "utf-8");
11028
- fs14.unlinkSync(resolved.path);
10956
+ const fs13 = await import("fs");
10957
+ const configContent = fs13.readFileSync(resolved.path, "utf-8");
10958
+ fs13.unlinkSync(resolved.path);
11029
10959
  const next = resolveConfig();
11030
- fs14.mkdirSync(path12.dirname(resolved.path), { recursive: true });
11031
- fs14.writeFileSync(resolved.path, configContent);
10960
+ fs13.mkdirSync(path11.dirname(resolved.path), { recursive: true });
10961
+ fs13.writeFileSync(resolved.path, configContent);
11032
10962
  let fallbackLabel;
11033
10963
  if (next.scope === "project") {
11034
- fallbackLabel = `parent project config (${path12.basename(next.projectRoot)})`;
10964
+ fallbackLabel = `parent project config (${path11.basename(next.projectRoot)})`;
11035
10965
  } else if (next.scope === "global") {
11036
10966
  fallbackLabel = "global config";
11037
10967
  } else {
@@ -11040,7 +10970,7 @@ config.command("reset").description("Remove the project config for the current d
11040
10970
  if (!isAgentMode()) {
11041
10971
  const p10 = await import("@clack/prompts");
11042
10972
  const confirmed = await p10.confirm({
11043
- message: `Delete project config for ${path12.basename(resolved.projectRoot)}? Will fall back to ${fallbackLabel}.`,
10973
+ message: `Delete project config for ${path11.basename(resolved.projectRoot)}? Will fall back to ${fallbackLabel}.`,
11044
10974
  initialValue: false
11045
10975
  });
11046
10976
  if (p10.isCancel(confirmed) || !confirmed) {
@@ -11048,9 +10978,9 @@ config.command("reset").description("Remove the project config for the current d
11048
10978
  return;
11049
10979
  }
11050
10980
  }
11051
- fs14.unlinkSync(resolved.path);
10981
+ fs13.unlinkSync(resolved.path);
11052
10982
  try {
11053
- fs14.rmdirSync(path12.dirname(resolved.path));
10983
+ fs13.rmdirSync(path11.dirname(resolved.path));
11054
10984
  } catch {
11055
10985
  }
11056
10986
  if (isAgentMode()) {
@@ -11073,13 +11003,13 @@ program.command("platforms").alias("p").description("List available platforms").
11073
11003
  await platformsCommand(options);
11074
11004
  });
11075
11005
  var actions = program.command("actions").alias("a").description("Search, explore, and execute platform actions (workflow: search \u2192 knowledge \u2192 execute)");
11076
- actions.command("search <platform> <query>").description('Search for actions on a platform (e.g. one actions search gmail "send email")').option("-t, --type <type>", "execute (to run it) or knowledge (to learn about it). Default: knowledge").option("--no-cache", "Skip cache, fetch fresh from API").action(async (platform, query, options) => {
11006
+ actions.command("search <platform> <query>").description('Search for actions on a platform (e.g. one actions search gmail "send email")').option("-t, --type <type>", "execute (to run it) or knowledge (to learn about it). Default: knowledge").option("--no-cache", "Bypass the cache and re-fetch from the API (the fresh response still refreshes the cache)").action(async (platform, query, options) => {
11077
11007
  await actionsSearchCommand(platform, query, options);
11078
11008
  });
11079
- 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) => {
11009
+ 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", "Bypass the cache and re-fetch from the API (the fresh response still refreshes the cache)").option("--cache-status", "Print cache metadata without fetching").action(async (platform, actionId, options) => {
11080
11010
  await actionsKnowledgeCommand(platform, actionId, options);
11081
11011
  });
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) => {
11012
+ 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", "Bypass the cached action details and re-fetch them (the fresh details still refresh the 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
11013
  if (options.parallel) {
11084
11014
  await actionsExecuteParallelCommand();
11085
11015
  return;
@@ -11097,7 +11027,8 @@ actions.command("execute [platform] [actionId] [connectionKey]").alias("x").allo
11097
11027
  dryRun: options.dryRun,
11098
11028
  mock: options.mock,
11099
11029
  skipValidation: options.skipValidation,
11100
- output: options.output
11030
+ output: options.output,
11031
+ cache: options.cache
11101
11032
  });
11102
11033
  });
11103
11034
  var flow = program.command("flow").alias("f").description("Create, execute, and manage multi-step workflows");