@withone/cli 1.45.0 → 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/README.md CHANGED
@@ -268,7 +268,7 @@ one actions execute stripe <actionId> <connectionKey> \
268
268
  | `--mock` | Return example response without making an API call |
269
269
  | `--skip-validation` | Skip input validation against the action schema |
270
270
  | `--output <path>` | Save response to a file (for binary downloads) |
271
- | `--no-cache` | Fetch action details fresh instead of from the local cache (execution itself is never cached) |
271
+ | `--no-cache` | Bypass the cached action details and re-fetch them; the fresh details still refresh the cache (execution itself is never cached) |
272
272
 
273
273
  The CLI validates required parameters (path variables, query params, body fields) against the action schema before executing. Missing params return a clear error with the flag name and description. Pass `--skip-validation` to bypass.
274
274
 
@@ -672,29 +672,32 @@ function isActionDetailsEntry(entry) {
672
672
  }
673
673
  async function resolveActionDetails(api, actionId, opts = {}) {
674
674
  const useCache = opts.useCache !== false;
675
+ const warn = opts.warn ?? ((m) => {
676
+ process.stderr.write(m);
677
+ });
675
678
  const cachePath = knowledgeCachePath(actionId);
676
679
  const raw = useCache ? readCache(cachePath) : null;
677
680
  const cached = isActionDetailsEntry(raw) ? raw : null;
678
681
  if (cached && isFresh(cached)) {
679
- return { details: cached.data, cacheHit: true, entry: cached };
682
+ return { details: cached.data, cacheHit: true, stale: false, entry: cached };
680
683
  }
681
684
  try {
682
685
  const result = await api.getActionDetailsWithMeta(actionId, cached?.etag ?? void 0);
683
686
  if (result.status === 304 && cached) {
684
687
  cached.cachedAt = (/* @__PURE__ */ new Date()).toISOString();
685
688
  writeCache(cachePath, cached);
686
- return { details: cached.data, cacheHit: true, entry: cached };
689
+ return { details: cached.data, cacheHit: true, stale: false, entry: cached };
687
690
  }
688
691
  const entry = makeCacheEntry(actionId, result.data, result.etag);
689
692
  writeCache(cachePath, entry);
690
- return { details: result.data, cacheHit: false, entry };
693
+ return { details: result.data, cacheHit: false, stale: false, entry };
691
694
  } catch (fetchError) {
692
695
  if (cached) {
693
- process.stderr.write(
696
+ warn(
694
697
  `Warning: serving cached action details (network unavailable, cached ${formatAge(getAge(cached))} ago)
695
698
  `
696
699
  );
697
- return { details: cached.data, cacheHit: true, entry: cached };
700
+ return { details: cached.data, cacheHit: true, stale: true, entry: cached };
698
701
  }
699
702
  throw fetchError;
700
703
  }
@@ -1268,7 +1271,7 @@ async function executeSubflowStep(step, context, api, permissions, allowedAction
1268
1271
  if (flowStack.includes(resolvedKey)) {
1269
1272
  throw new Error(`Circular flow detected: ${[...flowStack, resolvedKey].join(" \u2192 ")}`);
1270
1273
  }
1271
- const { loadFlowWithMeta: loadFlowWithMeta2 } = await import("./flow-runner-FQVTF36N.js");
1274
+ const { loadFlowWithMeta: loadFlowWithMeta2 } = await import("./flow-runner-6KN2ZVXB.js");
1272
1275
  const { flow: subFlow, rootDir: subRootDir } = loadFlowWithMeta2(resolvedKey);
1273
1276
  const subContext = await executeFlow(
1274
1277
  subFlow,
@@ -11,7 +11,7 @@ import {
11
11
  saveFlow,
12
12
  summarizeFlowInputs,
13
13
  walkSteps
14
- } from "./chunk-UXKF6AEG.js";
14
+ } from "./chunk-DZK56R5R.js";
15
15
  import "./chunk-44CV5IMX.js";
16
16
  import "./chunk-TVIZC7AC.js";
17
17
  export {
package/dist/index.js CHANGED
@@ -30,7 +30,7 @@ import {
30
30
  searchCachePath,
31
31
  validateActionInput,
32
32
  writeCache
33
- } from "./chunk-UXKF6AEG.js";
33
+ } from "./chunk-DZK56R5R.js";
34
34
  import {
35
35
  memSqlCommand
36
36
  } from "./chunk-TLRJMJGU.js";
@@ -2382,7 +2382,8 @@ async function actionsSearchCommand(platform, query, options) {
2382
2382
  try {
2383
2383
  const agentType = knowledgeAgent ? "knowledge" : options.type || "execute";
2384
2384
  const useCache = options.cache !== false;
2385
- const cachePath = searchCachePath(platform, query, agentType || "knowledge");
2385
+ const searchType = agentType || "knowledge";
2386
+ const cachePath = searchCachePath(platform, query, searchType);
2386
2387
  const cached = useCache ? readCache(cachePath) : null;
2387
2388
  let cleanedActions;
2388
2389
  let cacheHit = false;
@@ -2413,8 +2414,8 @@ async function actionsSearchCommand(platform, query, options) {
2413
2414
  path: action.path
2414
2415
  }));
2415
2416
  writeCache(cachePath, makeCacheEntry(
2416
- `${platform}_${query}_${agentType || "knowledge"}`,
2417
- { actions: cleanedActions },
2417
+ `${platform}_${query}_${searchType}`,
2418
+ { actions: cleanedActions, platform, query, searchType },
2418
2419
  result.etag
2419
2420
  ));
2420
2421
  }
@@ -2596,7 +2597,7 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
2596
2597
  }
2597
2598
  const api = new OneApi(apiKey, getApiBase());
2598
2599
  const spinner5 = createSpinner();
2599
- spinner5.start("Loading action details...");
2600
+ spinner5.start("Resolving action details...");
2600
2601
  try {
2601
2602
  const { details: actionDetails, cacheHit: preflightCacheHit } = await resolveActionDetails(api, actionId, { useCache: options.cache !== false });
2602
2603
  if (!isMethodAllowed(actionDetails.method, permissions)) {
@@ -2605,7 +2606,9 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
2605
2606
  `Method "${actionDetails.method}" is not allowed under "${permissions}" permission level.`
2606
2607
  );
2607
2608
  }
2608
- spinner5.stop(`Action: ${actionDetails.title} [${actionDetails.method}]`);
2609
+ spinner5.stop(
2610
+ `Action: ${actionDetails.title} [${actionDetails.method}]` + (preflightCacheHit ? pc6.dim(" (cached)") : "")
2611
+ );
2609
2612
  const data = options.data ? parseJsonArg2(options.data, "--data") : void 0;
2610
2613
  const pathVariables = options.pathVars ? parseJsonArg2(options.pathVars, "--path-vars") : void 0;
2611
2614
  const queryParams = options.queryParams ? parseJsonArg2(options.queryParams, "--query-params") : void 0;
@@ -2830,6 +2833,7 @@ async function actionsExecuteParallelCommand() {
2830
2833
  const api = new OneApi(apiKey, getApiBase());
2831
2834
  const prepared = [];
2832
2835
  const errors = [];
2836
+ const staleWarned = /* @__PURE__ */ new Set();
2833
2837
  for (let i = 0; i < segments.length; i++) {
2834
2838
  const seg = segments[i];
2835
2839
  const label = `${seg.platform}/${seg.actionId}`;
@@ -2843,7 +2847,14 @@ async function actionsExecuteParallelCommand() {
2843
2847
  let actionDetails;
2844
2848
  let preflightCacheHit = false;
2845
2849
  try {
2846
- const resolved = await resolveActionDetails(api, seg.actionId, { useCache: flags.useCache });
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
+ });
2847
2858
  actionDetails = resolved.details;
2848
2859
  preflightCacheHit = resolved.cacheHit;
2849
2860
  } catch (err) {
@@ -9204,6 +9215,9 @@ async function cacheUpdateAllCommand() {
9204
9215
  error("Not configured. Run `one init` first.");
9205
9216
  }
9206
9217
  const api = new OneApi(apiKey, getApiBase());
9218
+ const ac = getAccessControlFromAllSources();
9219
+ const permissions = ac.permissions || "admin";
9220
+ const actionIds = ac.actionIds || ["*"];
9207
9221
  const entries = listCacheEntries();
9208
9222
  if (entries.length === 0) {
9209
9223
  if (isAgentMode()) {
@@ -9226,8 +9240,36 @@ async function cacheUpdateAllCommand() {
9226
9240
  writeCache(e.filePath, newEntry);
9227
9241
  updated++;
9228
9242
  } else {
9229
- const refreshed = { ...e.entry, cachedAt: (/* @__PURE__ */ new Date()).toISOString() };
9230
- writeCache(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
+ }
9231
9273
  updated++;
9232
9274
  }
9233
9275
  } catch (err) {
@@ -9313,7 +9355,7 @@ one --agent actions execute <platform> <actionId> <key> -d '{}' # Execute it
9313
9355
  - \`--mock\` \u2014 Return example response without making an API call (useful for building UI against a response shape)
9314
9356
  - \`--skip-validation\` \u2014 Skip input validation against the action schema
9315
9357
  - \`--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)
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)
9317
9359
 
9318
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.
9319
9361
 
@@ -9439,7 +9481,7 @@ one --agent actions execute <platform> <actionId> <connectionKey> [options]
9439
9481
  - \`--mock\` \u2014 Return example response without making an API call
9440
9482
  - \`--skip-validation\` \u2014 Skip input validation against the action schema
9441
9483
  - \`--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)
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)
9443
9485
 
9444
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.
9445
9487
 
@@ -10961,13 +11003,13 @@ program.command("platforms").alias("p").description("List available platforms").
10961
11003
  await platformsCommand(options);
10962
11004
  });
10963
11005
  var actions = program.command("actions").alias("a").description("Search, explore, and execute platform actions (workflow: search \u2192 knowledge \u2192 execute)");
10964
- 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) => {
10965
11007
  await actionsSearchCommand(platform, query, options);
10966
11008
  });
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) => {
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) => {
10968
11010
  await actionsKnowledgeCommand(platform, actionId, options);
10969
11011
  });
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) => {
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) => {
10971
11013
  if (options.parallel) {
10972
11014
  await actionsExecuteParallelCommand();
10973
11015
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@withone/cli",
3
- "version": "1.45.0",
3
+ "version": "1.45.1",
4
4
  "description": "CLI for managing One",
5
5
  "type": "module",
6
6
  "files": [
@@ -90,7 +90,7 @@ Options:
90
90
  - `--mock` — Return example response without making an API call (useful for building UI)
91
91
  - `--skip-validation` — Skip input validation against the action schema
92
92
  - `--output <path>` — Save response to a file (for binary downloads like PDFs, images, documents)
93
- - `--no-cache` — Fetch action details fresh instead of from the local cache (execution itself is never cached)
93
+ - `--no-cache` — Bypass the cached action details and re-fetch them; the fresh details still refresh the cache (execution itself is never cached)
94
94
 
95
95
  The CLI validates required parameters before executing. Missing params return a structured error with the flag name, parameter name, and description. Pass `--skip-validation` to bypass.
96
96