@withone/cli 1.57.1 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -5,11 +5,8 @@ import {
5
5
  OneApi,
6
6
  PERMISSION_METHODS,
7
7
  TimeoutError,
8
- buildActionKnowledgeWithGuidance,
9
- buildCacheMeta,
10
8
  clearAll,
11
9
  clearEntry,
12
- filterByPermissions,
13
10
  flowRequiresBash,
14
11
  formatAge,
15
12
  generateFlowGuide,
@@ -28,11 +25,10 @@ import {
28
25
  resolveActionDetails,
29
26
  resolveFlowPath,
30
27
  saveFlow,
31
- searchCachePath,
32
28
  validateActionInput,
33
29
  walkSteps,
34
30
  writeCache
35
- } from "./chunk-QCXFSOTS.js";
31
+ } from "./chunk-6EQDEYVD.js";
36
32
  import {
37
33
  memSqlCommand
38
34
  } from "./chunk-GKAIRI4Y.js";
@@ -165,11 +161,11 @@ import { fileURLToPath as fileURLToPath3 } from "url";
165
161
  import fs from "fs";
166
162
  import path from "path";
167
163
  import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
168
- function expandPath(p10) {
169
- if (p10.startsWith("~/")) {
170
- return path.join(homeDir(), p10.slice(2));
164
+ function expandPath(p9) {
165
+ if (p9.startsWith("~/")) {
166
+ return path.join(homeDir(), p9.slice(2));
171
167
  }
172
- return p10;
168
+ return p9;
173
169
  }
174
170
  function getClaudeDesktopConfigPath() {
175
171
  switch (process.platform) {
@@ -2615,16 +2611,16 @@ function formatAccess(access, maxActions = 2) {
2615
2611
  function findPlatform(platforms, query) {
2616
2612
  const normalizedQuery = query.toLowerCase().trim();
2617
2613
  const exact = platforms.find(
2618
- (p10) => p10.platform.toLowerCase() === normalizedQuery || p10.name.toLowerCase() === normalizedQuery
2614
+ (p9) => p9.platform.toLowerCase() === normalizedQuery || p9.name.toLowerCase() === normalizedQuery
2619
2615
  );
2620
2616
  if (exact) return exact;
2621
2617
  return null;
2622
2618
  }
2623
2619
  function findSimilarPlatforms(platforms, query, limit = 3) {
2624
2620
  const normalizedQuery = query.toLowerCase().trim();
2625
- const scored = platforms.map((p10) => {
2626
- const name = p10.name.toLowerCase();
2627
- const slug = p10.platform.toLowerCase();
2621
+ const scored = platforms.map((p9) => {
2622
+ const name = p9.name.toLowerCase();
2623
+ const slug = p9.platform.toLowerCase();
2628
2624
  let score = 0;
2629
2625
  if (name.includes(normalizedQuery) || slug.includes(normalizedQuery)) {
2630
2626
  score = 10;
@@ -2633,7 +2629,7 @@ function findSimilarPlatforms(platforms, query, limit = 3) {
2633
2629
  } else {
2634
2630
  score = countMatchingChars(normalizedQuery, slug);
2635
2631
  }
2636
- return { platform: p10, score };
2632
+ return { platform: p9, score };
2637
2633
  }).filter((item) => item.score > 0).sort((a, b) => b.score - a.score).slice(0, limit);
2638
2634
  return scored.map((item) => item.platform);
2639
2635
  }
@@ -2991,7 +2987,7 @@ function accessHint(permissions, actionIds, knowledgeOnly) {
2991
2987
  const parts = [];
2992
2988
  if (!actionIds.includes("*")) {
2993
2989
  parts.push(
2994
- "Action-scoped: each connection's `access.actions` are the only actions you may run \u2014 use them directly, no `actions search` needed."
2990
+ "Action-scoped: each connection's `access.actions` are the only actions you may run \u2014 use them directly: `actions load <actionId>` reads their docs, no find needed."
2995
2991
  );
2996
2992
  } else if (permissions !== "admin") {
2997
2993
  const methods = PERMISSION_METHODS[permissions]?.join(", ") ?? "";
@@ -3107,7 +3103,6 @@ async function platformsCommand(options) {
3107
3103
  }
3108
3104
 
3109
3105
  // src/commands/actions.ts
3110
- import * as p6 from "@clack/prompts";
3111
3106
  import pc8 from "picocolors";
3112
3107
 
3113
3108
  // src/lib/knowledge-sections.ts
@@ -3235,7 +3230,7 @@ var ESSENTIAL_PREFIX = ["required "];
3235
3230
  function classifyHeading(heading) {
3236
3231
  const c = canonicalHeading(heading);
3237
3232
  if (ESSENTIAL_EXACT.has(c)) return "essential";
3238
- if (ESSENTIAL_PREFIX.some((p10) => c.startsWith(p10))) return "essential";
3233
+ if (ESSENTIAL_PREFIX.some((p9) => c.startsWith(p9))) return "essential";
3239
3234
  return "deferred";
3240
3235
  }
3241
3236
  function deferredPriority(heading) {
@@ -3248,14 +3243,14 @@ function deferredPriority(heading) {
3248
3243
  if (c === "response" || c.startsWith("success response") || c.startsWith("error response")) return 6;
3249
3244
  return 4;
3250
3245
  }
3251
- function truncateText(text5, cap, id) {
3246
+ function truncateText(text5, cap, id, actionId) {
3252
3247
  const cut = text5.slice(0, cap);
3253
3248
  const nl = cut.lastIndexOf("\n");
3254
3249
  const head = nl > cap * 0.5 ? cut.slice(0, nl) : cut;
3255
3250
  const remaining = text5.length - head.length;
3256
3251
  return `${head}
3257
3252
 
3258
- _[truncated \u2014 ${remaining.toLocaleString("en-US")} more chars. Load the full section with --section ${id}]_`;
3253
+ _[truncated \u2014 ${remaining.toLocaleString("en-US")} more chars. Load the full section with${actionId ? `: one --agent actions load ${actionId} --section ${id}` : ` --section ${id}`}]_`;
3259
3254
  }
3260
3255
  function buildDigest(doc, opts = {}) {
3261
3256
  const wholeThreshold = opts.wholeDocThreshold ?? DEFAULT_WHOLE_DOC_THRESHOLD;
@@ -3279,7 +3274,7 @@ function buildDigest(doc, opts = {}) {
3279
3274
  if (node.tier === "essential" || node.level >= 3 && hasEssentialDescendant(node)) {
3280
3275
  const own = node.text;
3281
3276
  if (own.length > cap) {
3282
- const render = truncateText(own, cap, node.id);
3277
+ const render = truncateText(own, cap, node.id, opts.actionId);
3283
3278
  decisions.set(node.id, { node, included: "partial", render });
3284
3279
  used += render.length;
3285
3280
  } else {
@@ -3333,15 +3328,15 @@ function summary(s, included) {
3333
3328
  return { id: s.id, heading: s.heading, level: s.level, chars: s.chars, included };
3334
3329
  }
3335
3330
  function parentOf(roots, target) {
3336
- const find = (list, parent) => {
3331
+ const find2 = (list, parent) => {
3337
3332
  for (const n of list) {
3338
3333
  if (n === target) return parent;
3339
- const r = find(n.children, n);
3334
+ const r = find2(n.children, n);
3340
3335
  if (r !== void 0) return r;
3341
3336
  }
3342
3337
  return void 0;
3343
3338
  };
3344
- return find(roots, null) ?? null;
3339
+ return find2(roots, null) ?? null;
3345
3340
  }
3346
3341
  function renderWhole(doc) {
3347
3342
  const out = [];
@@ -3373,10 +3368,7 @@ function collapseSections(sections, max = DEFAULT_TOC_MAX_ENTRIES) {
3373
3368
  }
3374
3369
  return { sections, collapsed: false };
3375
3370
  }
3376
- function omittedSections(digest, max = DEFAULT_TOC_MAX_ENTRIES) {
3377
- return collapseSections(digest.sections.filter((s) => s.included !== true), max);
3378
- }
3379
- function renderDigestNotice(digest, platform, actionId) {
3371
+ function renderDigestNotice(digest, actionId) {
3380
3372
  if (!digest.truncated) return "";
3381
3373
  const topMost = digest.sections.filter((s, idx) => {
3382
3374
  if (s.included === true) return false;
@@ -3391,7 +3383,7 @@ function renderDigestNotice(digest, platform, actionId) {
3391
3383
  if (s.level === 1) return `${s.heading} (appendix)`;
3392
3384
  return s.heading;
3393
3385
  });
3394
- const base = `one --agent actions knowledge ${platform} ${actionId}`;
3386
+ const base = `one --agent actions load ${actionId}`;
3395
3387
  const MAX_NAMES = 12;
3396
3388
  const shown = names.slice(0, MAX_NAMES);
3397
3389
  const rest = names.length - shown.length;
@@ -3493,6 +3485,394 @@ function parseSectionFlag(value) {
3493
3485
  return raw.flatMap((v) => v.split(",")).map((v) => v.trim()).filter(Boolean);
3494
3486
  }
3495
3487
 
3488
+ // src/lib/find.ts
3489
+ var FIND_MAX_INTENTS = 10;
3490
+ var FIND_MAX_LOADS = 10;
3491
+ var FIND_DOCUMENTS_BUDGET = 4e5;
3492
+ var NO_KNOWLEDGE = "(No additional knowledge available for this action.)";
3493
+ var REFUSED_LOAD = "no such action, or this CLI may not use it";
3494
+ var EXECUTE_GUIDE = `Run an action with:
3495
+ one --agent actions execute <platform> <actionId> <connectionKey> [--path-vars '{...}'] [--query-params '{...}'] [-d '{...}']
3496
+ Connection keys come from \`one --agent list\`. Put each value where the action's documentation says it goes: path variables (placeholders like {userId}) in --path-vars, query parameters in --query-params, the request body in -d. Never put path variables or query parameters in -d.`;
3497
+ var FindArgsError = class extends Error {
3498
+ };
3499
+ function actionHeading(action) {
3500
+ return `${action.title} \xB7 \`${action.method.toUpperCase()} ${action.path}\` \xB7 actionId: \`${action.actionId}\``;
3501
+ }
3502
+ var ref = (a) => ({ actionId: a.systemId, title: a.title, method: a.method, path: a.path });
3503
+ function allows(settings, action) {
3504
+ return isActionAllowed(action.systemId, settings.actionIds) && isMethodAllowed(action.method, settings.permissions);
3505
+ }
3506
+ async function reachable(settings, deps) {
3507
+ if (settings.connectionKeys.includes("*")) return null;
3508
+ return (await deps.connectedPlatforms()).map((p9) => p9.toLowerCase());
3509
+ }
3510
+ function narrow(answer, settings) {
3511
+ const allowed = (action) => allows(settings, action);
3512
+ const selected = answer.selected.filter(allowed);
3513
+ const alternatives = answer.alternatives.filter(allowed);
3514
+ let alsoSelected = (answer.alsoSelected ?? []).filter(allowed);
3515
+ let runnerUp = answer.runnerUp && allowed(answer.runnerUp) ? answer.runnerUp : void 0;
3516
+ let replaced = false;
3517
+ let pickRefused = false;
3518
+ if (answer.selected.length > 0 && !allowed(answer.selected[0])) {
3519
+ const next = runnerUp ?? alternatives.shift();
3520
+ if (next) {
3521
+ selected.unshift(next);
3522
+ runnerUp = next === runnerUp ? void 0 : runnerUp;
3523
+ replaced = true;
3524
+ } else {
3525
+ alsoSelected = [...selected, ...alsoSelected];
3526
+ selected.length = 0;
3527
+ pickRefused = true;
3528
+ }
3529
+ }
3530
+ const found = answer.selected.length + answer.alternatives.length + (answer.alsoSelected?.length ?? 0) + (answer.runnerUp ? 1 : 0);
3531
+ const kept = selected.length + alternatives.length + alsoSelected.length + (runnerUp ? 1 : 0);
3532
+ return {
3533
+ answer: { ...answer, selected, alsoSelected, runnerUp, alternatives },
3534
+ replaced,
3535
+ pickRefused: pickRefused && kept > 0,
3536
+ refusedAll: found > 0 && kept === 0
3537
+ };
3538
+ }
3539
+ function status(answer, narrowed) {
3540
+ if (narrowed.pickRefused) {
3541
+ return "The chosen action is not allowed by this CLI, and no allowed candidate can take its place. The actions listed were needed beside it; tell the user which operation is blocked.";
3542
+ }
3543
+ if (narrowed.refusedAll) {
3544
+ return "Actions were found for this intent, but this CLI's access settings (action allowlist, permission level) allow none of them, so rephrasing will not help. Tell the user which operation is blocked.";
3545
+ }
3546
+ if (narrowed.replaced) {
3547
+ return "The chosen action is not allowed by this CLI, so this is the next allowed candidate: check it fits before using it.";
3548
+ }
3549
+ if (answer.selector === "none_fit" || answer.selected.length === 0) {
3550
+ return answer.alternatives.length === 0 ? "No action fits this intent, and nothing close was found. Rephrase it, or check the platform name." : "No action fits this intent. Rephrase it more specifically, or load one of the alternatives.";
3551
+ }
3552
+ if (answer.selector === "search_order") {
3553
+ return "The decision model was unavailable, so this is the top search result: check it fits before using it.";
3554
+ }
3555
+ return answer.confidence === void 0 ? "Chosen by the decision model." : `Chosen with confidence ${answer.confidence.toFixed(2)}.`;
3556
+ }
3557
+ function document(action, details, platform, settings) {
3558
+ if (details instanceof Error) {
3559
+ return {
3560
+ ...action,
3561
+ knowledge: `Its documentation could not be loaded (${details.message}). Load it with \`one --agent actions load ${action.actionId}\` before executing it; never execute it without reading it.`,
3562
+ truncated: true
3563
+ };
3564
+ }
3565
+ const knowledge = details.knowledge;
3566
+ if (settings.knowledgeAgent) {
3567
+ return { ...action, knowledge: codeGuideAction(action, knowledge, platform, details.tags ?? [], settings.apiBase), truncated: false };
3568
+ }
3569
+ if (!knowledge) {
3570
+ return { ...action, knowledge: NO_KNOWLEDGE, truncated: false };
3571
+ }
3572
+ const doc = parseSections(knowledge);
3573
+ const digest = buildDigest(doc, { actionId: action.actionId });
3574
+ if (!digest.truncated || doc.sections.length === 0) {
3575
+ return { ...action, knowledge, truncated: false };
3576
+ }
3577
+ return {
3578
+ ...action,
3579
+ knowledge: [renderDigestBanner(digest), digest.markdown, renderDigestNotice(digest, action.actionId)].filter(Boolean).join("\n\n"),
3580
+ truncated: true
3581
+ };
3582
+ }
3583
+ async function find(requests, task, deps, settings, { knowledgeCatalog = false, knowledge = true } = {}) {
3584
+ if (requests.length === 0 || requests.length > FIND_MAX_INTENTS) {
3585
+ throw new FindArgsError(`Send between 1 and ${FIND_MAX_INTENTS} platform and intent pairs.`);
3586
+ }
3587
+ const empty = requests.find((r) => !r.platform.trim() || !r.intent.trim());
3588
+ if (empty) {
3589
+ throw new FindArgsError("Every request needs a platform and an intent.");
3590
+ }
3591
+ const platforms = await reachable(settings, deps);
3592
+ const reaches = (platform) => platforms === null || platforms.includes(platform.toLowerCase());
3593
+ const asked = requests.filter((r) => reaches(r.platform));
3594
+ const answers = asked.length > 0 ? await deps.findActions(asked, task, settings.knowledgeAgent || knowledgeCatalog) : [];
3595
+ if (answers.length !== asked.length) {
3596
+ throw new Error(`One answered ${answers.length} of ${asked.length} requests; try again.`);
3597
+ }
3598
+ let next = 0;
3599
+ const plans = requests.map((intent) => {
3600
+ if (!reaches(intent.platform)) return { intent, unreachable: true };
3601
+ const narrowed = narrow(answers[next++], settings);
3602
+ const { answer } = narrowed;
3603
+ const picks = knowledge && settings.knowledgeAgent ? answer.selected.slice(0, 1) : answer.selected;
3604
+ return {
3605
+ intent,
3606
+ unreachable: false,
3607
+ narrowed,
3608
+ picks,
3609
+ deferred: [...answer.selected.slice(picks.length), ...answer.alsoSelected ?? []],
3610
+ runnerUpDocumented: knowledge && !settings.knowledgeAgent && answer.runnerUp !== void 0
3611
+ };
3612
+ });
3613
+ const ids = /* @__PURE__ */ new Set();
3614
+ for (const plan of plans) {
3615
+ if (plan.unreachable || !knowledge) continue;
3616
+ plan.picks.forEach((a) => ids.add(a.systemId));
3617
+ if (plan.runnerUpDocumented && plan.narrowed.answer.runnerUp) ids.add(plan.narrowed.answer.runnerUp.systemId);
3618
+ }
3619
+ const details = new Map(
3620
+ await Promise.all(
3621
+ [...ids].map(async (id) => {
3622
+ try {
3623
+ return [id, await deps.getActionDetails(id)];
3624
+ } catch (error2) {
3625
+ return [id, error2 instanceof Error ? error2 : new Error(String(error2))];
3626
+ }
3627
+ })
3628
+ )
3629
+ );
3630
+ let used = 0;
3631
+ let served = false;
3632
+ const admit = (doc) => {
3633
+ if (served && used + doc.knowledge.length > FIND_DOCUMENTS_BUDGET) return false;
3634
+ used += doc.knowledge.length;
3635
+ served = true;
3636
+ return true;
3637
+ };
3638
+ const result = plans.map((plan) => {
3639
+ if (plan.unreachable) {
3640
+ return {
3641
+ ...plan.intent,
3642
+ status: `Platform "${plan.intent.platform}" has no allowed connections for this CLI.`,
3643
+ selected: [],
3644
+ alsoSelected: [],
3645
+ alternatives: []
3646
+ };
3647
+ }
3648
+ const { answer } = plan.narrowed;
3649
+ const selected = knowledge ? [] : plan.picks.map(ref);
3650
+ const deferred = [];
3651
+ for (const [index, pick] of (knowledge ? plan.picks : []).entries()) {
3652
+ const doc = document(ref(pick), details.get(pick.systemId) ?? new Error("not fetched"), plan.intent.platform, settings);
3653
+ if (!admit(doc)) {
3654
+ deferred.push(...plan.picks.slice(index).map(ref));
3655
+ break;
3656
+ }
3657
+ selected.push(doc);
3658
+ }
3659
+ return {
3660
+ ...plan.intent,
3661
+ status: status(answer, plan.narrowed),
3662
+ selector: answer.selector,
3663
+ ...answer.confidence !== void 0 ? { confidence: answer.confidence } : {},
3664
+ selected,
3665
+ alsoSelected: [...deferred, ...plan.deferred.map(ref)],
3666
+ ...answer.runnerUp ? { runnerUp: ref(answer.runnerUp) } : {},
3667
+ alternatives: answer.alternatives.map(ref)
3668
+ };
3669
+ });
3670
+ plans.forEach((plan, index) => {
3671
+ if (plan.unreachable || !plan.runnerUpDocumented || !plan.narrowed.answer.runnerUp) return;
3672
+ const runnerUp = plan.narrowed.answer.runnerUp;
3673
+ const doc = document(ref(runnerUp), details.get(runnerUp.systemId) ?? new Error("not fetched"), plan.intent.platform, settings);
3674
+ if (used + doc.knowledge.length <= FIND_DOCUMENTS_BUDGET) {
3675
+ used += doc.knowledge.length;
3676
+ result[index].runnerUp = doc;
3677
+ }
3678
+ });
3679
+ const documented = result.some((a) => a.selected.some((s) => "knowledge" in s) || a.runnerUp && "knowledge" in a.runnerUp);
3680
+ return { answers: result, ...documented ? { guide: closingGuide(settings) } : {} };
3681
+ }
3682
+ async function load(actionIds, options, deps, settings) {
3683
+ if (actionIds.length === 0 || actionIds.length > FIND_MAX_LOADS) {
3684
+ throw new FindArgsError(`Load between 1 and ${FIND_MAX_LOADS} actions at once.`);
3685
+ }
3686
+ const platforms = await reachable(settings, deps);
3687
+ const entries = await Promise.all(
3688
+ actionIds.map(async (actionId) => {
3689
+ const refused = { actionId, error: REFUSED_LOAD };
3690
+ if (!isActionAllowed(actionId, settings.actionIds)) return refused;
3691
+ const details = await deps.getActionDetails(actionId).catch(() => void 0);
3692
+ if (!details || !isMethodAllowed(details.method, settings.permissions)) return refused;
3693
+ const platform = details.connectionPlatform ?? "";
3694
+ if (platforms !== null && platform && !platforms.includes(platform.toLowerCase())) return refused;
3695
+ const action = { actionId, title: details.title, method: details.method, path: details.path };
3696
+ if (settings.knowledgeAgent) {
3697
+ return document(action, details, platform, settings);
3698
+ }
3699
+ return { ...action, ...part(details.knowledge, actionId, options) };
3700
+ })
3701
+ );
3702
+ let used = 0;
3703
+ let served = false;
3704
+ const loaded = entries.map((entry) => {
3705
+ if ("error" in entry) return entry;
3706
+ if (served && used + entry.knowledge.length > FIND_DOCUMENTS_BUDGET) {
3707
+ return { actionId: entry.actionId, error: "too large to serve beside the others; load it on its own" };
3708
+ }
3709
+ used += entry.knowledge.length;
3710
+ served = true;
3711
+ return entry;
3712
+ });
3713
+ const documented = loaded.some((e) => !("error" in e));
3714
+ return { loaded, ...documented ? { guide: closingGuide(settings) } : {} };
3715
+ }
3716
+ function part(knowledge, actionId, options) {
3717
+ if (!knowledge) return { knowledge: NO_KNOWLEDGE, truncated: false };
3718
+ const doc = parseSections(knowledge);
3719
+ const names = parseSectionFlag(options.section);
3720
+ const specific = names.filter((n) => n.toLowerCase() !== "all");
3721
+ if (specific.length > 0) {
3722
+ const picked = selectSections(doc, specific);
3723
+ if (!picked.ok) {
3724
+ const toc = collapseSections(picked.candidates);
3725
+ const listing = toc.sections.map((c) => `${c.heading} [${c.id}] (${c.chars} chars${c.children ? `, +${c.children} nested` : ""})`).join("\n");
3726
+ const lead = picked.reason === "ambiguous" ? `Section "${picked.query}" matches several sections; pick one by id or full heading.` : `No section named "${picked.query}". Use one of the names below, or --full.`;
3727
+ return { knowledge: `${lead}
3728
+
3729
+ ${listing}`, truncated: true };
3730
+ }
3731
+ return { knowledge: picked.markdown, truncated: true };
3732
+ }
3733
+ if (options.toc) {
3734
+ const listing = flattenSections(doc.sections).map((s) => `${" ".repeat(Math.max(0, s.level - 1))}${s.heading} [${s.id}] (${s.chars} chars)`).join("\n");
3735
+ return {
3736
+ knowledge: `Table of contents. Load any with: one --agent actions load ${actionId} --section "<id or heading>", or the whole document with --full.
3737
+
3738
+ ${listing || "(this document has no sections)"}`,
3739
+ truncated: true
3740
+ };
3741
+ }
3742
+ if (options.full === true || names.length > 0) {
3743
+ return { knowledge, truncated: false };
3744
+ }
3745
+ const digest = buildDigest(doc, { actionId });
3746
+ if (!digest.truncated || doc.sections.length === 0) return { knowledge, truncated: false };
3747
+ return {
3748
+ knowledge: [renderDigestBanner(digest), digest.markdown, renderDigestNotice(digest, actionId)].filter(Boolean).join("\n\n"),
3749
+ truncated: true
3750
+ };
3751
+ }
3752
+ function closingGuide(settings) {
3753
+ return settings.knowledgeAgent ? codeGuideRules() : EXECUTE_GUIDE;
3754
+ }
3755
+ function platformEnvSegment(platform) {
3756
+ const segment = platform.toUpperCase().split(/[^A-Z0-9]+/).filter(Boolean).join("_");
3757
+ return segment || "PLATFORM";
3758
+ }
3759
+ var CUSTOM_ACTION_NOTE = '\n\nThis is a custom action: ALSO include "connectionKey" (the same value as the x-one-connection-key header) as a field in the JSON body for non-GET requests.';
3760
+ function codeGuideAction(action, knowledge, platform, tags, apiBase) {
3761
+ const base = apiBase.replace(/\/$/, "");
3762
+ const method = action.method.toUpperCase();
3763
+ const path14 = action.path.startsWith("/") ? action.path : `/${action.path}`;
3764
+ const connEnv = `ONE_${platformEnvSegment(platform)}_CONNECTION_KEY`;
3765
+ const customNote = tags.includes("custom") ? CUSTOM_ACTION_NOTE : "";
3766
+ return `### ${actionHeading(action)}
3767
+ **Platform:** ${platform}
3768
+
3769
+ ${knowledge ?? NO_KNOWLEDGE}
3770
+
3771
+ ## Calling this action from code
3772
+ URL: ${base}/passthrough${path14}
3773
+ Method: ${method}
3774
+ Headers:
3775
+ - x-one-secret: the value of the ONE_SECRET env var
3776
+ - x-one-connection-key: the value of the ${connEnv} env var
3777
+ - x-one-action-id: ${action.actionId}
3778
+ - Content-Type: application/json${customNote}
3779
+
3780
+ Environment variables: ONE_SECRET (their One API key) and ${connEnv} (the key of their ${platform} connection), both from the One dashboard.
3781
+
3782
+ \`\`\`typescript
3783
+ const response = await fetch("${base}/passthrough${path14}", {
3784
+ method: "${method}",
3785
+ headers: {
3786
+ "x-one-secret": process.env.ONE_SECRET,
3787
+ "x-one-connection-key": process.env.${connEnv},
3788
+ "x-one-action-id": "${action.actionId}",
3789
+ "Content-Type": "application/json",
3790
+ },
3791
+ // body: JSON.stringify(...) - only for non-GET requests
3792
+ });
3793
+ \`\`\``;
3794
+ }
3795
+ function codeGuideRules() {
3796
+ return `================================================================
3797
+ INTEGRATION CODE GUIDE - using these actions in an application
3798
+ ================================================================
3799
+ You are in knowledge mode: actions cannot be executed here. Use this
3800
+ guide, with each action's "Calling this action from code", to write
3801
+ integration code in the user's project.
3802
+
3803
+ ## 1. Where this code must live
3804
+ Server-side only - an API route, edge function, or backend handler
3805
+ (e.g. Supabase Edge Function, Next.js route handler, Express route).
3806
+ NEVER call this API from browser/client code and NEVER hardcode secret
3807
+ values in source - read them from environment variables.
3808
+
3809
+ ## 2. The request
3810
+ All calls go through the One Passthrough API. Do NOT call the third-party
3811
+ API URL from the documentation directly. The URL is the One base plus the
3812
+ action path ONLY:
3813
+ \u2705 {One base}/v1/passthrough{action path} (the path starts with /)
3814
+ \u274C {One base}/v1/passthrough/https://some-vendor-api.com{action path}
3815
+
3816
+ ## 3. Parameter placement
3817
+ Per each action's documentation:
3818
+ - Path variables (placeholders like {{userId}} in the path) \u2192 substitute
3819
+ real values into the URL path; never send them in the body.
3820
+ - Query parameters \u2192 the URL query string, not the body.
3821
+ - Body fields \u2192 the JSON request body (POST/PUT/PATCH only).
3822
+
3823
+ ## 4. Environment variables & deployment
3824
+ The code will not work until the user sets each action's environment
3825
+ variables in their hosting platform's secrets manager (Supabase secrets,
3826
+ Vercel/Netlify environment settings, or the project's env settings -
3827
+ never committed to code). When you deliver the code, explicitly tell the
3828
+ user to set them.
3829
+
3830
+ ## 5. Code generation rules
3831
+ - Use TypeScript unless the user asked for another language.
3832
+ - Include the complete input/output structure from the documentation
3833
+ (required/optional fields, types) in the implementation.
3834
+ - Handle errors: on a non-2xx response, read the response body and
3835
+ surface a useful message.`;
3836
+ }
3837
+ function renderFind(result) {
3838
+ const listing = (lead, actions2) => actions2.length === 0 ? [] : [`${lead} (load with \`one actions load <actionId>\`):
3839
+ ${actions2.map((a) => `- ${actionHeading(a)}`).join("\n")}`];
3840
+ const shown = (doc) => doc.knowledge.startsWith("### ") ? doc.knowledge : `### ${actionHeading(doc)}
3841
+
3842
+ ${doc.knowledge}`;
3843
+ const sections = result.answers.map((answer) => {
3844
+ const parts = [`## ${answer.platform}: ${answer.intent}
3845
+
3846
+ ${answer.status}`];
3847
+ const documented = answer.selected.filter((s) => "knowledge" in s);
3848
+ parts.push(...documented.map(shown));
3849
+ parts.push(...listing("Chosen for this intent", answer.selected.filter((s) => !("knowledge" in s))));
3850
+ parts.push(
3851
+ ...listing(
3852
+ answer.selected.length === 0 ? "Chosen for this intent, documentation left out to keep the answer small" : "Also chosen for this intent, documentation left out to keep the answer small",
3853
+ answer.alsoSelected
3854
+ )
3855
+ );
3856
+ if (answer.runnerUp) {
3857
+ const lead = "If the chosen action does not fit, use this one instead: one or the other, never both";
3858
+ parts.push(..."knowledge" in answer.runnerUp ? [`${lead}.
3859
+
3860
+ ${shown(answer.runnerUp)}`] : listing(lead, [answer.runnerUp]));
3861
+ }
3862
+ parts.push(...listing("Alternatives, not documented", answer.alternatives));
3863
+ return parts.join("\n\n");
3864
+ });
3865
+ return [...sections, ...result.guide ? [result.guide] : []].join("\n\n---\n\n");
3866
+ }
3867
+ function renderLoad(result) {
3868
+ const entries = result.loaded.map(
3869
+ (entry) => "error" in entry ? `\`${entry.actionId}\`: ${entry.error}` : entry.knowledge.startsWith("### ") ? entry.knowledge : `### ${actionHeading(entry)}
3870
+
3871
+ ${entry.knowledge}`
3872
+ );
3873
+ return [...entries, ...result.guide ? [result.guide] : []].join("\n\n---\n\n");
3874
+ }
3875
+
3496
3876
  // src/commands/actions.ts
3497
3877
  function getConfig() {
3498
3878
  const apiKey = getApiKey();
@@ -3513,312 +3893,101 @@ function parseJsonArg2(value, argName) {
3513
3893
  error(`Invalid JSON for ${argName}: ${value}`);
3514
3894
  }
3515
3895
  }
3516
- async function actionsSearchCommand(platform, query, options) {
3896
+ function findDeps(api, connectionKeys, useCache) {
3897
+ return {
3898
+ findActions: (requests, task, knowledgeAgent) => api.findActions(requests, task, knowledgeAgent),
3899
+ getActionDetails: async (actionId) => (await resolveActionDetails(api, actionId, { useCache })).details,
3900
+ connectedPlatforms: async () => (await api.listConnections()).filter((c) => connectionKeys.includes(c.key)).map((c) => c.platform)
3901
+ };
3902
+ }
3903
+ function failure(error2) {
3904
+ if (error2 instanceof ApiError) {
3905
+ try {
3906
+ const body = JSON.parse(error2.message);
3907
+ if (body.message) return body.message;
3908
+ } catch {
3909
+ }
3910
+ }
3911
+ return error2 instanceof Error ? error2.message : "Unknown error";
3912
+ }
3913
+ async function actionsFindCommand(pairs, options) {
3517
3914
  intro(pc8.bgCyan(pc8.black(" One ")));
3518
- const { apiKey, permissions, actionIds, knowledgeAgent } = getConfig();
3915
+ if (options.type !== void 0 && options.type !== "execute" && options.type !== "knowledge") {
3916
+ error("--type must be execute or knowledge.");
3917
+ }
3918
+ if (pairs.length === 0 || pairs.length % 2 !== 0) {
3919
+ error('Pass platform and intent pairs: one actions find <platform> "<intent>" [<platform> "<intent>" ...]');
3920
+ }
3921
+ const requests = [];
3922
+ for (let i = 0; i < pairs.length; i += 2) {
3923
+ requests.push({ platform: pairs[i], intent: pairs[i + 1] });
3924
+ }
3925
+ const { apiKey, permissions, connectionKeys, actionIds, knowledgeAgent } = getConfig();
3519
3926
  const api = new OneApi(apiKey, getApiBase());
3927
+ const settings = { knowledgeAgent, permissions, actionIds, connectionKeys, apiBase: getApiBase() };
3520
3928
  const spinner4 = createSpinner();
3521
- spinner4.start(`Searching actions on ${pc8.cyan(platform)} for "${query}"...`);
3929
+ spinner4.start(`Finding actions for ${requests.length} intent${requests.length === 1 ? "" : "s"}...`);
3522
3930
  try {
3523
- const agentType = knowledgeAgent ? "knowledge" : options.type || "execute";
3524
- const useCache = options.cache !== false;
3525
- const searchType = agentType || "knowledge";
3526
- const cachePath = searchCachePath(platform, query, searchType);
3527
- const cached2 = useCache ? readCache(cachePath) : null;
3528
- let cleanedActions;
3529
- let cacheHit = false;
3530
- if (cached2 && isFresh(cached2)) {
3531
- cleanedActions = cached2.data.actions;
3532
- cacheHit = true;
3533
- } else {
3534
- try {
3535
- const result = await api.searchActionsWithMeta(
3536
- platform,
3537
- query,
3538
- agentType,
3539
- cached2?.etag ?? void 0
3540
- );
3541
- if (result.status === 304 && cached2) {
3542
- cached2.cachedAt = (/* @__PURE__ */ new Date()).toISOString();
3543
- writeCache(cachePath, cached2);
3544
- cleanedActions = cached2.data.actions;
3545
- cacheHit = true;
3546
- } else {
3547
- let actions2 = result.data;
3548
- actions2 = filterByPermissions(actions2, permissions);
3549
- actions2 = actions2.filter((a) => isActionAllowed(a.systemId, actionIds));
3550
- cleanedActions = actions2.map((action) => ({
3551
- actionId: action.systemId,
3552
- title: action.title,
3553
- method: action.method,
3554
- path: action.path
3555
- }));
3556
- writeCache(cachePath, makeCacheEntry(
3557
- `${platform}_${query}_${searchType}`,
3558
- { actions: cleanedActions, platform, query, searchType },
3559
- result.etag
3560
- ));
3561
- }
3562
- } catch (fetchError) {
3563
- if (cached2) {
3564
- process.stderr.write(
3565
- `Warning: serving cached search results (network unavailable, cached ${formatAge(getAge(cached2))} ago)
3566
- `
3567
- );
3568
- cleanedActions = cached2.data.actions;
3569
- cacheHit = true;
3570
- } else {
3571
- throw fetchError;
3572
- }
3573
- }
3574
- }
3931
+ const result = await find(
3932
+ requests,
3933
+ options.task,
3934
+ findDeps(api, connectionKeys, options.cache !== false),
3935
+ settings,
3936
+ { knowledgeCatalog: options.type === "knowledge", knowledge: options.knowledge !== false }
3937
+ );
3575
3938
  if (isAgentMode()) {
3576
- const response = { actions: cleanedActions };
3577
- if (cacheHit && cached2) {
3578
- response._cache = buildCacheMeta(cached2, true);
3579
- } else {
3580
- const freshEntry = readCache(cachePath);
3581
- response._cache = buildCacheMeta(freshEntry, false);
3582
- }
3583
- json(response);
3584
- return;
3585
- }
3586
- if (cleanedActions.length === 0) {
3587
- spinner4.stop("No actions found");
3588
- p6.note(
3589
- `No actions found for platform '${platform}' matching query '${query}'.
3590
-
3591
- Suggestions:
3592
- - Try a more general query (e.g., 'list', 'get', 'search', 'create')
3593
- - Verify the platform name is correct
3594
- - Check available platforms with ${pc8.cyan("one platforms")}
3595
-
3596
- Examples of good queries:
3597
- - "search contacts"
3598
- - "send email"
3599
- - "create customer"
3600
- - "list orders"`,
3601
- "No Results"
3602
- );
3939
+ json(result);
3603
3940
  return;
3604
3941
  }
3605
- spinner4.stop(
3606
- `Found ${cleanedActions.length} action(s) for '${platform}' matching '${query}'`
3607
- );
3942
+ spinner4.stop("Found");
3608
3943
  console.log();
3609
- const rows = cleanedActions.map((a) => ({
3610
- method: colorMethod(a.method),
3611
- title: a.title,
3612
- actionId: a.actionId,
3613
- path: a.path
3614
- }));
3615
- printTable(
3616
- [
3617
- { key: "method", label: "Method" },
3618
- { key: "title", label: "Title" },
3619
- { key: "actionId", label: "Action ID", color: pc8.dim },
3620
- { key: "path", label: "Path", color: pc8.dim }
3621
- ],
3622
- rows
3623
- );
3944
+ console.log(renderFind(result));
3624
3945
  console.log();
3625
- p6.note(
3626
- `Get details: ${pc8.cyan(`one actions knowledge ${platform} <actionId>`)}
3627
- Execute: ${pc8.cyan(`one actions execute ${platform} <actionId> <connectionKey>`)}`,
3628
- "Next Steps"
3629
- );
3630
3946
  } catch (error2) {
3631
- spinner4.stop("Search failed");
3632
- error(
3633
- `Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`
3634
- );
3947
+ spinner4.stop("Find failed");
3948
+ error(`Error: ${failure(error2)}`);
3635
3949
  }
3636
3950
  }
3637
- async function actionsKnowledgeCommand(platform, actionId, options) {
3638
- const cachePath = knowledgeCachePath(actionId);
3951
+ async function actionsLoadCommand(actionIds, options) {
3639
3952
  if (options.cacheStatus) {
3640
- const entry = readCache(cachePath);
3641
- if (!entry) {
3642
- json({
3643
- cached: false,
3644
- path: cachePath
3645
- });
3646
- } else {
3647
- const age = getAge(entry);
3648
- json({
3649
- cached: true,
3650
- cachedAt: entry.cachedAt,
3651
- age: formatAge(age),
3652
- ttl: entry.ttl,
3653
- expired: !isFresh(entry),
3654
- etag: entry.etag,
3655
- path: cachePath
3656
- });
3657
- }
3953
+ json(
3954
+ actionIds.map((actionId) => {
3955
+ const cachePath = knowledgeCachePath(actionId);
3956
+ const entry = readCache(cachePath);
3957
+ if (!entry) return { actionId, cached: false, path: cachePath };
3958
+ return {
3959
+ actionId,
3960
+ cached: true,
3961
+ cachedAt: entry.cachedAt,
3962
+ age: formatAge(getAge(entry)),
3963
+ ttl: entry.ttl,
3964
+ expired: !isFresh(entry),
3965
+ etag: entry.etag,
3966
+ path: cachePath
3967
+ };
3968
+ })
3969
+ );
3658
3970
  return;
3659
3971
  }
3660
3972
  intro(pc8.bgCyan(pc8.black(" One ")));
3661
- const { apiKey, actionIds, connectionKeys } = getConfig();
3973
+ const { apiKey, permissions, connectionKeys, actionIds: allowed, knowledgeAgent } = getConfig();
3662
3974
  const api = new OneApi(apiKey, getApiBase());
3663
- if (!isActionAllowed(actionId, actionIds)) {
3664
- error(`Action "${actionId}" is not in the allowed action list.`);
3665
- }
3666
- if (!connectionKeys.includes("*")) {
3667
- const spinner5 = createSpinner();
3668
- spinner5.start("Checking connections...");
3669
- try {
3670
- const connections = await api.listConnections();
3671
- const connectedPlatforms = connections.map((c) => c.platform);
3672
- if (!connectedPlatforms.includes(platform)) {
3673
- spinner5.stop("Platform not connected");
3674
- error(`Platform "${platform}" has no allowed connections.`);
3675
- }
3676
- spinner5.stop("Connection verified");
3677
- } catch (error2) {
3678
- spinner5.stop("Failed to check connections");
3679
- error(
3680
- `Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`
3681
- );
3682
- }
3683
- }
3975
+ const settings = { knowledgeAgent, permissions, actionIds: allowed, connectionKeys, apiBase: getApiBase() };
3684
3976
  const spinner4 = createSpinner();
3685
- spinner4.start(`Loading knowledge for action ${pc8.dim(actionId)}...`);
3977
+ spinner4.start(`Loading ${actionIds.length === 1 ? "the action" : `${actionIds.length} actions`}...`);
3686
3978
  try {
3687
- const { details, cacheHit, entry } = await resolveActionDetails(api, actionId, {
3688
- useCache: options.cache !== false
3689
- });
3690
- const knowledgeData = {
3691
- knowledge: details.knowledge || "No knowledge was found",
3692
- method: details.method || "No method was found"
3693
- };
3694
- const doc = parseSections(knowledgeData.knowledge);
3695
- const sectionNames = parseSectionFlag(options.section);
3696
- const wantFull = options.full === true || sectionNames.some((n) => n.toLowerCase() === "all");
3697
- const base = `one --agent actions knowledge ${platform} ${actionId}`;
3698
- const fullToc = flattenSections(doc.sections).map((s) => ({ id: s.id, heading: s.heading, level: s.level, chars: s.chars }));
3699
- if (options.toc) {
3700
- if (isAgentMode()) {
3701
- json({
3702
- title: doc.title,
3703
- method: knowledgeData.method,
3704
- chars: doc.chars,
3705
- sections: fullToc,
3706
- more: { section: `${base} --section <id or heading>[,<id or heading>...]`, full: `${base} --full` },
3707
- _cache: buildCacheMeta(entry, cacheHit)
3708
- });
3709
- return;
3710
- }
3711
- spinner4.stop("Sections");
3712
- console.log();
3713
- for (const t of fullToc) console.log(`${" ".repeat(Math.max(0, t.level - 1))}${t.heading} ${pc8.dim(`[${t.id}] ${t.chars} chars`)}`);
3714
- console.log();
3715
- return;
3716
- }
3717
- if (sectionNames.length > 0 && !wantFull) {
3718
- const picked = selectSections(doc, sectionNames);
3719
- if (!picked.ok) {
3720
- const toc = collapseSections(picked.candidates);
3721
- const list = toc.sections.map((c) => `${" ".repeat(Math.max(0, c.level - 2))}${c.heading} [${c.id}] (${c.chars} chars${c.children ? `, +${c.children} nested` : ""})`).join("\n");
3722
- if (isAgentMode()) {
3723
- json({
3724
- error: picked.reason === "ambiguous" ? `Section "${picked.query}" matches several sections; pick one by id or full heading.` : `No section named "${picked.query}". Use one of the ids or headings below, or --full.`,
3725
- query: picked.query,
3726
- reason: picked.reason,
3727
- sections: toc.sections.map(({ id, heading, level, chars, children }) => children ? { id, heading, level, chars, children } : { id, heading, level, chars }),
3728
- ...toc.collapsed ? { sectionsCollapsed: true, sectionCount: picked.candidates.length } : {},
3729
- hint: `${base} --section <id or heading>`,
3730
- toc: `${base} --toc`
3731
- });
3732
- process.exit(1);
3733
- }
3734
- spinner4.stop("Section not found");
3735
- error(`${picked.reason === "ambiguous" ? "Ambiguous" : "Unknown"} section "${picked.query}". Available:
3736
- ${list}`);
3737
- }
3738
- if (isAgentMode()) {
3739
- json({
3740
- knowledge: picked.markdown,
3741
- method: knowledgeData.method,
3742
- title: doc.title,
3743
- // The requested sections are returned whole; nothing here was cut.
3744
- truncated: false,
3745
- requested: sectionNames,
3746
- // What each name matched — fuzzy and alias matches are visible here.
3747
- resolved: picked.sections.map((s) => ({ id: s.id, heading: s.heading, chars: s.chars })),
3748
- sectionCount: fullToc.length,
3749
- more: {
3750
- note: "Only the requested sections are included. The digest call listed the others; `--toc` lists all of them.",
3751
- section: `${base} --section <id or heading>[,<id or heading>...]`,
3752
- toc: `${base} --toc`,
3753
- full: `${base} --full`
3754
- },
3755
- _cache: buildCacheMeta(entry, cacheHit)
3756
- });
3757
- return;
3758
- }
3759
- spinner4.stop("Sections loaded");
3760
- console.log();
3761
- console.log(picked.markdown);
3762
- console.log();
3763
- return;
3764
- }
3765
- const digest = buildDigest(
3766
- doc,
3767
- isAgentMode() && !wantFull ? {} : { wholeDocThreshold: Number.POSITIVE_INFINITY }
3768
- );
3769
- const body = doc.sections.length === 0 ? knowledgeData.knowledge : digest.markdown;
3770
- const notice = renderDigestNotice(digest, platform, actionId);
3771
- const banner = renderDigestBanner(digest);
3772
- const knowledgeWithGuidance = buildActionKnowledgeWithGuidance(
3773
- notice ? `${banner}
3774
-
3775
- ${body}
3776
-
3777
- ${notice}` : body,
3778
- knowledgeData.method,
3779
- platform,
3780
- actionId
3781
- );
3979
+ const result = await load(actionIds, options, findDeps(api, connectionKeys, options.cache !== false), settings);
3782
3980
  if (isAgentMode()) {
3783
- const response = {
3784
- knowledge: knowledgeWithGuidance,
3785
- method: knowledgeData.method,
3786
- title: doc.title || void 0,
3787
- truncated: digest.truncated,
3788
- _cache: buildCacheMeta(entry, cacheHit)
3789
- };
3790
- if (digest.truncated) {
3791
- const toc = omittedSections(digest);
3792
- response.omitted = digest.omitted;
3793
- response.omittedChars = digest.omittedChars;
3794
- response.sections = toc.sections;
3795
- if (toc.collapsed) {
3796
- response.sectionsCollapsed = true;
3797
- response.sectionCount = digest.sections.length;
3798
- }
3799
- response.more = {
3800
- note: toc.collapsed ? `This is a digest. \`sections\` lists what was omitted, collapsed to ${toc.sections.length} entries (\`children\` counts nested ones); request any by id or heading, or --toc for all ${digest.sections.length} headings.` : "This is a digest. `sections` lists what was omitted; request any by id or heading.",
3801
- section: `${base} --section <id or heading>[,<id or heading>...]`,
3802
- toc: `${base} --toc`,
3803
- full: `${base} --full`
3804
- };
3805
- }
3806
- json(response);
3981
+ json(result);
3807
3982
  return;
3808
3983
  }
3809
- spinner4.stop("Knowledge loaded");
3984
+ spinner4.stop("Loaded");
3810
3985
  console.log();
3811
- console.log(knowledgeWithGuidance);
3986
+ console.log(renderLoad(result));
3812
3987
  console.log();
3813
- p6.note(
3814
- `Execute: ${pc8.cyan(`one actions execute ${platform} ${actionId} <connectionKey>`)}`,
3815
- "Next Step"
3816
- );
3817
3988
  } catch (error2) {
3818
- spinner4.stop("Failed to load knowledge");
3819
- error(
3820
- `Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`
3821
- );
3989
+ spinner4.stop("Load failed");
3990
+ error(`Error: ${failure(error2)}`);
3822
3991
  }
3823
3992
  }
3824
3993
  async function actionsExecuteCommand(platform, actionId, connectionKey, options) {
@@ -4275,22 +4444,6 @@ async function actionsExecuteParallelCommand() {
4275
4444
  }
4276
4445
  console.log();
4277
4446
  }
4278
- function colorMethod(method) {
4279
- switch (method.toUpperCase()) {
4280
- case "GET":
4281
- return pc8.green(method);
4282
- case "POST":
4283
- return pc8.yellow(method);
4284
- case "PUT":
4285
- return pc8.blue(method);
4286
- case "PATCH":
4287
- return pc8.magenta(method);
4288
- case "DELETE":
4289
- return pc8.red(method);
4290
- default:
4291
- return method;
4292
- }
4293
- }
4294
4447
 
4295
4448
  // src/commands/flow.ts
4296
4449
  import pc9 from "picocolors";
@@ -5049,14 +5202,14 @@ function previewValue(value, max = 120) {
5049
5202
  if (str === void 0) str = String(value);
5050
5203
  return str.length > max ? `${str.slice(0, max - 1)}\u2026` : str;
5051
5204
  }
5052
- function renderDryRef(ref) {
5053
- if (ref.status === "resolved") {
5054
- return `${pc9.green("\u2713")} ${ref.selector} ${pc9.dim("\u2192")} ${previewValue(ref.value)}`;
5205
+ function renderDryRef(ref2) {
5206
+ if (ref2.status === "resolved") {
5207
+ return `${pc9.green("\u2713")} ${ref2.selector} ${pc9.dim("\u2192")} ${previewValue(ref2.value)}`;
5055
5208
  }
5056
- if (ref.status === "deferred") {
5057
- return `${pc9.dim("\u25CB")} ${ref.selector} ${pc9.dim("\u2192 pending (produced by a later step)")}`;
5209
+ if (ref2.status === "deferred") {
5210
+ return `${pc9.dim("\u25CB")} ${ref2.selector} ${pc9.dim("\u2192 pending (produced by a later step)")}`;
5058
5211
  }
5059
- return `${pc9.yellow("!")} ${ref.selector} ${pc9.yellow("\u2192 unresolved \u2014 check the input/env name")}`;
5212
+ return `${pc9.yellow("!")} ${ref2.selector} ${pc9.yellow("\u2192 unresolved \u2014 check the input/env name")}`;
5060
5213
  }
5061
5214
  function renderDryResolution(steps) {
5062
5215
  const isExpr = (t) => t === "transform" || t === "condition" || t === "while";
@@ -5072,8 +5225,8 @@ function renderDryResolution(steps) {
5072
5225
  console.log(` ${pc9.dim("=")} ${previewValue(s.resolved)}`);
5073
5226
  }
5074
5227
  if (!(isExpr(s.type) && s.deferred)) {
5075
- for (const ref of s.references) {
5076
- console.log(` ${renderDryRef(ref)}`);
5228
+ for (const ref2 of s.references) {
5229
+ console.log(` ${renderDryRef(ref2)}`);
5077
5230
  }
5078
5231
  }
5079
5232
  if (!isExpr(s.type) && s.references.length === 0 && s.error === void 0) {
@@ -5280,8 +5433,8 @@ ${pc9.yellow("Pausing after current step completes...")} (run ID: ${runId})`);
5280
5433
  if (event.event === "step:start") {
5281
5434
  console.log(` ${pc9.dim(ts)} ${pc9.cyan("\u25B6")} ${event.stepName} ${pc9.dim(`(${event.type})`)}`);
5282
5435
  } else if (event.event === "step:complete") {
5283
- const status = event.status === "success" ? pc9.green("\u2713") : event.status === "skipped" ? pc9.dim("\u25CB") : pc9.red("\u2717");
5284
- console.log(` ${pc9.dim(ts)} ${status} ${event.stepId} ${pc9.dim(`${event.durationMs}ms`)}`);
5436
+ const status2 = event.status === "success" ? pc9.green("\u2713") : event.status === "skipped" ? pc9.dim("\u25CB") : pc9.red("\u2717");
5437
+ console.log(` ${pc9.dim(ts)} ${status2} ${event.stepId} ${pc9.dim(`${event.durationMs}ms`)}`);
5285
5438
  } else if (event.event === "step:error") {
5286
5439
  console.log(` ${pc9.dim(ts)} ${pc9.red("\u2717")} ${event.stepId}: ${event.error}`);
5287
5440
  }
@@ -5618,18 +5771,18 @@ async function flowInspectCommand(runId, options = {}) {
5618
5771
  console.log(` ${pc9.dim(`Log: ${path7.join(".one/flows/.logs", `${state.flowKey}-${state.runId}.log`)}`)}`);
5619
5772
  console.log();
5620
5773
  }
5621
- function colorStatus(status) {
5622
- switch (status) {
5774
+ function colorStatus(status2) {
5775
+ switch (status2) {
5623
5776
  case "completed":
5624
- return pc9.green(status);
5777
+ return pc9.green(status2);
5625
5778
  case "running":
5626
- return pc9.cyan(status);
5779
+ return pc9.cyan(status2);
5627
5780
  case "paused":
5628
- return pc9.yellow(status);
5781
+ return pc9.yellow(status2);
5629
5782
  case "failed":
5630
- return pc9.red(status);
5783
+ return pc9.red(status2);
5631
5784
  default:
5632
- return status;
5785
+ return status2;
5633
5786
  }
5634
5787
  }
5635
5788
  var SCAFFOLD_TEMPLATES = {
@@ -6156,7 +6309,7 @@ async function relayPlatformsCommand() {
6156
6309
  { key: "platform", label: "Platform" },
6157
6310
  { key: "eventTypeCount", label: "Event types", color: pc10.dim }
6158
6311
  ],
6159
- platforms.map((p10) => ({ platform: p10.platform, eventTypeCount: String(p10.eventTypeCount) }))
6312
+ platforms.map((p9) => ({ platform: p9.platform, eventTypeCount: String(p9.eventTypeCount) }))
6160
6313
  );
6161
6314
  console.log();
6162
6315
  console.log(
@@ -6682,9 +6835,9 @@ function interpolate(template, record) {
6682
6835
  return template.replace(/\{?\{(\w+(?:\.\w+)*)\}\}?/g, (_, path14) => {
6683
6836
  const parts = path14.split(".");
6684
6837
  let value = record;
6685
- for (const part of parts) {
6838
+ for (const part2 of parts) {
6686
6839
  if (typeof value !== "object" || value === null) return "";
6687
- value = value[part];
6840
+ value = value[part2];
6688
6841
  }
6689
6842
  return value === null || value === void 0 ? "" : String(value);
6690
6843
  });
@@ -6711,9 +6864,9 @@ function deepMerge(target, source) {
6711
6864
  function getByDotPath2(obj, path14) {
6712
6865
  const parts = path14.split(".");
6713
6866
  let current = obj;
6714
- for (const part of parts) {
6867
+ for (const part2 of parts) {
6715
6868
  if (current === null || current === void 0 || typeof current !== "object") return void 0;
6716
- current = current[part];
6869
+ current = current[part2];
6717
6870
  }
6718
6871
  return current;
6719
6872
  }
@@ -6868,7 +7021,7 @@ async function enrichPhase(api, db, config2, model, idField, connectionKey, plat
6868
7021
  }
6869
7022
  if (detailAction.tags?.includes("custom")) {
6870
7023
  throw new Error(
6871
- `Enrich does not support custom actions. Action ${config2.actionId} is tagged "custom". Use a passthrough detail endpoint \u2014 run 'one actions search ${platform} "<model> get"' to find one.`
7024
+ `Enrich does not support custom actions. Action ${config2.actionId} is tagged "custom". Use a passthrough detail endpoint \u2014 run 'one actions find ${platform} "get a <model>" -t knowledge' to find one.`
6872
7025
  );
6873
7026
  }
6874
7027
  let concurrency = config2.concurrency ?? DEFAULT_CONCURRENCY;
@@ -6915,16 +7068,16 @@ async function enrichPhase(api, db, config2, model, idField, connectionKey, plat
6915
7068
  }
6916
7069
  let writes = pending2;
6917
7070
  if (ctx.transform && pending2.length > 0) {
6918
- const transformed = await transformRecords(ctx.transform, pending2.map((p10) => p10.merged));
7071
+ const transformed = await transformRecords(ctx.transform, pending2.map((p9) => p9.merged));
6919
7072
  if (transformed) {
6920
7073
  const byId = /* @__PURE__ */ new Map();
6921
7074
  for (const r of transformed) byId.set(r[idField], r);
6922
7075
  writes = [];
6923
- for (const p10 of pending2) {
6924
- const t = byId.get(p10.id);
7076
+ for (const p9 of pending2) {
7077
+ const t = byId.get(p9.id);
6925
7078
  if (!t) continue;
6926
7079
  if (!t[tsField]) t[tsField] = now;
6927
- writes.push({ merged: t, id: p10.id });
7080
+ writes.push({ merged: t, id: p9.id });
6928
7081
  }
6929
7082
  }
6930
7083
  }
@@ -7312,7 +7465,7 @@ async function syncModel(api, profile, options) {
7312
7465
  const { details: actionDetails } = await resolveActionDetails(api, profile.actionId);
7313
7466
  if (actionDetails.tags?.includes("custom")) {
7314
7467
  throw new Error(
7315
- `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.`
7468
+ `Sync does not support custom actions. Action ${profile.actionId} is tagged "custom". Use a passthrough action \u2014 run 'one actions find ${platform} "list ${model}" -t knowledge' to find one, or compose a flow that chains passthrough calls if the logic is complex.`
7316
7469
  );
7317
7470
  }
7318
7471
  const maxPages = options.maxPages ?? Infinity;
@@ -7861,7 +8014,7 @@ async function testSyncProfile(api, profile) {
7861
8014
  checks.push({
7862
8015
  name: "action is passthrough (not custom)",
7863
8016
  ok: false,
7864
- detail: `Action ${profile.actionId} is tagged "custom". Sync only supports passthrough actions. Run 'one actions search ${profile.platform} "${profile.model}"' to find one.`
8017
+ detail: `Action ${profile.actionId} is tagged "custom". Sync only supports passthrough actions. Run 'one actions find ${profile.platform} "list ${profile.model}" -t knowledge' to find one.`
7865
8018
  });
7866
8019
  return report;
7867
8020
  }
@@ -8716,7 +8869,7 @@ async function searchSyncedData(query, options) {
8716
8869
  const backend = await getBackend();
8717
8870
  const profiles = listProfiles(options.platform);
8718
8871
  const modelFilter = options.models ? new Set(options.models) : null;
8719
- const types = profiles.filter((p10) => !modelFilter || modelFilter.has(p10.model)).map((p10) => `${p10.platform}/${p10.model}`);
8872
+ const types = profiles.filter((p9) => !modelFilter || modelFilter.has(p9.model)).map((p9) => `${p9.platform}/${p9.model}`);
8720
8873
  if (types.length === 0) {
8721
8874
  throw new Error(
8722
8875
  options.platform ? `No sync profiles found for ${options.platform}. Run 'one sync init ${options.platform} <model>' first.` : `No sync profiles configured. Run 'one sync init <platform> <model>' first.`
@@ -8872,7 +9025,7 @@ function suggestSearchablePaths(records, limit = 15) {
8872
9025
 
8873
9026
  // src/lib/memory/sync/index.ts
8874
9027
  import { spawn as spawn4 } from "child_process";
8875
- import * as p7 from "@clack/prompts";
9028
+ import * as p6 from "@clack/prompts";
8876
9029
  import pc11 from "picocolors";
8877
9030
  async function syncInstallCommand() {
8878
9031
  if (await isSqliteAvailable()) {
@@ -8960,17 +9113,17 @@ async function syncProfilesCommand(platform) {
8960
9113
  const profiles = listBuiltinProfiles(platform);
8961
9114
  if (isAgentMode()) {
8962
9115
  json({
8963
- profiles: profiles.map((p10) => ({
8964
- platform: p10.platform,
8965
- model: p10.model,
8966
- description: p10.description,
8967
- hasEnrich: !!p10.enrich,
9116
+ profiles: profiles.map((p9) => ({
9117
+ platform: p9.platform,
9118
+ model: p9.model,
9119
+ description: p9.description,
9120
+ hasEnrich: !!p9.enrich,
8968
9121
  // `identityKey` (singular) is the entity-merge key; `identityKeys`
8969
9122
  // (plural, #167) are non-merging association keys. Reading only the
8970
9123
  // singular reported hasIdentityKey:false for gmail/gcal/fathom — the
8971
9124
  // three profiles the plural form was added for. (#129/#130)
8972
- hasIdentityKey: !!p10.identityKey || !!p10.identityKeys,
8973
- hasIdentityKeys: !!p10.identityKeys
9125
+ hasIdentityKey: !!p9.identityKey || !!p9.identityKeys,
9126
+ hasIdentityKeys: !!p9.identityKeys
8974
9127
  })),
8975
9128
  total: profiles.length,
8976
9129
  _hint: profiles.length > 0 ? "Use a built-in profile: one --agent sync init <platform> <model>" : "No built-in profiles found. Use sync init to auto-infer from action knowledge."
@@ -8984,13 +9137,13 @@ async function syncProfilesCommand(platform) {
8984
9137
  );
8985
9138
  return;
8986
9139
  }
8987
- for (const p10 of profiles) {
9140
+ for (const p9 of profiles) {
8988
9141
  const extras = [];
8989
- if (p10.enrich) extras.push("enrich");
8990
- if (p10.identityKey || p10.identityKeys) extras.push("identity");
8991
- if (p10.dateFilter) extras.push("incremental");
9142
+ if (p9.enrich) extras.push("enrich");
9143
+ if (p9.identityKey || p9.identityKeys) extras.push("identity");
9144
+ if (p9.dateFilter) extras.push("incremental");
8992
9145
  const tags = extras.length > 0 ? ` ${pc11.dim(`[${extras.join(", ")}]`)}` : "";
8993
- console.log(` ${pc11.bold(`${p10.platform}/${p10.model}`.padEnd(35))} ${p10.description}${tags}`);
9146
+ console.log(` ${pc11.bold(`${p9.platform}/${p9.model}`.padEnd(35))} ${p9.description}${tags}`);
8994
9147
  }
8995
9148
  console.log(`
8996
9149
  ${profiles.length} built-in profile(s). Run ${pc11.bold("one sync init <platform> <model>")} to use one.`);
@@ -9101,7 +9254,7 @@ async function syncInitCommand(platform, model, options) {
9101
9254
  } catch {
9102
9255
  }
9103
9256
  }
9104
- const hint = isComplete ? testReport?.ok ? `Profile complete and validated. Run: one sync run ${platform} --models ${model}` : `Profile complete but test had issues \u2014 check the test report below.` : actionId ? `Fill remaining FILL_IN fields, then: one sync test ${platform}/${model}` : `Action ID not resolved. Run: one --agent actions search ${platform} "list ${model}" -t execute`;
9257
+ const hint = isComplete ? testReport?.ok ? `Profile complete and validated. Run: one sync run ${platform} --models ${model}` : `Profile complete but test had issues \u2014 check the test report below.` : actionId ? `Fill remaining FILL_IN fields, then: one sync test ${platform}/${model}` : `Action ID not resolved. Run: one --agent actions find ${platform} "list ${model}" -t knowledge`;
9105
9258
  if (isAgentMode()) {
9106
9259
  json({
9107
9260
  ...template,
@@ -9249,11 +9402,11 @@ async function syncTestCommand(platformModel, options = {}) {
9249
9402
  console.log(` ${pc11.dim("text:")} ${searchablePreview.text.slice(0, 300)}${searchablePreview.length > 300 ? pc11.dim(" \u2026") : ""}`);
9250
9403
  if (searchablePreview.paths) {
9251
9404
  console.log(` ${pc11.dim("paths:")} ${pc11.dim('(hit rate across all samples \u2014 differentiates "wrong path" from "field sometimes missing")')}`);
9252
- for (const p10 of searchablePreview.paths) {
9253
- const rate = `${p10.hits}/${p10.total}`;
9254
- const mark = p10.hits === p10.total ? pc11.green("\u2713") : p10.hits === 0 ? pc11.red("\u2717") : pc11.yellow("~");
9255
- const trailer = p10.sample ? pc11.dim(` \u2192 "${p10.sample}"`) : p10.hits === 0 ? pc11.dim(" (no sample matched \u2014 typo, or field never populated in this page)") : "";
9256
- console.log(` ${mark} ${rate.padStart(5)} ${p10.path}${trailer}`);
9405
+ for (const p9 of searchablePreview.paths) {
9406
+ const rate = `${p9.hits}/${p9.total}`;
9407
+ const mark = p9.hits === p9.total ? pc11.green("\u2713") : p9.hits === 0 ? pc11.red("\u2717") : pc11.yellow("~");
9408
+ const trailer = p9.sample ? pc11.dim(` \u2192 "${p9.sample}"`) : p9.hits === 0 ? pc11.dim(" (no sample matched \u2014 typo, or field never populated in this page)") : "";
9409
+ console.log(` ${mark} ${rate.padStart(5)} ${p9.path}${trailer}`);
9257
9410
  }
9258
9411
  } else {
9259
9412
  console.log(` ${pc11.yellow("note:")} no memory.searchable declared \u2014 using the default walker (walks every field, often noisy).`);
@@ -9273,10 +9426,10 @@ function buildSearchablePreview(profile, samples) {
9273
9426
  const perPathAgg = paths.map((path14) => ({ path: path14, hits: 0, total: samples.length, sample: "" }));
9274
9427
  for (const record of samples) {
9275
9428
  const { paths: perPath } = extractSearchableFromPaths(record, paths);
9276
- perPath.forEach((p10, i) => {
9277
- if (p10.found) {
9429
+ perPath.forEach((p9, i) => {
9430
+ if (p9.found) {
9278
9431
  perPathAgg[i].hits++;
9279
- if (!perPathAgg[i].sample) perPathAgg[i].sample = p10.sample;
9432
+ if (!perPathAgg[i].sample) perPathAgg[i].sample = p9.sample;
9280
9433
  }
9281
9434
  });
9282
9435
  }
@@ -9290,16 +9443,16 @@ async function syncRunCommand(platform, options) {
9290
9443
  const api = getApi();
9291
9444
  const profiles = listProfiles(platform);
9292
9445
  const targetModels = options.models;
9293
- const toSync = targetModels ? profiles.filter((p10) => targetModels.includes(p10.model)) : profiles;
9446
+ const toSync = targetModels ? profiles.filter((p9) => targetModels.includes(p9.model)) : profiles;
9294
9447
  if (toSync.length === 0) {
9295
9448
  error(
9296
9449
  `No sync profiles found for ${platform}` + (targetModels ? ` with models: ${targetModels.join(", ")}` : "") + `. Run 'one sync init ${platform} <model> --config ...' first.`
9297
9450
  );
9298
9451
  }
9299
9452
  if (!options.dryRun) {
9300
- await maybeAutoMigrateLegacy(platform, toSync.map((p10) => p10.model));
9453
+ await maybeAutoMigrateLegacy(platform, toSync.map((p9) => p9.model));
9301
9454
  }
9302
- const profileDrift = toSync.map((p10) => ({ model: p10.model, missing: findMissingBuiltinCapabilities(platform, p10.model, p10) })).filter((d) => d.missing.length > 0);
9455
+ const profileDrift = toSync.map((p9) => ({ model: p9.model, missing: findMissingBuiltinCapabilities(platform, p9.model, p9) })).filter((d) => d.missing.length > 0);
9303
9456
  if (profileDrift.length > 0 && !isAgentMode()) {
9304
9457
  for (const d of profileDrift) {
9305
9458
  console.log(
@@ -9347,8 +9500,8 @@ async function syncRunCommand(platform, options) {
9347
9500
  return;
9348
9501
  }
9349
9502
  for (const r of results) {
9350
- const status = r.status === "complete" ? pc11.green("complete") : r.status === "dry-run" ? pc11.yellow("dry-run") : pc11.red("failed");
9351
- console.log(` ${pc11.bold(r.model)} \u2014 ${r.recordsSynced} records, ${r.pagesProcessed} pages, ${r.duration} [${status}]`);
9503
+ const status2 = r.status === "complete" ? pc11.green("complete") : r.status === "dry-run" ? pc11.yellow("dry-run") : pc11.red("failed");
9504
+ console.log(` ${pc11.bold(r.model)} \u2014 ${r.recordsSynced} records, ${r.pagesProcessed} pages, ${r.duration} [${status2}]`);
9352
9505
  if (r.reconcileSkipped) {
9353
9506
  console.log(` ${pc11.yellow("--full-refresh reconcile skipped \u2014 pagination truncated (e.g. --max-pages). Re-run without the cap to prune stale rows.")}`);
9354
9507
  }
@@ -9475,8 +9628,8 @@ async function syncDeleteCommand(platformModel, options) {
9475
9628
  return;
9476
9629
  }
9477
9630
  if (!options.yes && !isAgentMode()) {
9478
- const confirmed = await p7.confirm({ message: `Delete ${preview.count} record(s) from ${platform}/${model}?` });
9479
- if (p7.isCancel(confirmed) || !confirmed) {
9631
+ const confirmed = await p6.confirm({ message: `Delete ${preview.count} record(s) from ${platform}/${model}?` });
9632
+ if (p6.isCancel(confirmed) || !confirmed) {
9480
9633
  db.close();
9481
9634
  cancel("Cancelled.");
9482
9635
  return;
@@ -9518,11 +9671,11 @@ async function maybeAutoMigrateLegacy(platform, models) {
9518
9671
  await memMigrateCommand3({ platform, yes: true });
9519
9672
  return;
9520
9673
  }
9521
- const shouldMigrate = await p7.confirm({
9674
+ const shouldMigrate = await p6.confirm({
9522
9675
  message: `Found legacy .one/sync/data/${platform}.db (${dbSize}) with no corresponding memory records. Migrate into the unified memory store before syncing?`,
9523
9676
  initialValue: true
9524
9677
  });
9525
- if (p7.isCancel(shouldMigrate) || !shouldMigrate) return;
9678
+ if (p6.isCancel(shouldMigrate) || !shouldMigrate) return;
9526
9679
  const { memMigrateCommand: memMigrateCommand2 } = await import("./migrate-TACDLGPD.js");
9527
9680
  await memMigrateCommand2({ platform, yes: true });
9528
9681
  }
@@ -9586,14 +9739,14 @@ async function syncListCommand(platform) {
9586
9739
  const state = await readSyncState();
9587
9740
  const { getBackend: getBackend2 } = await import("./runtime-SX36HGBA.js");
9588
9741
  const backend = await getBackend2();
9589
- const syncs = await Promise.all(profiles.map(async (p10) => {
9590
- const modelState = state[p10.platform]?.[p10.model];
9591
- const type = `${p10.platform}/${p10.model}`;
9742
+ const syncs = await Promise.all(profiles.map(async (p9) => {
9743
+ const modelState = state[p9.platform]?.[p9.model];
9744
+ const type = `${p9.platform}/${p9.model}`;
9592
9745
  const totalRecords = await backend.count(type, { status: "active" }).catch(() => 0);
9593
- const legacyDbSize = getDatabaseSize(p10.platform);
9746
+ const legacyDbSize = getDatabaseSize(p9.platform);
9594
9747
  return {
9595
- platform: p10.platform,
9596
- model: p10.model,
9748
+ platform: p9.platform,
9749
+ model: p9.model,
9597
9750
  lastSync: modelState?.lastSync ?? null,
9598
9751
  totalRecords,
9599
9752
  pagesProcessed: modelState?.pagesProcessed ?? 0,
@@ -9613,10 +9766,10 @@ async function syncListCommand(platform) {
9613
9766
  return;
9614
9767
  }
9615
9768
  for (const s of syncs) {
9616
- const status = s.status === "idle" ? pc11.green("idle") : s.status === "syncing" ? pc11.yellow(`syncing \u2014 page ${s.pagesProcessed}`) : pc11.red("failed");
9769
+ const status2 = s.status === "idle" ? pc11.green("idle") : s.status === "syncing" ? pc11.yellow(`syncing \u2014 page ${s.pagesProcessed}`) : pc11.red("failed");
9617
9770
  const legacy = s.legacyDbSize && s.legacyDbSize !== "0 B" ? pc11.yellow(` legacy .db ${s.legacyDbSize}`) : "";
9618
9771
  console.log(
9619
- ` ${pc11.bold(`${s.platform}/${s.model}`.padEnd(35))} ${String(s.totalRecords).padStart(8)} records ${status} ${pc11.dim(s.lastSync ? `last: ${s.lastSync}` : "never synced")}` + legacy
9772
+ ` ${pc11.bold(`${s.platform}/${s.model}`.padEnd(35))} ${String(s.totalRecords).padStart(8)} records ${status2} ${pc11.dim(s.lastSync ? `last: ${s.lastSync}` : "never synced")}` + legacy
9620
9773
  );
9621
9774
  }
9622
9775
  }
@@ -9624,7 +9777,7 @@ async function syncRemoveCommand(platform, options) {
9624
9777
  const modelList = options.models?.split(",").map((m) => m.trim());
9625
9778
  const preview = [];
9626
9779
  const profiles = listProfiles(platform);
9627
- const targetModels = modelList ?? profiles.map((p10) => p10.model);
9780
+ const targetModels = modelList ?? profiles.map((p9) => p9.model);
9628
9781
  try {
9629
9782
  if (targetModels.length > 0) {
9630
9783
  const db = await openDatabase(platform);
@@ -9636,14 +9789,14 @@ async function syncRemoveCommand(platform, options) {
9636
9789
  } catch {
9637
9790
  for (const model of targetModels) preview.push({ model, records: 0 });
9638
9791
  }
9639
- const totalRecords = preview.reduce((sum, p10) => sum + p10.records, 0);
9792
+ const totalRecords = preview.reduce((sum, p9) => sum + p9.records, 0);
9640
9793
  const dbSize = getDatabaseSize(platform);
9641
9794
  if (options.dryRun) {
9642
9795
  if (isAgentMode()) {
9643
9796
  json({ dryRun: true, platform, models: preview, totalRecords, dbSize });
9644
9797
  } else {
9645
9798
  note(
9646
- preview.map((p10) => ` ${p10.model.padEnd(30)} ${String(p10.records).padStart(8)} records`).join("\n") + `
9799
+ preview.map((p9) => ` ${p9.model.padEnd(30)} ${String(p9.records).padStart(8)} records`).join("\n") + `
9647
9800
 
9648
9801
  Total: ${totalRecords} records across ${preview.length} model(s), ${dbSize} on disk`,
9649
9802
  `Would remove from ${platform}`
@@ -9653,10 +9806,10 @@ async function syncRemoveCommand(platform, options) {
9653
9806
  }
9654
9807
  if (!options.yes && !isAgentMode()) {
9655
9808
  const target = modelList ? `${platform}/${modelList.join(", ")}` : `all synced data for ${platform}`;
9656
- const confirmed = await p7.confirm({
9809
+ const confirmed = await p6.confirm({
9657
9810
  message: `Remove ${target}? (${totalRecords} records, ${dbSize} on disk)`
9658
9811
  });
9659
- if (p7.isCancel(confirmed) || !confirmed) {
9812
+ if (p6.isCancel(confirmed) || !confirmed) {
9660
9813
  cancel("Cancelled.");
9661
9814
  return;
9662
9815
  }
@@ -9891,7 +10044,7 @@ function registerSyncSubcommands(sync) {
9891
10044
  }
9892
10045
 
9893
10046
  // src/commands/mem/init.ts
9894
- import * as p8 from "@clack/prompts";
10047
+ import * as p7 from "@clack/prompts";
9895
10048
  async function memInitCommand(flags) {
9896
10049
  if (!readConfig()) {
9897
10050
  error("Run `one init` first to configure the base One CLI before `one mem init`.");
@@ -9900,11 +10053,11 @@ async function memInitCommand(flags) {
9900
10053
  if (isAgentMode()) {
9901
10054
  error("Memory is already configured. Pass --force to overwrite, or use `one mem config` to adjust.");
9902
10055
  }
9903
- const shouldOverwrite = flags.yes ?? await p8.confirm({
10056
+ const shouldOverwrite = flags.yes ?? await p7.confirm({
9904
10057
  message: "Memory is already configured. Overwrite the current config?",
9905
10058
  initialValue: false
9906
10059
  });
9907
- if (p8.isCancel(shouldOverwrite) || !shouldOverwrite) {
10060
+ if (p7.isCancel(shouldOverwrite) || !shouldOverwrite) {
9908
10061
  outro("Aborted. Run `one mem config` to adjust specific fields.");
9909
10062
  return;
9910
10063
  }
@@ -9954,7 +10107,7 @@ Run \`one mem doctor\` for a detailed report.`,
9954
10107
  async function interactiveInit(flags) {
9955
10108
  intro("one mem init");
9956
10109
  const plugins = listBackendPlugins();
9957
- const backend = flags.backend ?? await p8.select({
10110
+ const backend = flags.backend ?? await p7.select({
9958
10111
  message: "Where should memory live?",
9959
10112
  options: plugins.map((plug) => ({
9960
10113
  value: plug.name,
@@ -9963,26 +10116,26 @@ async function interactiveInit(flags) {
9963
10116
  })),
9964
10117
  initialValue: "embedded-postgres"
9965
10118
  });
9966
- if (p8.isCancel(backend)) error("Cancelled.");
10119
+ if (p7.isCancel(backend)) error("Cancelled.");
9967
10120
  const perBackend = {};
9968
10121
  if (backend === "embedded-postgres") {
9969
- const dataDir = flags.dbPath ?? await p8.text({
10122
+ const dataDir = flags.dbPath ?? await p7.text({
9970
10123
  message: "Postgres data directory (leave blank for default)",
9971
10124
  placeholder: "~/.one/pg",
9972
10125
  initialValue: ""
9973
10126
  });
9974
- if (p8.isCancel(dataDir)) error("Cancelled.");
10127
+ if (p7.isCancel(dataDir)) error("Cancelled.");
9975
10128
  if (dataDir) perBackend["embedded-postgres"] = { dataDir };
9976
10129
  } else if (backend === "postgres") {
9977
- const connectionString = flags.connectionString ?? await p8.text({
10130
+ const connectionString = flags.connectionString ?? await p7.text({
9978
10131
  message: "Postgres connection string",
9979
10132
  placeholder: "postgres://user:pass@host:5432/dbname",
9980
10133
  validate: (v) => v ? void 0 : "Connection string is required"
9981
10134
  });
9982
- if (p8.isCancel(connectionString)) error("Cancelled.");
10135
+ if (p7.isCancel(connectionString)) error("Cancelled.");
9983
10136
  perBackend.postgres = { connectionString };
9984
10137
  }
9985
- const provider = flags.embedding ?? await p8.select({
10138
+ const provider = flags.embedding ?? await p7.select({
9986
10139
  message: "Enable embeddings (semantic search)?",
9987
10140
  options: [
9988
10141
  { value: "openai", label: "Yes, via OpenAI", hint: "requires an API key" },
@@ -9990,7 +10143,7 @@ async function interactiveInit(flags) {
9990
10143
  ],
9991
10144
  initialValue: "none"
9992
10145
  });
9993
- if (p8.isCancel(provider)) error("Cancelled.");
10146
+ if (p7.isCancel(provider)) error("Cancelled.");
9994
10147
  let apiKey;
9995
10148
  let embedOnAdd = DEFAULT_MEMORY_CONFIG.defaults.embedOnAdd;
9996
10149
  let embedOnSync = DEFAULT_MEMORY_CONFIG.defaults.embedOnSync;
@@ -9999,25 +10152,25 @@ async function interactiveInit(flags) {
9999
10152
  if (flags.openaiKey) {
10000
10153
  apiKey = flags.openaiKey;
10001
10154
  } else {
10002
- const entered = await p8.password({
10155
+ const entered = await p7.password({
10003
10156
  message: "OpenAI API key",
10004
10157
  mask: "\u2022",
10005
10158
  validate: (v) => v || envKey ? void 0 : "Required (or set OPENAI_API_KEY)"
10006
10159
  });
10007
- if (p8.isCancel(entered)) error("Cancelled.");
10160
+ if (p7.isCancel(entered)) error("Cancelled.");
10008
10161
  apiKey = entered || envKey;
10009
10162
  }
10010
- const embedAdd = flags.embedOnAdd ?? await p8.confirm({
10163
+ const embedAdd = flags.embedOnAdd ?? await p7.confirm({
10011
10164
  message: "Embed user memories (mem add) by default?",
10012
10165
  initialValue: true
10013
10166
  });
10014
- if (p8.isCancel(embedAdd)) error("Cancelled.");
10167
+ if (p7.isCancel(embedAdd)) error("Cancelled.");
10015
10168
  embedOnAdd = embedAdd;
10016
- const embedSync = flags.embedOnSync ?? await p8.confirm({
10169
+ const embedSync = flags.embedOnSync ?? await p7.confirm({
10017
10170
  message: "Embed synced records by default? (overridable per profile)",
10018
10171
  initialValue: false
10019
10172
  });
10020
- if (p8.isCancel(embedSync)) error("Cancelled.");
10173
+ if (p7.isCancel(embedSync)) error("Cancelled.");
10021
10174
  embedOnSync = embedSync;
10022
10175
  }
10023
10176
  return {
@@ -10238,9 +10391,9 @@ function redactSecrets(cfg) {
10238
10391
  function getPath(obj, path14) {
10239
10392
  const parts = path14.split(".");
10240
10393
  let cur = obj;
10241
- for (const part of parts) {
10394
+ for (const part2 of parts) {
10242
10395
  if (cur == null || typeof cur !== "object") return void 0;
10243
- cur = cur[part];
10396
+ cur = cur[part2];
10244
10397
  }
10245
10398
  return cur;
10246
10399
  }
@@ -10248,9 +10401,9 @@ function setPath(obj, path14, value) {
10248
10401
  const parts = path14.split(".");
10249
10402
  let cur = obj;
10250
10403
  for (let i = 0; i < parts.length - 1; i++) {
10251
- const part = parts[i];
10252
- if (cur[part] == null || typeof cur[part] !== "object") cur[part] = {};
10253
- cur = cur[part];
10404
+ const part2 = parts[i];
10405
+ if (cur[part2] == null || typeof cur[part2] !== "object") cur[part2] = {};
10406
+ cur = cur[part2];
10254
10407
  }
10255
10408
  cur[parts[parts.length - 1]] = value;
10256
10409
  return obj;
@@ -10259,9 +10412,9 @@ function unsetPath(obj, path14) {
10259
10412
  const parts = path14.split(".");
10260
10413
  let cur = obj;
10261
10414
  for (let i = 0; i < parts.length - 1; i++) {
10262
- const part = parts[i];
10263
- if (cur[part] == null || typeof cur[part] !== "object") return obj;
10264
- cur = cur[part];
10415
+ const part2 = parts[i];
10416
+ if (cur[part2] == null || typeof cur[part2] !== "object") return obj;
10417
+ cur = cur[part2];
10265
10418
  }
10266
10419
  delete cur[parts[parts.length - 1]];
10267
10420
  return obj;
@@ -10375,10 +10528,10 @@ async function memListCommand(type, flags) {
10375
10528
  const backend = await getBackend();
10376
10529
  const limit = flags.limit ? parsePositiveInt(flags.limit, 100, "limit") : 100;
10377
10530
  const offset = flags.offset ? parsePositiveInt(flags.offset, 0, "offset") : 0;
10378
- const status = flags.status ?? "active";
10531
+ const status2 = flags.status ?? "active";
10379
10532
  const [records, total] = await Promise.all([
10380
- backend.list(type, { limit, offset, status }),
10381
- backend.count(type, { status })
10533
+ backend.list(type, { limit, offset, status: status2 }),
10534
+ backend.count(type, { status: status2 })
10382
10535
  ]);
10383
10536
  if (isAgentMode()) {
10384
10537
  json({ items: records, returned: records.length, total, limit, offset });
@@ -10581,7 +10734,7 @@ async function memDoctorCommand() {
10581
10734
  return emit(checks, { vectorSearchAvailable: true });
10582
10735
  }
10583
10736
  checks.push({ name: "memory config exists", ok: true, detail: `backend=${cfg.backend}` });
10584
- const available = listBackendPlugins().map((p10) => p10.name);
10737
+ const available = listBackendPlugins().map((p9) => p9.name);
10585
10738
  if (!available.includes(cfg.backend)) {
10586
10739
  checks.push({
10587
10740
  name: `backend plugin "${cfg.backend}" resolves`,
@@ -10712,10 +10865,10 @@ async function memExportCommand(outfile) {
10712
10865
  const pageSize = 500;
10713
10866
  let written = 0;
10714
10867
  for (const type of all) {
10715
- for (const status of ["active", "archived"]) {
10868
+ for (const status2 of ["active", "archived"]) {
10716
10869
  let offset = 0;
10717
10870
  while (true) {
10718
- const page = await backend.list(type, { limit: pageSize, offset, status });
10871
+ const page = await backend.list(type, { limit: pageSize, offset, status: status2 });
10719
10872
  for (const r of page) {
10720
10873
  await writeLine(stream, JSON.stringify(r) + "\n");
10721
10874
  written++;
@@ -10925,12 +11078,12 @@ async function memReindexSearchableCommand(flags) {
10925
11078
  // src/commands/mem.ts
10926
11079
  function memStatusCommand() {
10927
11080
  const cfg = getMemoryConfig();
10928
- const plugins = listBackendPlugins().map((p10) => ({
10929
- name: p10.name,
10930
- description: p10.description,
10931
- version: p10.version,
10932
- schemaVersion: p10.schemaVersion,
10933
- capabilities: p10.capabilities
11081
+ const plugins = listBackendPlugins().map((p9) => ({
11082
+ name: p9.name,
11083
+ description: p9.description,
11084
+ version: p9.version,
11085
+ schemaVersion: p9.schemaVersion,
11086
+ capabilities: p9.capabilities
10934
11087
  }));
10935
11088
  const upgrade = semanticSearchUpgradeHint();
10936
11089
  const payload = {
@@ -11052,9 +11205,6 @@ async function cacheUpdateAllCommand() {
11052
11205
  error("Not configured. Run `one init` first.");
11053
11206
  }
11054
11207
  const api = new OneApi(apiKey, getApiBase());
11055
- const ac = getAccessControlFromAllSources();
11056
- const permissions = ac.permissions || "admin";
11057
- const actionIds = ac.actionIds || ["*"];
11058
11208
  const entries = listCacheEntries();
11059
11209
  if (entries.length === 0) {
11060
11210
  if (isAgentMode()) {
@@ -11071,44 +11221,9 @@ async function cacheUpdateAllCommand() {
11071
11221
  const errors = [];
11072
11222
  for (const e of entries) {
11073
11223
  try {
11074
- if (e.type === "knowledge") {
11075
- const result = await api.getActionDetailsWithMeta(e.entry.key);
11076
- const newEntry = makeCacheEntry(e.entry.key, result.data, result.etag);
11077
- writeCache(e.filePath, newEntry);
11078
- updated++;
11079
- } else {
11080
- const data = e.entry.data;
11081
- if (data?.platform && data?.query) {
11082
- const searchType = data.searchType ?? "knowledge";
11083
- const result = await api.searchActionsWithMeta(
11084
- data.platform,
11085
- data.query,
11086
- searchType,
11087
- e.entry.etag ?? void 0
11088
- );
11089
- if (result.status === 304) {
11090
- writeCache(e.filePath, { ...e.entry, cachedAt: (/* @__PURE__ */ new Date()).toISOString() });
11091
- } else {
11092
- let actions2 = result.data;
11093
- actions2 = filterByPermissions(actions2, permissions);
11094
- actions2 = actions2.filter((a) => isActionAllowed(a.systemId, actionIds));
11095
- const cleaned = actions2.map((a) => ({
11096
- actionId: a.systemId,
11097
- title: a.title,
11098
- method: a.method,
11099
- path: a.path
11100
- }));
11101
- writeCache(e.filePath, makeCacheEntry(
11102
- e.entry.key,
11103
- { actions: cleaned, platform: data.platform, query: data.query, searchType },
11104
- result.etag
11105
- ));
11106
- }
11107
- } else {
11108
- writeCache(e.filePath, { ...e.entry, cachedAt: (/* @__PURE__ */ new Date()).toISOString() });
11109
- }
11110
- updated++;
11111
- }
11224
+ const result = await api.getActionDetailsWithMeta(e.entry.key);
11225
+ writeCache(e.filePath, makeCacheEntry(e.entry.key, result.data, result.etag));
11226
+ updated++;
11112
11227
  } catch (err) {
11113
11228
  failed++;
11114
11229
  errors.push({
@@ -11174,14 +11289,14 @@ Before using any feature, read its guide section first: \`one guide actions\`, \
11174
11289
  ## Features
11175
11290
 
11176
11291
  ### 1. Actions \u2014 Execute API calls on 750+ platforms
11177
- Search for actions, read their docs, and execute them. This is the core workflow.
11292
+ Find the actions a task needs with their docs, in one call, then execute them. This is the core workflow.
11178
11293
 
11179
11294
  **Quick start:**
11180
11295
  \`\`\`bash
11181
11296
  one --agent connection list # See connected platforms + your access on each
11182
11297
  one --agent connection delete <connection-key> # Remove a connection
11183
- one --agent actions search <platform> "<query>" -t execute # Find an action
11184
- one --agent actions knowledge <platform> <actionId> # Read docs (REQUIRED)
11298
+ one --agent actions find <platform> "<intent>" [<platform> "<intent>" ...] --task "<the job, in general terms>" # Find every action, with its docs (READ them)
11299
+ one --agent actions load <actionId> --section "<name>" # More of a doc: a section it left out, --full, --toc
11185
11300
  one --agent actions execute <platform> <actionId> <key> -d '{}' # Execute it
11186
11301
  \`\`\`
11187
11302
 
@@ -11244,7 +11359,7 @@ one --agent relay deliveries --endpoint-id <id> # Check delivery
11244
11359
  - \`passthrough\` actions map webhook fields to another platform's API using Handlebars: \`{{payload.data.object.email}}\`
11245
11360
  - Template context: \`{{relayEventId}}\`, \`{{platform}}\`, \`{{eventType}}\`, \`{{payload}}\`, \`{{timestamp}}\`, \`{{connectionId}}\`
11246
11361
  - \`--create-webhook\` auto-registers the webhook URL with the source platform
11247
- - Use \`actions knowledge\` to learn both the incoming payload shape AND the destination API shape before building templates
11362
+ - Use \`actions find\` (and \`actions load\` for more) to learn both the incoming payload shape AND the destination API shape before building templates
11248
11363
 
11249
11364
  ### 4. Memory + Sync \u2014 Unified store with hybrid FTS + semantic search
11250
11365
  One ships a local memory store (a real Postgres process bootstrapped on demand via the bundled \`embedded-postgres\` plugin, with a \`postgres\` plugin for remote/self-hosted) that backs both user-authored notes (\`one mem add\`) and synced platform data (\`one sync run\`). Auto-initializes on first use \u2014 no separate install step. Run \`one guide memory\` and \`one guide sync\` for the full references.
@@ -11253,7 +11368,7 @@ One ships a local memory store (a real Postgres process bootstrapped on demand v
11253
11368
 
11254
11369
  Request specific sections:
11255
11370
  - \`one guide overview\` \u2014 This section
11256
- - \`one guide actions\` \u2014 Actions reference (search, knowledge, execute)
11371
+ - \`one guide actions\` \u2014 Actions reference (find, load, execute)
11257
11372
  - \`one guide flows\` \u2014 Workflow engine reference (step types, selectors, examples)
11258
11373
  - \`one guide relay\` \u2014 Webhook relay reference (templates, passthrough actions)
11259
11374
  - \`one guide cache\` \u2014 Cache management (TTL, flags, commands)
@@ -11264,7 +11379,7 @@ Request specific sections:
11264
11379
 
11265
11380
  - **Always use \`--agent\` flag** for structured JSON output
11266
11381
  - Platform names are **lowercase**; multi-word names use dashes (e.g., \`hubspot\`, \`google-calendar\`)
11267
- - Always use the **exact action ID** from search results \u2014 don't guess
11382
+ - Always use the **exact action ID** from a find answer \u2014 don't guess
11268
11383
  - Always read **knowledge** before executing any action
11269
11384
  - Connection keys come from \`one connection list\` \u2014 don't hardcode them
11270
11385
  - \`connection list\` also reports an \`access\` field per connection (\`full\` / \`methods\` / \`actions\`) \u2014 read it before planning so you don't propose an action the access config will reject
@@ -11272,9 +11387,9 @@ Request specific sections:
11272
11387
  `;
11273
11388
  var GUIDE_ACTIONS = `# One Actions \u2014 Reference
11274
11389
 
11275
- ## Workflow: search \u2192 knowledge \u2192 execute
11390
+ ## Workflow: find \u2192 execute
11276
11391
 
11277
- Always follow this sequence. Never skip the knowledge step.
11392
+ Always follow this sequence. Never execute without reading the action's documentation, which \`actions find\` returns.
11278
11393
 
11279
11394
  ### 1. List Connections
11280
11395
 
@@ -11288,9 +11403,9 @@ Returns platforms, status, connection keys, tags, and an \`access\` field per co
11288
11403
  |----------|---------|
11289
11404
  | \`{"policy": "full"}\` | Every action on the connection |
11290
11405
  | \`{"policy": "methods", "methods": ["GET"]}\` | Only actions with these HTTP methods will execute |
11291
- | \`{"policy": "actions", "actions": [{"actionId", "title", "method"}]}\` | Only these exact actions \u2014 use them directly, skip \`actions search\` |
11406
+ | \`{"policy": "actions", "actions": [{"actionId", "title", "method"}]}\` | Only these exact actions \u2014 use them directly: \`actions load <actionId>\` reads their docs, no find needed |
11292
11407
 
11293
- Also present when relevant: \`knowledgeOnly: true\` (execution disabled \u2014 read knowledge and write code instead), \`unresolvedActionIds\` (allowlisted ids that could not be looked up), and \`accessHint\` (a one-line summary of the restriction).
11408
+ Also present when relevant: \`knowledgeOnly: true\` (execution disabled \u2014 read the docs and write code instead), \`unresolvedActionIds\` (allowlisted ids that could not be looked up), and \`accessHint\` (a one-line summary of the restriction).
11294
11409
 
11295
11410
  Read \`access\` before planning \u2014 it prevents proposing an action the config will reject. Change it with \`one config\`.
11296
11411
 
@@ -11302,60 +11417,72 @@ one --agent connection delete <connection-key>
11302
11417
 
11303
11418
  Removes a connection by its key. In agent mode, returns \`{"deleted": true, "platform": "...", "key": "..."}\`. The connection key comes from \`one connection list\`.
11304
11419
 
11305
- ### 2. Search Actions
11420
+ ### 2. Find Actions
11306
11421
 
11307
11422
  \`\`\`bash
11308
- one --agent actions search <platform> "<query>" -t execute
11423
+ one --agent actions find <platform> "<intent>" [<platform> "<intent>" ...] --task "<the job, in general terms>"
11309
11424
  \`\`\`
11310
11425
 
11311
- - Use \`-t execute\` when the user wants to perform an action
11312
- - Use \`-t knowledge\` (default) for documentation/code generation
11313
- - Returns up to 5 matching actions with IDs, methods, and paths
11426
+ One call for the whole task: one platform and intent pair per operation, on any platforms (up to 10). One's decision model picks the action for each and returns it **with its documentation** \u2014 required fields, validation rules, request structure. **Read it before execute.**
11314
11427
 
11315
- ### 3. Get Knowledge
11316
-
11317
- \`\`\`bash
11318
- one --agent actions knowledge <platform> <actionId>
11319
- \`\`\`
11428
+ - **\`intent\` names the operation alone**, in a few words: \`"send a message to a channel"\`, not \`"post 'deploy done' in #eng"\`. IDs, names, and message text in the intent make the search miss.
11429
+ - **\`--task\`** (optional) is the whole job in one line, **in general terms**: what it does, without names, addresses, IDs, or message text. It helps choose between similar actions.
11430
+ - **\`-t knowledge\`** searches the catalog for writing code and building flows and relays, which includes the platform's own (passthrough) endpoints; the default, \`-t execute\`, is the catalog for running actions now. Knowledge-only mode always uses \`knowledge\`.
11431
+ - **\`--ai-model\`** (optional) names the model running the CLI (e.g. \`claude-sonnet-5\`); it will be used to tune documentation per model.
11432
+ - **\`--no-knowledge\`** (optional) lists the chosen actions without their documentation, when only the actionIds are needed. Load the documentation with \`actions load\` before executing.
11320
11433
 
11321
- Returns the API docs: required fields, validation rules, request structure. **REQUIRED before execute.** The output includes a CLI PARAMETER MAPPING section showing which flags to use.
11322
-
11323
- **In \`--agent\` mode this is a digest, not the whole document.** Large docs (most of their size is response shapes and optional-field tables) are trimmed to the sections needed to build a correct request: method/URL, headers, description, enforcement rules, required and optional parameters, sample request, gotchas, error handling. Everything else is listed in a table of contents so you can pull it on demand:
11434
+ In \`--agent\` mode:
11324
11435
 
11325
11436
  \`\`\`json
11326
11437
  {
11327
- "knowledge": "...digest markdown, ends with a notice naming the omitted sections...",
11328
- "method": "POST",
11329
- "title": "Create an Issue",
11330
- "truncated": true,
11331
- "sections": [
11332
- { "id": "response", "heading": "Response", "level": 2, "chars": 16483, "included": false },
11333
- { "id": "response-fields", "heading": "Response Fields", "level": 2, "chars": 3353, "included": false }
11438
+ "answers": [
11439
+ {
11440
+ "platform": "gmail",
11441
+ "intent": "send an email",
11442
+ "status": "Chosen with confidence 0.99.",
11443
+ "selector": "model",
11444
+ "confidence": 0.99,
11445
+ "selected": [
11446
+ { "actionId": "conn_mod_def::...", "title": "Send Email", "method": "POST", "path": "/v1/gmail/send-email",
11447
+ "knowledge": "...digest markdown, ends with the exact actions load command for what it left out...", "truncated": true }
11448
+ ],
11449
+ "alsoSelected": [],
11450
+ "runnerUp": { "actionId": "...", "title": "...", "method": "...", "path": "...", "knowledge": "...", "truncated": false },
11451
+ "alternatives": [ { "actionId": "...", "title": "...", "method": "...", "path": "..." } ]
11452
+ }
11334
11453
  ],
11335
- "omitted": 2,
11336
- "omittedChars": 19836,
11337
- "more": { "section": "one --agent actions knowledge <platform> <actionId> --section <id>[,<id>...]", "full": "..." }
11454
+ "guide": "Run an action with: one --agent actions execute <platform> <actionId> <connectionKey> ..."
11338
11455
  }
11339
11456
  \`\`\`
11340
11457
 
11341
- - \`truncated: false\` means you have the whole document \u2014 small docs are never trimmed, and no \`sections\` list is sent.
11342
- - \`sections\` lists only what was omitted. \`included\` is \`false\` or \`"partial"\` (an oversized essential section was cut; its text ends with a truncation marker). Included sections are simply the headings in the markdown.
11343
- - Load more by heading, id, or alias \u2014 several at once, comma-separated or repeated:
11458
+ - **\`selected\`** \u2014 the action(s) to use, documented. More than one means the intent needs them together (look up, then update).
11459
+ - **\`alsoSelected\`** \u2014 also needed, listed rather than documented to keep the answer small: \`actions load\` them.
11460
+ - **\`runnerUp\`** \u2014 only when the model was unsure: a **substitute** for the pick. Use one or the other, **never both**.
11461
+ - **\`alternatives\`** \u2014 other candidates, undocumented.
11462
+ - **\`status\`** \u2014 why: a confidence, *no action fits* (rephrase the intent by outcome, or check the platform), *the decision model was unavailable* (top search result: check it fits), *not allowed by this CLI* (the next allowed candidate stood in), or *allow none of them* (your access settings block the operation \u2014 rephrasing won't help).
11463
+ - **\`guide\`** \u2014 how to execute, stated once for every action.
11464
+ - \`truncated: false\` means \`knowledge\` is the whole document; small docs are never trimmed.
11344
11465
 
11345
- \`\`\`bash
11346
- one --agent actions knowledge <platform> <actionId> --section "Response Fields"
11347
- one --agent actions knowledge <platform> <actionId> --section response,optional
11348
- one --agent actions knowledge <platform> <actionId> --full
11349
- \`\`\`
11466
+ A large doc is a **digest**: the sections needed to build a correct request (method/URL, headers, description, enforcement rules, required and optional parameters, sample request, gotchas, error handling), then a notice naming what it left out with the exact command to load it.
11350
11467
 
11351
- Aliases: \`response\`, \`fields\`, \`optional\`, \`required\`, \`examples\`, \`errors\`, \`success\`, \`body\`, \`query\`, \`path\`, \`notes\`, \`behavior\`, \`gotchas\`. A parent section brings its subsections. Section requests are served from the local cache \u2014 no network call. An unknown name returns an error that lists every available section, so retry with one of those ids.
11468
+ In knowledge-only mode (\`one config\`), each pick comes back **whole**, with how to call it from code through the One Passthrough API, and \`guide\` is the Integration Code Guide.
11352
11469
 
11353
- A \`--section\` response carries \`requested\`, \`resolved\` (the ids each name matched \u2014 alias and prefix matches are visible here), and \`truncated: false\` (the requested sections are whole). It does not repeat the table of contents. On scraped mega-docs with hundreds of headings the digest's \`sections\` list is collapsed to the top levels (\`sectionsCollapsed: true\`, each entry's \`children\` counts the hidden ones); \`--toc\` returns the complete list without the document:
11470
+ Find reads documentation through the local cache, so a later \`actions execute\` of the same action makes a single API call.
11471
+
11472
+ ### 3. Load More of a Document
11354
11473
 
11355
11474
  \`\`\`bash
11356
- one --agent actions knowledge <platform> <actionId> --toc
11475
+ one --agent actions load <actionId> --section "Response Fields"
11476
+ one --agent actions load <actionId> --section response,optional
11477
+ one --agent actions load <actionId> --full
11478
+ one --agent actions load <actionId> --toc
11479
+ one --agent actions load <actionId> # the digest: how to read an alternative
11357
11480
  \`\`\`
11358
11481
 
11482
+ Up to 10 action ids at once; the flags apply to each. Aliases: \`response\`, \`fields\`, \`optional\`, \`required\`, \`examples\`, \`errors\`, \`success\`, \`body\`, \`query\`, \`path\`, \`notes\`, \`behavior\`, \`gotchas\`. A parent section brings its subsections. Loads are served from the local cache once a doc is cached. An unknown section name returns the list of available sections, so retry with one of those ids. \`--toc\` lists every section of the document (id, heading, size) without the text.
11483
+
11484
+ In \`--agent\` mode: \`{ "loaded": [ { "actionId", "title", "method", "path", "knowledge", "truncated" } | { "actionId", "error" } ], "guide": "..." }\`. An action your access settings refuse reads the same as one that doesn't exist.
11485
+
11359
11486
  ### 4. Execute
11360
11487
 
11361
11488
  \`\`\`bash
@@ -11375,7 +11502,7 @@ one --agent actions execute <platform> <actionId> <connectionKey> [options]
11375
11502
  - \`--output <path>\` \u2014 Save response to a file (for binary downloads like PDFs, images, documents). Text responses (text/plain, HTML, CSV, XML) render inline automatically \u2014 \`--output\` is only needed for genuinely binary payloads.
11376
11503
  - \`--no-cache\` \u2014 Bypass the cached action details and re-fetch them; the fresh details still refresh the cache (execution itself is never cached)
11377
11504
 
11378
- 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.
11505
+ Execute reuses the action details cached by \`actions find\` and \`actions load\` (method, path, schema), so in the standard find \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.
11379
11506
 
11380
11507
  **Do NOT** pass path or query parameters in \`-d\`. Use the correct flags.
11381
11508
 
@@ -11414,7 +11541,7 @@ All errors return JSON: \`{"error": "message"}\`. Check the \`error\` key.
11414
11541
 
11415
11542
  - Platform names are **lowercase**; multi-word names use dashes (e.g., \`hubspot\`, \`ship-station\`)
11416
11543
  - JSON flags use single quotes around the JSON to avoid shell escaping
11417
- - If search returns no results, try broader queries
11544
+ - If find says no action fits, rephrase the intent by outcome (\`"list invoices"\`, not an endpoint name) or check the platform name
11418
11545
  - Access control settings from \`one config\` may restrict execution
11419
11546
  `;
11420
11547
  var GUIDE_FLOWS = generateFlowGuide();
@@ -11529,9 +11656,9 @@ var GUIDE_CACHE = `# One Cache \u2014 Reference
11529
11656
 
11530
11657
  ## Overview
11531
11658
 
11532
- 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.
11659
+ The One CLI caches each action's details (docs, method, path, schema) locally, so repeated calls serve instantly from disk instead of hitting the API. \`actions find\` and \`actions load\` read documentation through this cache, and \`actions execute\` reuses it for its preflight lookup \u2014 in the standard find \u2192 execute flow, execute makes exactly one API call: the action itself. Find's picks themselves are not cached: they come from One's decision model on every call.
11533
11660
 
11534
- Cache location: \`~/.one/cache/knowledge/\` and \`~/.one/cache/search/\`
11661
+ Cache location: \`~/.one/cache/knowledge/\`
11535
11662
 
11536
11663
  ## How It Works
11537
11664
 
@@ -11539,7 +11666,7 @@ Cache location: \`~/.one/cache/knowledge/\` and \`~/.one/cache/search/\`
11539
11666
  - **Subsequent calls (within TTL)**: serves from cache instantly, no API call
11540
11667
  - **After TTL expires**: makes a conditional request (ETag). If content unchanged, refreshes the cache timestamp. If changed, writes fresh data.
11541
11668
  - **Network failure with stale cache**: serves the stale cache with a warning \u2014 never fails hard when a cache exists
11542
- - **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
11669
+ - **Shared preflight**: \`actions find\`, \`actions load\`, \`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 find, a flow run, and a later execute of the same action all reuse one cached lookup
11543
11670
 
11544
11671
  Default TTL: 3600 seconds (1 hour). Configure via \`ONE_CACHE_TTL\` env var or \`cacheTtl\` in \`~/.one/config.json\`.
11545
11672
 
@@ -11547,44 +11674,27 @@ Default TTL: 3600 seconds (1 hour). Configure via \`ONE_CACHE_TTL\` env var or \
11547
11674
 
11548
11675
  | Cached | Not Cached |
11549
11676
  |--------|-----------|
11550
- | \`actions knowledge\` (API docs, change infrequently) | \`actions execute\` responses (live data, always fresh) |
11551
- | \`actions search\` results | \`connection list\` (changes with add/remove) |
11677
+ | Action docs read by \`actions find\` / \`actions load\` (change infrequently) | \`actions execute\` responses (live data, always fresh) |
11678
+ | | \`actions find\` picks (the decision model answers every call) |
11679
+ | | \`connection list\` (changes with add/remove) |
11552
11680
  | Action details used by execute / flow / sync preflight (method, path, schema) | |
11553
11681
 
11554
- ## Agent Mode \`_cache\` Metadata
11682
+ ## Cache Status
11555
11683
 
11556
- In \`--agent\` mode, knowledge and search responses include a \`_cache\` field:
11557
-
11558
- \`\`\`json
11559
- {
11560
- "knowledge": "...",
11561
- "method": "POST",
11562
- "truncated": true,
11563
- "sections": [ ... ],
11564
- "_cache": {
11565
- "hit": true,
11566
- "age": 1423,
11567
- "fresh": true
11568
- }
11569
- }
11570
- \`\`\`
11571
-
11572
- Use this to programmatically decide whether to force-refresh.
11684
+ \`actions load --cache-status\` prints, for each action id, whether its details are cached, when, their age and TTL, whether they have expired, and their ETag, without fetching anything.
11573
11685
 
11574
11686
  ## Cache Flags
11575
11687
 
11576
11688
  \`\`\`bash
11577
11689
  # Skip cache, fetch fresh (result still gets cached for next time)
11578
- one --agent actions knowledge <platform> <actionId> --no-cache
11690
+ one --agent actions load <actionId> --no-cache
11691
+ one --agent actions find <platform> "<intent>" --no-cache
11579
11692
 
11580
11693
  # Check cache status without fetching
11581
- one --agent actions knowledge <platform> <actionId> --cache-status
11694
+ one --agent actions load <actionId> --cache-status
11582
11695
 
11583
11696
  # Sections and --full are served from the cache once the doc is cached
11584
- one --agent actions knowledge <platform> <actionId> --section "Response Fields"
11585
-
11586
- # Same for search
11587
- one --agent actions search <platform> "<query>" --no-cache
11697
+ one --agent actions load <actionId> --section "Response Fields"
11588
11698
 
11589
11699
  # Same for execute's action-details preflight (the action itself always runs live)
11590
11700
  one --agent actions execute <platform> <actionId> <key> --no-cache
@@ -11597,7 +11707,7 @@ In \`--agent\` mode, execute responses include \`"_preflight": {"cache": "hit"|"
11597
11707
  \`\`\`bash
11598
11708
  one cache list # List all cached entries with age and status
11599
11709
  one cache list --expired # List only expired entries
11600
- one cache clear # Delete all cached knowledge and search data
11710
+ one cache clear # Delete all cached action documentation
11601
11711
  one cache clear <actionId> # Delete one specific entry
11602
11712
  one cache update-all # Re-fetch fresh data for all cached entries
11603
11713
  \`\`\`
@@ -11860,7 +11970,7 @@ Why the block:
11860
11970
  enrichment locally \u2014 server-side fan-out on top of that creates 5xx, not value
11861
11971
 
11862
11972
  How to build a profile:
11863
- 1. \`one actions search <platform> "<model>"\` surfaces passthrough actions.
11973
+ 1. \`one actions find <platform> "list <model>" -t knowledge\` surfaces passthrough actions (the pick and its alternatives).
11864
11974
  \`sync init\`'s auto-infer also drops customs before offering choices.
11865
11975
  2. Prefer GET passthrough endpoints (e.g. /gmail/v1/users/{userId}/threads)
11866
11976
  over POST custom endpoints (e.g. /gmail/get-threads).
@@ -12292,7 +12402,7 @@ var TOPICS = [
12292
12402
  { topic: "actions", description: "Search, read docs, and execute platform actions" },
12293
12403
  { topic: "flows", description: "Build and execute multi-step workflows" },
12294
12404
  { topic: "relay", description: "Receive webhooks and forward to other platforms" },
12295
- { topic: "cache", description: "Local caching for knowledge and search responses" },
12405
+ { topic: "cache", description: "Local caching for action documentation" },
12296
12406
  { topic: "memory", description: "Unified memory store: notes, decisions, synced rows, semantic search" },
12297
12407
  { topic: "sync", description: "Sync platform data into memory for instant offline queries" },
12298
12408
  { topic: "all", description: "Complete guide (all topics combined)" }
@@ -12384,7 +12494,7 @@ function pairKey(a, b) {
12384
12494
  }
12385
12495
  function getWorkflowExamples(connectedPlatforms) {
12386
12496
  const results = [];
12387
- const platforms = connectedPlatforms.map((p10) => p10.toLowerCase());
12497
+ const platforms = connectedPlatforms.map((p9) => p9.toLowerCase());
12388
12498
  for (let i = 0; i < platforms.length; i++) {
12389
12499
  for (let j = i + 1; j < platforms.length; j++) {
12390
12500
  const key = pairKey(platforms[i], platforms[j]);
@@ -12501,17 +12611,17 @@ common mistakes to avoid. Never guess \u2014 read the skill, then act.
12501
12611
 
12502
12612
  ### Quick reference:
12503
12613
  - \`one --agent list\` \u2014 See connected platforms and connection keys
12504
- - \`one --agent actions search <platform> "<query>"\` \u2014 Find actions
12505
- - \`one --agent actions knowledge <platform> <actionId>\` \u2014 Read docs (REQUIRED before execute; a digest \u2014 add \`--section <name>\` or \`--full\` for more)
12614
+ - \`one --agent actions find <platform> "<intent>" [<platform> "<intent>" ...]\` \u2014 Find every action a task needs, with its docs (READ them before execute)
12615
+ - \`one --agent actions load <actionId> --section <name>\` \u2014 More of a doc (a digest names the exact command), or \`--full\`
12506
12616
  - \`one --agent actions execute <platform> <actionId> <connectionKey>\` \u2014 Execute action
12507
12617
  - \`one --agent flow create\` \u2014 Build multi-step workflows
12508
12618
  - \`one --agent relay create\` \u2014 Set up webhook relay (receive events, forward to other platforms)
12509
12619
  - \`one --agent guide\` \u2014 Full documentation
12510
12620
  - \`one add <platform>\` \u2014 Connect a new platform (interactive, no --agent)
12511
12621
 
12512
- ### Workflow: search -> knowledge -> execute
12513
- Always read the knowledge before executing. It tells you required parameters,
12514
- validation rules, and platform-specific details.
12622
+ ### Workflow: find -> execute
12623
+ Always read the documentation find returns before executing. It tells you
12624
+ required parameters, validation rules, and platform-specific details.
12515
12625
 
12516
12626
  ### Webhook Relay
12517
12627
  Use \`one relay\` to receive webhooks from platforms (Stripe, GitHub, etc.)
@@ -12525,8 +12635,7 @@ Handlebars templates. No middleware needed.
12525
12635
  Every command supports \`--agent\` which gives you clean, structured JSON
12526
12636
  output instead of human-formatted text. Always use it:
12527
12637
  one --agent list
12528
- one --agent actions search gmail "send email"
12529
- one --agent actions knowledge gmail <actionId>
12638
+ one --agent actions find gmail "send an email" --task "email a report to a contact"
12530
12639
  one --agent actions execute gmail <actionId> <connectionKey> -d '{...}'
12531
12640
  one --agent platforms
12532
12641
  one --agent guide
@@ -12534,8 +12643,8 @@ output instead of human-formatted text. Always use it:
12534
12643
  The \`--agent\` flag goes right after \`one\`, before the subcommand.
12535
12644
 
12536
12645
  ### Discovery Workflow (follow this every time):
12537
- 1. \`one --agent actions search <platform> "<query>"\` \u2014 Find the right action
12538
- 2. \`one --agent actions knowledge <platform> <actionId>\` \u2014 Read the docs (ALWAYS before execute)
12646
+ 1. \`one --agent actions find <platform> "<intent>" [<platform> "<intent>" ...] --task "<the job>"\` \u2014 Find every action the task needs, with its docs; each intent names the operation alone, without its data
12647
+ 2. Read each action's docs (ALWAYS before execute); \`one --agent actions load <actionId> --section <name>\` for a section a digest left out
12539
12648
  3. \`one --agent actions execute <platform> <actionId> <connectionKey>\` \u2014 Execute it
12540
12649
 
12541
12650
  ### Multi-Step Workflows:
@@ -12616,8 +12725,8 @@ You have ${connections.length} platform(s) connected:
12616
12725
  const tableHeader = " Platform Status Connection Key";
12617
12726
  const tableRows = connections.map((c) => {
12618
12727
  const platform = c.platform.padEnd(22);
12619
- const status = c.state.padEnd(14);
12620
- return ` ${platform}${status}${c.key}`;
12728
+ const status2 = c.state.padEnd(14);
12729
+ return ` ${platform}${status2}${c.key}`;
12621
12730
  });
12622
12731
  return header + "\n" + tableHeader + "\n" + tableRows.join("\n");
12623
12732
  }
@@ -12628,13 +12737,13 @@ function buildDemoActions(connections) {
12628
12737
  const connectedPlatforms = connections.map((c) => c.platform.toLowerCase());
12629
12738
  const popularPlatforms = ["gmail", "google-calendar", "slack", "shopify", "hubspot", "github"];
12630
12739
  const platformsToShow = [
12631
- ...connectedPlatforms.filter((p10) => PLATFORM_DEMO_ACTIONS[p10]),
12632
- ...popularPlatforms.filter((p10) => !connectedPlatforms.includes(p10))
12740
+ ...connectedPlatforms.filter((p9) => PLATFORM_DEMO_ACTIONS[p9]),
12741
+ ...popularPlatforms.filter((p9) => !connectedPlatforms.includes(p9))
12633
12742
  ];
12634
12743
  const seen = /* @__PURE__ */ new Set();
12635
- const unique = platformsToShow.filter((p10) => {
12636
- if (seen.has(p10)) return false;
12637
- seen.add(p10);
12744
+ const unique = platformsToShow.filter((p9) => {
12745
+ if (seen.has(p9)) return false;
12746
+ seen.add(p9);
12638
12747
  return true;
12639
12748
  }).slice(0, 6);
12640
12749
  for (const platform of unique) {
@@ -12643,7 +12752,7 @@ function buildDemoActions(connections) {
12643
12752
  const displayName = platform.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
12644
12753
  lines.push("");
12645
12754
  lines.push(`### ${displayName}`);
12646
- lines.push(`- ${demo.description}: \`one actions search ${platform} "${demo.query}"\``);
12755
+ lines.push(`- ${demo.description}: \`one actions find ${platform} "${demo.query}"\``);
12647
12756
  lines.push(`- Then get knowledge and execute to show the user the results`);
12648
12757
  }
12649
12758
  lines.push("");
@@ -12667,7 +12776,7 @@ function buildWorkflowIdeas(connections) {
12667
12776
 
12668
12777
  // src/commands/logout.ts
12669
12778
  import fs13 from "fs";
12670
- import * as p9 from "@clack/prompts";
12779
+ import * as p8 from "@clack/prompts";
12671
12780
  function formatWhoami(config2, apiKey, pc16) {
12672
12781
  const whoami = config2.whoami;
12673
12782
  const env = getEnvFromApiKey(apiKey);
@@ -12729,8 +12838,8 @@ async function logoutCommand() {
12729
12838
  infoLines.push(`${pc16.magenta("Global config:")}`);
12730
12839
  infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey, pc16));
12731
12840
  }
12732
- p9.note(infoLines.join("\n"));
12733
- const choice = await p9.select({
12841
+ p8.note(infoLines.join("\n"));
12842
+ const choice = await p8.select({
12734
12843
  message: "What would you like to log out of?",
12735
12844
  options: [
12736
12845
  { value: "project", label: "This directory", hint: "local config only" },
@@ -12738,8 +12847,8 @@ async function logoutCommand() {
12738
12847
  { value: "both", label: "Both", hint: "remove all credentials" }
12739
12848
  ]
12740
12849
  });
12741
- if (p9.isCancel(choice)) {
12742
- p9.cancel("Logout cancelled.");
12850
+ if (p8.isCancel(choice)) {
12851
+ p8.cancel("Logout cancelled.");
12743
12852
  return;
12744
12853
  }
12745
12854
  targetScope = choice;
@@ -12747,18 +12856,18 @@ async function logoutCommand() {
12747
12856
  const infoLines = ["You are logged in.", ""];
12748
12857
  infoLines.push(`${pc16.dim("Stored in")} ${pc16.cyan("local config")}`);
12749
12858
  infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey, pc16));
12750
- p9.note(infoLines.join("\n"));
12859
+ p8.note(infoLines.join("\n"));
12751
12860
  targetScope = "project";
12752
12861
  } else if (hasGlobal) {
12753
12862
  const infoLines = ["You are logged in.", ""];
12754
12863
  infoLines.push(`${pc16.dim("Stored in")} ${pc16.magenta("global config")}`);
12755
12864
  infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey, pc16));
12756
- p9.note(infoLines.join("\n"));
12865
+ p8.note(infoLines.join("\n"));
12757
12866
  targetScope = "global";
12758
12867
  } else {
12759
- p9.log.warn("Credentials are set via environment variable or .onerc, not a config file.");
12760
- p9.log.info("Remove the ONE_SECRET variable from your environment or .onerc file.");
12761
- p9.outro("Nothing to remove.");
12868
+ p8.log.warn("Credentials are set via environment variable or .onerc, not a config file.");
12869
+ p8.log.info("Remove the ONE_SECRET variable from your environment or .onerc file.");
12870
+ p8.outro("Nothing to remove.");
12762
12871
  return;
12763
12872
  }
12764
12873
  const scopeLabels = {
@@ -12766,11 +12875,11 @@ async function logoutCommand() {
12766
12875
  global: "global",
12767
12876
  both: "all"
12768
12877
  };
12769
- const confirm7 = await p9.confirm({
12878
+ const confirm7 = await p8.confirm({
12770
12879
  message: `Remove ${scopeLabels[targetScope]} credentials?`
12771
12880
  });
12772
- if (p9.isCancel(confirm7) || !confirm7) {
12773
- p9.cancel("Logout cancelled.");
12881
+ if (p8.isCancel(confirm7) || !confirm7) {
12882
+ p8.cancel("Logout cancelled.");
12774
12883
  return;
12775
12884
  }
12776
12885
  if (targetScope === "project" || targetScope === "both") {
@@ -12781,9 +12890,9 @@ async function logoutCommand() {
12781
12890
  const globalPath = getGlobalConfigPath();
12782
12891
  if (fs13.existsSync(globalPath)) fs13.unlinkSync(globalPath);
12783
12892
  }
12784
- p9.log.success("Credentials cleared.");
12785
- p9.log.info("Your API key is still active. Manage keys at app.withone.ai/settings");
12786
- p9.outro("Logged out.");
12893
+ p8.log.success("Credentials cleared.");
12894
+ p8.log.info("Your API key is still active. Manage keys at app.withone.ai/settings");
12895
+ p8.outro("Logged out.");
12787
12896
  }
12788
12897
 
12789
12898
  // src/cli.ts
@@ -12804,9 +12913,9 @@ program.name("one").option("--agent", "Machine-readable JSON output (no colors,
12804
12913
 
12805
12914
  Workflow (use these in order):
12806
12915
  1. one list List connected platforms, keys, and your access on each
12807
- 2. one actions search <platform> <q> Search for actions using natural language
12808
- 3. one actions knowledge <plat> <id> Get docs for an action (ALWAYS do this before execute; --section/--full for more)
12809
- 4. one actions execute <p> <id> <key> Execute the action
12916
+ 2. one actions find <p> <intent> ... Find the action for every operation a task needs, with its docs (ALWAYS read them before execute)
12917
+ 3. one actions execute <p> <id> <key> Execute the action
12918
+ one actions load <id> --section <s> More of an action's docs: a section a digest left out, --full, or --toc
12810
12919
 
12811
12920
  Guide:
12812
12921
  one guide [topic] Full CLI guide (topics: overview, actions, workflows, memory, sync, all)
@@ -12853,11 +12962,9 @@ program.name("one").option("--agent", "Machine-readable JSON output (no colors,
12853
12962
  $ one list
12854
12963
  # Find: gmail operational live::gmail::default::abc123
12855
12964
 
12856
- $ one actions search gmail "send email" -t execute
12857
- # Find: POST Send Email conn_mod_def::xxx::yyy
12858
-
12859
- $ one actions knowledge gmail conn_mod_def::xxx::yyy
12860
- # Read the docs: required fields are to, subject, body, connectionKey
12965
+ $ one actions find gmail "send an email" --task "email a report to a contact"
12966
+ # Send Email \xB7 POST /v1/gmail/send-email \xB7 actionId: conn_mod_def::xxx::yyy
12967
+ # ...its docs: required fields are to, subject, body, connectionKey
12861
12968
 
12862
12969
  $ one actions execute gmail conn_mod_def::xxx::yyy live::gmail::default::abc123 \\
12863
12970
  -d '{"to":"j@example.com","subject":"Hello","body":"Hi!","connectionKey":"live::gmail::default::abc123"}'
@@ -12964,22 +13071,22 @@ configSkills.command("sync").description("Re-copy packaged skill files over the
12964
13071
  console.log(`\u2717 Sync failed${result.error ? ": " + result.error : ""}`);
12965
13072
  });
12966
13073
  configSkills.command("status").description("Show installed skill version and whether it matches the current CLI").action(async () => {
12967
- const status = getSkillStatus();
13074
+ const status2 = getSkillStatus();
12968
13075
  if (isAgentMode()) {
12969
- json({ command: "config skills status", ...status });
13076
+ json({ command: "config skills status", ...status2 });
12970
13077
  return;
12971
13078
  }
12972
- if (!status.installed) {
13079
+ if (!status2.installed) {
12973
13080
  console.log("Skill is not installed. Run 'one init' to install it.");
12974
- console.log(`Canonical path (empty): ${status.canonicalPath}`);
13081
+ console.log(`Canonical path (empty): ${status2.canonicalPath}`);
12975
13082
  return;
12976
13083
  }
12977
- const marker = status.installedVersion ?? "(no marker \u2014 pre-sync install)";
12978
- const state = status.upToDate ? "\u2713 up to date" : "\u26A0 stale \u2014 will sync on next command";
13084
+ const marker = status2.installedVersion ?? "(no marker \u2014 pre-sync install)";
13085
+ const state = status2.upToDate ? "\u2713 up to date" : "\u26A0 stale \u2014 will sync on next command";
12979
13086
  console.log(`Skill: ${state}`);
12980
13087
  console.log(` installed: ${marker}`);
12981
- console.log(` current: ${status.currentVersion}`);
12982
- console.log(` path: ${status.canonicalPath}`);
13088
+ console.log(` current: ${status2.currentVersion}`);
13089
+ console.log(` path: ${status2.canonicalPath}`);
12983
13090
  });
12984
13091
  config.command("reset").description("Remove the project config for the current directory (falls back to global)").option("--global", "Remove the global config instead").action(async (opts) => {
12985
13092
  const resolved = resolveConfig();
@@ -12994,12 +13101,12 @@ config.command("reset").description("Remove the project config for the current d
12994
13101
  return;
12995
13102
  }
12996
13103
  if (!isAgentMode()) {
12997
- const p10 = await import("@clack/prompts");
12998
- const confirmed = await p10.confirm({
13104
+ const p9 = await import("@clack/prompts");
13105
+ const confirmed = await p9.confirm({
12999
13106
  message: "Delete the global config? This removes your API key for all projects without a project config.",
13000
13107
  initialValue: false
13001
13108
  });
13002
- if (p10.isCancel(confirmed) || !confirmed) {
13109
+ if (p9.isCancel(confirmed) || !confirmed) {
13003
13110
  console.log("Cancelled.");
13004
13111
  return;
13005
13112
  }
@@ -13037,12 +13144,12 @@ config.command("reset").description("Remove the project config for the current d
13037
13144
  fallbackLabel = "no config";
13038
13145
  }
13039
13146
  if (!isAgentMode()) {
13040
- const p10 = await import("@clack/prompts");
13041
- const confirmed = await p10.confirm({
13147
+ const p9 = await import("@clack/prompts");
13148
+ const confirmed = await p9.confirm({
13042
13149
  message: `Delete project config for ${path13.basename(resolved.projectRoot)}? Will fall back to ${fallbackLabel}.`,
13043
13150
  initialValue: false
13044
13151
  });
13045
- if (p10.isCancel(confirmed) || !confirmed) {
13152
+ if (p9.isCancel(confirmed) || !confirmed) {
13046
13153
  console.log("Cancelled.");
13047
13154
  return;
13048
13155
  }
@@ -13071,12 +13178,12 @@ connection.command("delete <connection-key>").alias("rm").description("Delete a
13071
13178
  program.command("platforms").alias("p").description("List available platforms").option("-c, --category <category>", "Filter by category").option("--json", "Output as JSON").action(async (options) => {
13072
13179
  await platformsCommand(options);
13073
13180
  });
13074
- var actions = program.command("actions").alias("a").description("Search, explore, and execute platform actions (workflow: search \u2192 knowledge \u2192 execute)");
13075
- 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) => {
13076
- await actionsSearchCommand(platform, query, options);
13181
+ var actions = program.command("actions").alias("a").description("Find, read, and execute platform actions (workflow: find \u2192 execute)");
13182
+ actions.command("find <pairs...>").alias("f").description('Find the action for every operation a task needs, across platforms, with its documentation, in one call: one actions find <platform> "<intent>" [<platform> "<intent>" ...] (up to 10 pairs). Each intent names the operation alone ("send an email"), without its data. Large documents come back as a digest; each names the exact `actions load` command for what it left out').option("--task <task>", 'The whole task in one line, in general terms (e.g. "email a report to a contact"): what it does, without names, addresses, IDs or message text. Helps choose between similar actions').option("-t, --type <type>", "execute (default: actions to run now) or knowledge (the catalog for writing code and building flows and relays, with the platform's own endpoints). Knowledge-only mode always uses knowledge").option("--ai-model <model>", "The AI model running the CLI (e.g. claude-sonnet-5), which helps optimize the documentation returned. Optional").option("--no-cache", "Bypass the cache for action documentation and re-fetch it (the fresh response still refreshes the cache)").option("--no-knowledge", "List the chosen actions (actionId, title, method, path) without their documentation; load it with `one actions load <actionId>`").action(async (pairs, options) => {
13183
+ await actionsFindCommand(pairs, options);
13077
13184
  });
13078
- actions.command("knowledge <platform> <actionId>").alias("k").description("Get docs for an action \u2014 MUST call before execute to know required params. In --agent mode returns a digest (request-building sections + a table of contents); load the rest with --section or --full").option("--section <name>", 'Return only the named section(s) \u2014 by heading, id, or alias (e.g. "Response Fields", response, optional). Repeatable or comma-separated', collect, []).option("--full", "Return the whole document instead of the digest").option("--toc", "List every section (id, heading, size) without the document").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) => {
13079
- await actionsKnowledgeCommand(platform, actionId, options);
13185
+ actions.command("load <actionIds...>").alias("l").description("More of an action's documentation (up to 10 actions): the digest by default, --section for one a digest left out, --full for the whole document, --toc for its contents. Also how to read an alternative from a find answer").option("--section <name>", 'Return only the named section(s) \u2014 by heading, id, or alias (e.g. "Response Fields", response, optional). Repeatable or comma-separated', collect, []).option("--full", "Return the whole document instead of the digest").option("--toc", "List every section (id, heading, size) without the document").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 (actionIds, options) => {
13186
+ await actionsLoadCommand(actionIds, options);
13080
13187
  });
13081
13188
  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) => {
13082
13189
  if (options.parallel) {