@withone/cli 1.57.0 → 2.0.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,14 +25,13 @@ 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
- } from "./chunk-KAF5SVJS.js";
34
+ } from "./chunk-GKAIRI4Y.js";
39
35
  import {
40
36
  collectIdentityKeys,
41
37
  countRecords,
@@ -66,7 +62,7 @@ import {
66
62
  writeDraftProfile,
67
63
  writePageToMemory,
68
64
  writeProfile
69
- } from "./chunk-XWTV7FA3.js";
65
+ } from "./chunk-YTM6HJKA.js";
70
66
  import {
71
67
  getByDotPath
72
68
  } from "./chunk-44CV5IMX.js";
@@ -100,7 +96,7 @@ import {
100
96
  listBackendPlugins,
101
97
  loadBackendFromConfig,
102
98
  updateRecord
103
- } from "./chunk-VH46MAE4.js";
99
+ } from "./chunk-IMU2X3ZV.js";
104
100
  import {
105
101
  DEFAULT_MEMORY_CONFIG,
106
102
  defaultSearchableText,
@@ -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,392 @@ 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) {
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 = 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: !settings.knowledgeAgent && answer.runnerUp !== void 0
3611
+ };
3612
+ });
3613
+ const ids = /* @__PURE__ */ new Set();
3614
+ for (const plan of plans) {
3615
+ if (plan.unreachable) 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 = [];
3650
+ const deferred = [];
3651
+ for (const [index, pick] of 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.length > 0 || 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
+ parts.push(...answer.selected.map(shown));
3848
+ parts.push(
3849
+ ...listing(
3850
+ 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",
3851
+ answer.alsoSelected
3852
+ )
3853
+ );
3854
+ if (answer.runnerUp) {
3855
+ const lead = "If the chosen action does not fit, use this one instead: one or the other, never both";
3856
+ parts.push(..."knowledge" in answer.runnerUp ? [`${lead}.
3857
+
3858
+ ${shown(answer.runnerUp)}`] : listing(lead, [answer.runnerUp]));
3859
+ }
3860
+ parts.push(...listing("Alternatives, not documented", answer.alternatives));
3861
+ return parts.join("\n\n");
3862
+ });
3863
+ return [...sections, ...result.guide ? [result.guide] : []].join("\n\n---\n\n");
3864
+ }
3865
+ function renderLoad(result) {
3866
+ const entries = result.loaded.map(
3867
+ (entry) => "error" in entry ? `\`${entry.actionId}\`: ${entry.error}` : entry.knowledge.startsWith("### ") ? entry.knowledge : `### ${actionHeading(entry)}
3868
+
3869
+ ${entry.knowledge}`
3870
+ );
3871
+ return [...entries, ...result.guide ? [result.guide] : []].join("\n\n---\n\n");
3872
+ }
3873
+
3496
3874
  // src/commands/actions.ts
3497
3875
  function getConfig() {
3498
3876
  const apiKey = getApiKey();
@@ -3513,312 +3891,101 @@ function parseJsonArg2(value, argName) {
3513
3891
  error(`Invalid JSON for ${argName}: ${value}`);
3514
3892
  }
3515
3893
  }
3516
- async function actionsSearchCommand(platform, query, options) {
3894
+ function findDeps(api, connectionKeys, useCache) {
3895
+ return {
3896
+ findActions: (requests, task, knowledgeAgent) => api.findActions(requests, task, knowledgeAgent),
3897
+ getActionDetails: async (actionId) => (await resolveActionDetails(api, actionId, { useCache })).details,
3898
+ connectedPlatforms: async () => (await api.listConnections()).filter((c) => connectionKeys.includes(c.key)).map((c) => c.platform)
3899
+ };
3900
+ }
3901
+ function failure(error2) {
3902
+ if (error2 instanceof ApiError) {
3903
+ try {
3904
+ const body = JSON.parse(error2.message);
3905
+ if (body.message) return body.message;
3906
+ } catch {
3907
+ }
3908
+ }
3909
+ return error2 instanceof Error ? error2.message : "Unknown error";
3910
+ }
3911
+ async function actionsFindCommand(pairs, options) {
3517
3912
  intro(pc8.bgCyan(pc8.black(" One ")));
3518
- const { apiKey, permissions, actionIds, knowledgeAgent } = getConfig();
3913
+ if (options.type !== void 0 && options.type !== "execute" && options.type !== "knowledge") {
3914
+ error("--type must be execute or knowledge.");
3915
+ }
3916
+ if (pairs.length === 0 || pairs.length % 2 !== 0) {
3917
+ error('Pass platform and intent pairs: one actions find <platform> "<intent>" [<platform> "<intent>" ...]');
3918
+ }
3919
+ const requests = [];
3920
+ for (let i = 0; i < pairs.length; i += 2) {
3921
+ requests.push({ platform: pairs[i], intent: pairs[i + 1] });
3922
+ }
3923
+ const { apiKey, permissions, connectionKeys, actionIds, knowledgeAgent } = getConfig();
3519
3924
  const api = new OneApi(apiKey, getApiBase());
3925
+ const settings = { knowledgeAgent, permissions, actionIds, connectionKeys, apiBase: getApiBase() };
3520
3926
  const spinner4 = createSpinner();
3521
- spinner4.start(`Searching actions on ${pc8.cyan(platform)} for "${query}"...`);
3927
+ spinner4.start(`Finding actions for ${requests.length} intent${requests.length === 1 ? "" : "s"}...`);
3522
3928
  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
- }
3929
+ const result = await find(
3930
+ requests,
3931
+ options.task,
3932
+ findDeps(api, connectionKeys, options.cache !== false),
3933
+ settings,
3934
+ options.type === "knowledge"
3935
+ );
3575
3936
  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
- );
3937
+ json(result);
3603
3938
  return;
3604
3939
  }
3605
- spinner4.stop(
3606
- `Found ${cleanedActions.length} action(s) for '${platform}' matching '${query}'`
3607
- );
3940
+ spinner4.stop("Found");
3608
3941
  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
- );
3942
+ console.log(renderFind(result));
3624
3943
  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
3944
  } catch (error2) {
3631
- spinner4.stop("Search failed");
3632
- error(
3633
- `Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`
3634
- );
3945
+ spinner4.stop("Find failed");
3946
+ error(`Error: ${failure(error2)}`);
3635
3947
  }
3636
3948
  }
3637
- async function actionsKnowledgeCommand(platform, actionId, options) {
3638
- const cachePath = knowledgeCachePath(actionId);
3949
+ async function actionsLoadCommand(actionIds, options) {
3639
3950
  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
- }
3951
+ json(
3952
+ actionIds.map((actionId) => {
3953
+ const cachePath = knowledgeCachePath(actionId);
3954
+ const entry = readCache(cachePath);
3955
+ if (!entry) return { actionId, cached: false, path: cachePath };
3956
+ return {
3957
+ actionId,
3958
+ cached: true,
3959
+ cachedAt: entry.cachedAt,
3960
+ age: formatAge(getAge(entry)),
3961
+ ttl: entry.ttl,
3962
+ expired: !isFresh(entry),
3963
+ etag: entry.etag,
3964
+ path: cachePath
3965
+ };
3966
+ })
3967
+ );
3658
3968
  return;
3659
3969
  }
3660
3970
  intro(pc8.bgCyan(pc8.black(" One ")));
3661
- const { apiKey, actionIds, connectionKeys } = getConfig();
3971
+ const { apiKey, permissions, connectionKeys, actionIds: allowed, knowledgeAgent } = getConfig();
3662
3972
  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
- }
3973
+ const settings = { knowledgeAgent, permissions, actionIds: allowed, connectionKeys, apiBase: getApiBase() };
3684
3974
  const spinner4 = createSpinner();
3685
- spinner4.start(`Loading knowledge for action ${pc8.dim(actionId)}...`);
3975
+ spinner4.start(`Loading ${actionIds.length === 1 ? "the action" : `${actionIds.length} actions`}...`);
3686
3976
  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
- );
3977
+ const result = await load(actionIds, options, findDeps(api, connectionKeys, options.cache !== false), settings);
3782
3978
  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);
3979
+ json(result);
3807
3980
  return;
3808
3981
  }
3809
- spinner4.stop("Knowledge loaded");
3982
+ spinner4.stop("Loaded");
3810
3983
  console.log();
3811
- console.log(knowledgeWithGuidance);
3984
+ console.log(renderLoad(result));
3812
3985
  console.log();
3813
- p6.note(
3814
- `Execute: ${pc8.cyan(`one actions execute ${platform} ${actionId} <connectionKey>`)}`,
3815
- "Next Step"
3816
- );
3817
3986
  } catch (error2) {
3818
- spinner4.stop("Failed to load knowledge");
3819
- error(
3820
- `Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`
3821
- );
3987
+ spinner4.stop("Load failed");
3988
+ error(`Error: ${failure(error2)}`);
3822
3989
  }
3823
3990
  }
3824
3991
  async function actionsExecuteCommand(platform, actionId, connectionKey, options) {
@@ -4275,22 +4442,6 @@ async function actionsExecuteParallelCommand() {
4275
4442
  }
4276
4443
  console.log();
4277
4444
  }
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
4445
 
4295
4446
  // src/commands/flow.ts
4296
4447
  import pc9 from "picocolors";
@@ -5049,14 +5200,14 @@ function previewValue(value, max = 120) {
5049
5200
  if (str === void 0) str = String(value);
5050
5201
  return str.length > max ? `${str.slice(0, max - 1)}\u2026` : str;
5051
5202
  }
5052
- function renderDryRef(ref) {
5053
- if (ref.status === "resolved") {
5054
- return `${pc9.green("\u2713")} ${ref.selector} ${pc9.dim("\u2192")} ${previewValue(ref.value)}`;
5203
+ function renderDryRef(ref2) {
5204
+ if (ref2.status === "resolved") {
5205
+ return `${pc9.green("\u2713")} ${ref2.selector} ${pc9.dim("\u2192")} ${previewValue(ref2.value)}`;
5055
5206
  }
5056
- if (ref.status === "deferred") {
5057
- return `${pc9.dim("\u25CB")} ${ref.selector} ${pc9.dim("\u2192 pending (produced by a later step)")}`;
5207
+ if (ref2.status === "deferred") {
5208
+ return `${pc9.dim("\u25CB")} ${ref2.selector} ${pc9.dim("\u2192 pending (produced by a later step)")}`;
5058
5209
  }
5059
- return `${pc9.yellow("!")} ${ref.selector} ${pc9.yellow("\u2192 unresolved \u2014 check the input/env name")}`;
5210
+ return `${pc9.yellow("!")} ${ref2.selector} ${pc9.yellow("\u2192 unresolved \u2014 check the input/env name")}`;
5060
5211
  }
5061
5212
  function renderDryResolution(steps) {
5062
5213
  const isExpr = (t) => t === "transform" || t === "condition" || t === "while";
@@ -5072,8 +5223,8 @@ function renderDryResolution(steps) {
5072
5223
  console.log(` ${pc9.dim("=")} ${previewValue(s.resolved)}`);
5073
5224
  }
5074
5225
  if (!(isExpr(s.type) && s.deferred)) {
5075
- for (const ref of s.references) {
5076
- console.log(` ${renderDryRef(ref)}`);
5226
+ for (const ref2 of s.references) {
5227
+ console.log(` ${renderDryRef(ref2)}`);
5077
5228
  }
5078
5229
  }
5079
5230
  if (!isExpr(s.type) && s.references.length === 0 && s.error === void 0) {
@@ -5280,8 +5431,8 @@ ${pc9.yellow("Pausing after current step completes...")} (run ID: ${runId})`);
5280
5431
  if (event.event === "step:start") {
5281
5432
  console.log(` ${pc9.dim(ts)} ${pc9.cyan("\u25B6")} ${event.stepName} ${pc9.dim(`(${event.type})`)}`);
5282
5433
  } 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`)}`);
5434
+ const status2 = event.status === "success" ? pc9.green("\u2713") : event.status === "skipped" ? pc9.dim("\u25CB") : pc9.red("\u2717");
5435
+ console.log(` ${pc9.dim(ts)} ${status2} ${event.stepId} ${pc9.dim(`${event.durationMs}ms`)}`);
5285
5436
  } else if (event.event === "step:error") {
5286
5437
  console.log(` ${pc9.dim(ts)} ${pc9.red("\u2717")} ${event.stepId}: ${event.error}`);
5287
5438
  }
@@ -5618,18 +5769,18 @@ async function flowInspectCommand(runId, options = {}) {
5618
5769
  console.log(` ${pc9.dim(`Log: ${path7.join(".one/flows/.logs", `${state.flowKey}-${state.runId}.log`)}`)}`);
5619
5770
  console.log();
5620
5771
  }
5621
- function colorStatus(status) {
5622
- switch (status) {
5772
+ function colorStatus(status2) {
5773
+ switch (status2) {
5623
5774
  case "completed":
5624
- return pc9.green(status);
5775
+ return pc9.green(status2);
5625
5776
  case "running":
5626
- return pc9.cyan(status);
5777
+ return pc9.cyan(status2);
5627
5778
  case "paused":
5628
- return pc9.yellow(status);
5779
+ return pc9.yellow(status2);
5629
5780
  case "failed":
5630
- return pc9.red(status);
5781
+ return pc9.red(status2);
5631
5782
  default:
5632
- return status;
5783
+ return status2;
5633
5784
  }
5634
5785
  }
5635
5786
  var SCAFFOLD_TEMPLATES = {
@@ -6156,7 +6307,7 @@ async function relayPlatformsCommand() {
6156
6307
  { key: "platform", label: "Platform" },
6157
6308
  { key: "eventTypeCount", label: "Event types", color: pc10.dim }
6158
6309
  ],
6159
- platforms.map((p10) => ({ platform: p10.platform, eventTypeCount: String(p10.eventTypeCount) }))
6310
+ platforms.map((p9) => ({ platform: p9.platform, eventTypeCount: String(p9.eventTypeCount) }))
6160
6311
  );
6161
6312
  console.log();
6162
6313
  console.log(
@@ -6682,9 +6833,9 @@ function interpolate(template, record) {
6682
6833
  return template.replace(/\{?\{(\w+(?:\.\w+)*)\}\}?/g, (_, path14) => {
6683
6834
  const parts = path14.split(".");
6684
6835
  let value = record;
6685
- for (const part of parts) {
6836
+ for (const part2 of parts) {
6686
6837
  if (typeof value !== "object" || value === null) return "";
6687
- value = value[part];
6838
+ value = value[part2];
6688
6839
  }
6689
6840
  return value === null || value === void 0 ? "" : String(value);
6690
6841
  });
@@ -6711,9 +6862,9 @@ function deepMerge(target, source) {
6711
6862
  function getByDotPath2(obj, path14) {
6712
6863
  const parts = path14.split(".");
6713
6864
  let current = obj;
6714
- for (const part of parts) {
6865
+ for (const part2 of parts) {
6715
6866
  if (current === null || current === void 0 || typeof current !== "object") return void 0;
6716
- current = current[part];
6867
+ current = current[part2];
6717
6868
  }
6718
6869
  return current;
6719
6870
  }
@@ -6868,7 +7019,7 @@ async function enrichPhase(api, db, config2, model, idField, connectionKey, plat
6868
7019
  }
6869
7020
  if (detailAction.tags?.includes("custom")) {
6870
7021
  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.`
7022
+ `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
7023
  );
6873
7024
  }
6874
7025
  let concurrency = config2.concurrency ?? DEFAULT_CONCURRENCY;
@@ -6915,16 +7066,16 @@ async function enrichPhase(api, db, config2, model, idField, connectionKey, plat
6915
7066
  }
6916
7067
  let writes = pending2;
6917
7068
  if (ctx.transform && pending2.length > 0) {
6918
- const transformed = await transformRecords(ctx.transform, pending2.map((p10) => p10.merged));
7069
+ const transformed = await transformRecords(ctx.transform, pending2.map((p9) => p9.merged));
6919
7070
  if (transformed) {
6920
7071
  const byId = /* @__PURE__ */ new Map();
6921
7072
  for (const r of transformed) byId.set(r[idField], r);
6922
7073
  writes = [];
6923
- for (const p10 of pending2) {
6924
- const t = byId.get(p10.id);
7074
+ for (const p9 of pending2) {
7075
+ const t = byId.get(p9.id);
6925
7076
  if (!t) continue;
6926
7077
  if (!t[tsField]) t[tsField] = now;
6927
- writes.push({ merged: t, id: p10.id });
7078
+ writes.push({ merged: t, id: p9.id });
6928
7079
  }
6929
7080
  }
6930
7081
  }
@@ -7231,7 +7382,7 @@ async function syncModel(api, profile, options) {
7231
7382
  updateModelState(platform, model, { status: "failed", pagesProcessed, lastCursor }),
7232
7383
  (async () => {
7233
7384
  try {
7234
- const { getBackend: getBackend2 } = await import("./runtime-65IPTPVD.js");
7385
+ const { getBackend: getBackend2 } = await import("./runtime-SX36HGBA.js");
7235
7386
  const backend = await getBackend2();
7236
7387
  await Promise.race([
7237
7388
  backend.close(),
@@ -7312,7 +7463,7 @@ async function syncModel(api, profile, options) {
7312
7463
  const { details: actionDetails } = await resolveActionDetails(api, profile.actionId);
7313
7464
  if (actionDetails.tags?.includes("custom")) {
7314
7465
  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.`
7466
+ `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
7467
  );
7317
7468
  }
7318
7469
  const maxPages = options.maxPages ?? Infinity;
@@ -7597,7 +7748,7 @@ async function syncModel(api, profile, options) {
7597
7748
  db.exec(`DROP TABLE IF EXISTS _seen_ids`);
7598
7749
  }
7599
7750
  if (options.toMemory !== false) {
7600
- const backend = await (await import("./runtime-65IPTPVD.js")).getBackend();
7751
+ const backend = await (await import("./runtime-SX36HGBA.js")).getBackend();
7601
7752
  const type = `${platform}/${model}`;
7602
7753
  const existing = await backend.listKeysByType(type);
7603
7754
  const sourcePrefix = `${type}:`;
@@ -7698,7 +7849,7 @@ async function syncModel(api, profile, options) {
7698
7849
  let statusCounts;
7699
7850
  if (options.toMemory !== false) {
7700
7851
  try {
7701
- const backend = await (await import("./runtime-65IPTPVD.js")).getBackend();
7852
+ const backend = await (await import("./runtime-SX36HGBA.js")).getBackend();
7702
7853
  const typeName = `${platform}/${model}`;
7703
7854
  const [active, archived] = await Promise.all([
7704
7855
  backend.count(typeName, { status: "active" }),
@@ -7861,7 +8012,7 @@ async function testSyncProfile(api, profile) {
7861
8012
  checks.push({
7862
8013
  name: "action is passthrough (not custom)",
7863
8014
  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.`
8015
+ 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
8016
  });
7866
8017
  return report;
7867
8018
  }
@@ -8716,7 +8867,7 @@ async function searchSyncedData(query, options) {
8716
8867
  const backend = await getBackend();
8717
8868
  const profiles = listProfiles(options.platform);
8718
8869
  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}`);
8870
+ const types = profiles.filter((p9) => !modelFilter || modelFilter.has(p9.model)).map((p9) => `${p9.platform}/${p9.model}`);
8720
8871
  if (types.length === 0) {
8721
8872
  throw new Error(
8722
8873
  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 +9023,7 @@ function suggestSearchablePaths(records, limit = 15) {
8872
9023
 
8873
9024
  // src/lib/memory/sync/index.ts
8874
9025
  import { spawn as spawn4 } from "child_process";
8875
- import * as p7 from "@clack/prompts";
9026
+ import * as p6 from "@clack/prompts";
8876
9027
  import pc11 from "picocolors";
8877
9028
  async function syncInstallCommand() {
8878
9029
  if (await isSqliteAvailable()) {
@@ -8960,17 +9111,17 @@ async function syncProfilesCommand(platform) {
8960
9111
  const profiles = listBuiltinProfiles(platform);
8961
9112
  if (isAgentMode()) {
8962
9113
  json({
8963
- profiles: profiles.map((p10) => ({
8964
- platform: p10.platform,
8965
- model: p10.model,
8966
- description: p10.description,
8967
- hasEnrich: !!p10.enrich,
9114
+ profiles: profiles.map((p9) => ({
9115
+ platform: p9.platform,
9116
+ model: p9.model,
9117
+ description: p9.description,
9118
+ hasEnrich: !!p9.enrich,
8968
9119
  // `identityKey` (singular) is the entity-merge key; `identityKeys`
8969
9120
  // (plural, #167) are non-merging association keys. Reading only the
8970
9121
  // singular reported hasIdentityKey:false for gmail/gcal/fathom — the
8971
9122
  // three profiles the plural form was added for. (#129/#130)
8972
- hasIdentityKey: !!p10.identityKey || !!p10.identityKeys,
8973
- hasIdentityKeys: !!p10.identityKeys
9123
+ hasIdentityKey: !!p9.identityKey || !!p9.identityKeys,
9124
+ hasIdentityKeys: !!p9.identityKeys
8974
9125
  })),
8975
9126
  total: profiles.length,
8976
9127
  _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 +9135,13 @@ async function syncProfilesCommand(platform) {
8984
9135
  );
8985
9136
  return;
8986
9137
  }
8987
- for (const p10 of profiles) {
9138
+ for (const p9 of profiles) {
8988
9139
  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");
9140
+ if (p9.enrich) extras.push("enrich");
9141
+ if (p9.identityKey || p9.identityKeys) extras.push("identity");
9142
+ if (p9.dateFilter) extras.push("incremental");
8992
9143
  const tags = extras.length > 0 ? ` ${pc11.dim(`[${extras.join(", ")}]`)}` : "";
8993
- console.log(` ${pc11.bold(`${p10.platform}/${p10.model}`.padEnd(35))} ${p10.description}${tags}`);
9144
+ console.log(` ${pc11.bold(`${p9.platform}/${p9.model}`.padEnd(35))} ${p9.description}${tags}`);
8994
9145
  }
8995
9146
  console.log(`
8996
9147
  ${profiles.length} built-in profile(s). Run ${pc11.bold("one sync init <platform> <model>")} to use one.`);
@@ -9101,7 +9252,7 @@ async function syncInitCommand(platform, model, options) {
9101
9252
  } catch {
9102
9253
  }
9103
9254
  }
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`;
9255
+ 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
9256
  if (isAgentMode()) {
9106
9257
  json({
9107
9258
  ...template,
@@ -9249,11 +9400,11 @@ async function syncTestCommand(platformModel, options = {}) {
9249
9400
  console.log(` ${pc11.dim("text:")} ${searchablePreview.text.slice(0, 300)}${searchablePreview.length > 300 ? pc11.dim(" \u2026") : ""}`);
9250
9401
  if (searchablePreview.paths) {
9251
9402
  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}`);
9403
+ for (const p9 of searchablePreview.paths) {
9404
+ const rate = `${p9.hits}/${p9.total}`;
9405
+ const mark = p9.hits === p9.total ? pc11.green("\u2713") : p9.hits === 0 ? pc11.red("\u2717") : pc11.yellow("~");
9406
+ 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)") : "";
9407
+ console.log(` ${mark} ${rate.padStart(5)} ${p9.path}${trailer}`);
9257
9408
  }
9258
9409
  } else {
9259
9410
  console.log(` ${pc11.yellow("note:")} no memory.searchable declared \u2014 using the default walker (walks every field, often noisy).`);
@@ -9273,10 +9424,10 @@ function buildSearchablePreview(profile, samples) {
9273
9424
  const perPathAgg = paths.map((path14) => ({ path: path14, hits: 0, total: samples.length, sample: "" }));
9274
9425
  for (const record of samples) {
9275
9426
  const { paths: perPath } = extractSearchableFromPaths(record, paths);
9276
- perPath.forEach((p10, i) => {
9277
- if (p10.found) {
9427
+ perPath.forEach((p9, i) => {
9428
+ if (p9.found) {
9278
9429
  perPathAgg[i].hits++;
9279
- if (!perPathAgg[i].sample) perPathAgg[i].sample = p10.sample;
9430
+ if (!perPathAgg[i].sample) perPathAgg[i].sample = p9.sample;
9280
9431
  }
9281
9432
  });
9282
9433
  }
@@ -9290,16 +9441,16 @@ async function syncRunCommand(platform, options) {
9290
9441
  const api = getApi();
9291
9442
  const profiles = listProfiles(platform);
9292
9443
  const targetModels = options.models;
9293
- const toSync = targetModels ? profiles.filter((p10) => targetModels.includes(p10.model)) : profiles;
9444
+ const toSync = targetModels ? profiles.filter((p9) => targetModels.includes(p9.model)) : profiles;
9294
9445
  if (toSync.length === 0) {
9295
9446
  error(
9296
9447
  `No sync profiles found for ${platform}` + (targetModels ? ` with models: ${targetModels.join(", ")}` : "") + `. Run 'one sync init ${platform} <model> --config ...' first.`
9297
9448
  );
9298
9449
  }
9299
9450
  if (!options.dryRun) {
9300
- await maybeAutoMigrateLegacy(platform, toSync.map((p10) => p10.model));
9451
+ await maybeAutoMigrateLegacy(platform, toSync.map((p9) => p9.model));
9301
9452
  }
9302
- const profileDrift = toSync.map((p10) => ({ model: p10.model, missing: findMissingBuiltinCapabilities(platform, p10.model, p10) })).filter((d) => d.missing.length > 0);
9453
+ const profileDrift = toSync.map((p9) => ({ model: p9.model, missing: findMissingBuiltinCapabilities(platform, p9.model, p9) })).filter((d) => d.missing.length > 0);
9303
9454
  if (profileDrift.length > 0 && !isAgentMode()) {
9304
9455
  for (const d of profileDrift) {
9305
9456
  console.log(
@@ -9347,8 +9498,8 @@ async function syncRunCommand(platform, options) {
9347
9498
  return;
9348
9499
  }
9349
9500
  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}]`);
9501
+ const status2 = r.status === "complete" ? pc11.green("complete") : r.status === "dry-run" ? pc11.yellow("dry-run") : pc11.red("failed");
9502
+ console.log(` ${pc11.bold(r.model)} \u2014 ${r.recordsSynced} records, ${r.pagesProcessed} pages, ${r.duration} [${status2}]`);
9352
9503
  if (r.reconcileSkipped) {
9353
9504
  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
9505
  }
@@ -9420,7 +9571,7 @@ ${result.total} results`);
9420
9571
  }
9421
9572
  }
9422
9573
  async function syncSqlCommand(platformModel, sql) {
9423
- const { syncSqlCommand: runSyncSql } = await import("./sql-QIVDWTL3.js");
9574
+ const { syncSqlCommand: runSyncSql } = await import("./sql-SYCWUPNP.js");
9424
9575
  await runSyncSql(platformModel, sql);
9425
9576
  }
9426
9577
  async function syncDeleteCommand(platformModel, options) {
@@ -9475,8 +9626,8 @@ async function syncDeleteCommand(platformModel, options) {
9475
9626
  return;
9476
9627
  }
9477
9628
  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) {
9629
+ const confirmed = await p6.confirm({ message: `Delete ${preview.count} record(s) from ${platform}/${model}?` });
9630
+ if (p6.isCancel(confirmed) || !confirmed) {
9480
9631
  db.close();
9481
9632
  cancel("Cancelled.");
9482
9633
  return;
@@ -9498,7 +9649,7 @@ async function syncDeleteCommand(platformModel, options) {
9498
9649
  async function maybeAutoMigrateLegacy(platform, models) {
9499
9650
  const dbSize = getDatabaseSize(platform);
9500
9651
  if (!dbSize || dbSize === "0 B") return;
9501
- const { getBackend: getBackend2 } = await import("./runtime-65IPTPVD.js");
9652
+ const { getBackend: getBackend2 } = await import("./runtime-SX36HGBA.js");
9502
9653
  const backend = await getBackend2();
9503
9654
  let memoryHasData = false;
9504
9655
  for (const model of models) {
@@ -9514,16 +9665,16 @@ async function maybeAutoMigrateLegacy(platform, models) {
9514
9665
  ` detected legacy .one/sync/data/${platform}.db (${dbSize}) \u2014 auto-migrating into memory before sync.
9515
9666
  `
9516
9667
  );
9517
- const { memMigrateCommand: memMigrateCommand3 } = await import("./migrate-IJI3BTWL.js");
9668
+ const { memMigrateCommand: memMigrateCommand3 } = await import("./migrate-TACDLGPD.js");
9518
9669
  await memMigrateCommand3({ platform, yes: true });
9519
9670
  return;
9520
9671
  }
9521
- const shouldMigrate = await p7.confirm({
9672
+ const shouldMigrate = await p6.confirm({
9522
9673
  message: `Found legacy .one/sync/data/${platform}.db (${dbSize}) with no corresponding memory records. Migrate into the unified memory store before syncing?`,
9523
9674
  initialValue: true
9524
9675
  });
9525
- if (p7.isCancel(shouldMigrate) || !shouldMigrate) return;
9526
- const { memMigrateCommand: memMigrateCommand2 } = await import("./migrate-IJI3BTWL.js");
9676
+ if (p6.isCancel(shouldMigrate) || !shouldMigrate) return;
9677
+ const { memMigrateCommand: memMigrateCommand2 } = await import("./migrate-TACDLGPD.js");
9527
9678
  await memMigrateCommand2({ platform, yes: true });
9528
9679
  }
9529
9680
  async function syncSuggestSearchableCommand(platformModel, options = {}) {
@@ -9584,16 +9735,16 @@ async function syncSuggestSearchableCommand(platformModel, options = {}) {
9584
9735
  async function syncListCommand(platform) {
9585
9736
  const profiles = listProfiles(platform);
9586
9737
  const state = await readSyncState();
9587
- const { getBackend: getBackend2 } = await import("./runtime-65IPTPVD.js");
9738
+ const { getBackend: getBackend2 } = await import("./runtime-SX36HGBA.js");
9588
9739
  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}`;
9740
+ const syncs = await Promise.all(profiles.map(async (p9) => {
9741
+ const modelState = state[p9.platform]?.[p9.model];
9742
+ const type = `${p9.platform}/${p9.model}`;
9592
9743
  const totalRecords = await backend.count(type, { status: "active" }).catch(() => 0);
9593
- const legacyDbSize = getDatabaseSize(p10.platform);
9744
+ const legacyDbSize = getDatabaseSize(p9.platform);
9594
9745
  return {
9595
- platform: p10.platform,
9596
- model: p10.model,
9746
+ platform: p9.platform,
9747
+ model: p9.model,
9597
9748
  lastSync: modelState?.lastSync ?? null,
9598
9749
  totalRecords,
9599
9750
  pagesProcessed: modelState?.pagesProcessed ?? 0,
@@ -9613,10 +9764,10 @@ async function syncListCommand(platform) {
9613
9764
  return;
9614
9765
  }
9615
9766
  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");
9767
+ const status2 = s.status === "idle" ? pc11.green("idle") : s.status === "syncing" ? pc11.yellow(`syncing \u2014 page ${s.pagesProcessed}`) : pc11.red("failed");
9617
9768
  const legacy = s.legacyDbSize && s.legacyDbSize !== "0 B" ? pc11.yellow(` legacy .db ${s.legacyDbSize}`) : "";
9618
9769
  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
9770
+ ` ${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
9771
  );
9621
9772
  }
9622
9773
  }
@@ -9624,7 +9775,7 @@ async function syncRemoveCommand(platform, options) {
9624
9775
  const modelList = options.models?.split(",").map((m) => m.trim());
9625
9776
  const preview = [];
9626
9777
  const profiles = listProfiles(platform);
9627
- const targetModels = modelList ?? profiles.map((p10) => p10.model);
9778
+ const targetModels = modelList ?? profiles.map((p9) => p9.model);
9628
9779
  try {
9629
9780
  if (targetModels.length > 0) {
9630
9781
  const db = await openDatabase(platform);
@@ -9636,14 +9787,14 @@ async function syncRemoveCommand(platform, options) {
9636
9787
  } catch {
9637
9788
  for (const model of targetModels) preview.push({ model, records: 0 });
9638
9789
  }
9639
- const totalRecords = preview.reduce((sum, p10) => sum + p10.records, 0);
9790
+ const totalRecords = preview.reduce((sum, p9) => sum + p9.records, 0);
9640
9791
  const dbSize = getDatabaseSize(platform);
9641
9792
  if (options.dryRun) {
9642
9793
  if (isAgentMode()) {
9643
9794
  json({ dryRun: true, platform, models: preview, totalRecords, dbSize });
9644
9795
  } else {
9645
9796
  note(
9646
- preview.map((p10) => ` ${p10.model.padEnd(30)} ${String(p10.records).padStart(8)} records`).join("\n") + `
9797
+ preview.map((p9) => ` ${p9.model.padEnd(30)} ${String(p9.records).padStart(8)} records`).join("\n") + `
9647
9798
 
9648
9799
  Total: ${totalRecords} records across ${preview.length} model(s), ${dbSize} on disk`,
9649
9800
  `Would remove from ${platform}`
@@ -9653,10 +9804,10 @@ async function syncRemoveCommand(platform, options) {
9653
9804
  }
9654
9805
  if (!options.yes && !isAgentMode()) {
9655
9806
  const target = modelList ? `${platform}/${modelList.join(", ")}` : `all synced data for ${platform}`;
9656
- const confirmed = await p7.confirm({
9807
+ const confirmed = await p6.confirm({
9657
9808
  message: `Remove ${target}? (${totalRecords} records, ${dbSize} on disk)`
9658
9809
  });
9659
- if (p7.isCancel(confirmed) || !confirmed) {
9810
+ if (p6.isCancel(confirmed) || !confirmed) {
9660
9811
  cancel("Cancelled.");
9661
9812
  return;
9662
9813
  }
@@ -9860,7 +10011,7 @@ function registerSyncSubcommands(sync) {
9860
10011
  await syncSqlCommand(platformModel, sql);
9861
10012
  });
9862
10013
  sync.command("schema <platform/model>").description("Inspect the JSON structure of synced records (field paths, types, examples) \u2014 useful before writing `sync sql` queries").action(async (platformModel) => {
9863
- const { syncSchemaCommand } = await import("./schema-OO4WK5ND.js");
10014
+ const { syncSchemaCommand } = await import("./schema-RJC2WQQ6.js");
9864
10015
  await syncSchemaCommand(platformModel);
9865
10016
  });
9866
10017
  sync.command("delete <platform/model>").description('Delete records from local sync data (e.g. one sync delete notion/pages --id "abc-123")').option("--id <value>", "Delete record by ID").option("--where <conditions>", 'Delete records matching conditions (e.g. "status=archived")').option("--where-sql <predicate>", `Delete using a raw SQL WHERE clause (e.g. "json_extract(data, '$.type') = 'promotion'")`).option("--yes", "Skip confirmation prompt").action(async (platformModel, options) => {
@@ -9891,7 +10042,7 @@ function registerSyncSubcommands(sync) {
9891
10042
  }
9892
10043
 
9893
10044
  // src/commands/mem/init.ts
9894
- import * as p8 from "@clack/prompts";
10045
+ import * as p7 from "@clack/prompts";
9895
10046
  async function memInitCommand(flags) {
9896
10047
  if (!readConfig()) {
9897
10048
  error("Run `one init` first to configure the base One CLI before `one mem init`.");
@@ -9900,11 +10051,11 @@ async function memInitCommand(flags) {
9900
10051
  if (isAgentMode()) {
9901
10052
  error("Memory is already configured. Pass --force to overwrite, or use `one mem config` to adjust.");
9902
10053
  }
9903
- const shouldOverwrite = flags.yes ?? await p8.confirm({
10054
+ const shouldOverwrite = flags.yes ?? await p7.confirm({
9904
10055
  message: "Memory is already configured. Overwrite the current config?",
9905
10056
  initialValue: false
9906
10057
  });
9907
- if (p8.isCancel(shouldOverwrite) || !shouldOverwrite) {
10058
+ if (p7.isCancel(shouldOverwrite) || !shouldOverwrite) {
9908
10059
  outro("Aborted. Run `one mem config` to adjust specific fields.");
9909
10060
  return;
9910
10061
  }
@@ -9954,7 +10105,7 @@ Run \`one mem doctor\` for a detailed report.`,
9954
10105
  async function interactiveInit(flags) {
9955
10106
  intro("one mem init");
9956
10107
  const plugins = listBackendPlugins();
9957
- const backend = flags.backend ?? await p8.select({
10108
+ const backend = flags.backend ?? await p7.select({
9958
10109
  message: "Where should memory live?",
9959
10110
  options: plugins.map((plug) => ({
9960
10111
  value: plug.name,
@@ -9963,26 +10114,26 @@ async function interactiveInit(flags) {
9963
10114
  })),
9964
10115
  initialValue: "embedded-postgres"
9965
10116
  });
9966
- if (p8.isCancel(backend)) error("Cancelled.");
10117
+ if (p7.isCancel(backend)) error("Cancelled.");
9967
10118
  const perBackend = {};
9968
10119
  if (backend === "embedded-postgres") {
9969
- const dataDir = flags.dbPath ?? await p8.text({
10120
+ const dataDir = flags.dbPath ?? await p7.text({
9970
10121
  message: "Postgres data directory (leave blank for default)",
9971
10122
  placeholder: "~/.one/pg",
9972
10123
  initialValue: ""
9973
10124
  });
9974
- if (p8.isCancel(dataDir)) error("Cancelled.");
10125
+ if (p7.isCancel(dataDir)) error("Cancelled.");
9975
10126
  if (dataDir) perBackend["embedded-postgres"] = { dataDir };
9976
10127
  } else if (backend === "postgres") {
9977
- const connectionString = flags.connectionString ?? await p8.text({
10128
+ const connectionString = flags.connectionString ?? await p7.text({
9978
10129
  message: "Postgres connection string",
9979
10130
  placeholder: "postgres://user:pass@host:5432/dbname",
9980
10131
  validate: (v) => v ? void 0 : "Connection string is required"
9981
10132
  });
9982
- if (p8.isCancel(connectionString)) error("Cancelled.");
10133
+ if (p7.isCancel(connectionString)) error("Cancelled.");
9983
10134
  perBackend.postgres = { connectionString };
9984
10135
  }
9985
- const provider = flags.embedding ?? await p8.select({
10136
+ const provider = flags.embedding ?? await p7.select({
9986
10137
  message: "Enable embeddings (semantic search)?",
9987
10138
  options: [
9988
10139
  { value: "openai", label: "Yes, via OpenAI", hint: "requires an API key" },
@@ -9990,7 +10141,7 @@ async function interactiveInit(flags) {
9990
10141
  ],
9991
10142
  initialValue: "none"
9992
10143
  });
9993
- if (p8.isCancel(provider)) error("Cancelled.");
10144
+ if (p7.isCancel(provider)) error("Cancelled.");
9994
10145
  let apiKey;
9995
10146
  let embedOnAdd = DEFAULT_MEMORY_CONFIG.defaults.embedOnAdd;
9996
10147
  let embedOnSync = DEFAULT_MEMORY_CONFIG.defaults.embedOnSync;
@@ -9999,25 +10150,25 @@ async function interactiveInit(flags) {
9999
10150
  if (flags.openaiKey) {
10000
10151
  apiKey = flags.openaiKey;
10001
10152
  } else {
10002
- const entered = await p8.password({
10153
+ const entered = await p7.password({
10003
10154
  message: "OpenAI API key",
10004
10155
  mask: "\u2022",
10005
10156
  validate: (v) => v || envKey ? void 0 : "Required (or set OPENAI_API_KEY)"
10006
10157
  });
10007
- if (p8.isCancel(entered)) error("Cancelled.");
10158
+ if (p7.isCancel(entered)) error("Cancelled.");
10008
10159
  apiKey = entered || envKey;
10009
10160
  }
10010
- const embedAdd = flags.embedOnAdd ?? await p8.confirm({
10161
+ const embedAdd = flags.embedOnAdd ?? await p7.confirm({
10011
10162
  message: "Embed user memories (mem add) by default?",
10012
10163
  initialValue: true
10013
10164
  });
10014
- if (p8.isCancel(embedAdd)) error("Cancelled.");
10165
+ if (p7.isCancel(embedAdd)) error("Cancelled.");
10015
10166
  embedOnAdd = embedAdd;
10016
- const embedSync = flags.embedOnSync ?? await p8.confirm({
10167
+ const embedSync = flags.embedOnSync ?? await p7.confirm({
10017
10168
  message: "Embed synced records by default? (overridable per profile)",
10018
10169
  initialValue: false
10019
10170
  });
10020
- if (p8.isCancel(embedSync)) error("Cancelled.");
10171
+ if (p7.isCancel(embedSync)) error("Cancelled.");
10021
10172
  embedOnSync = embedSync;
10022
10173
  }
10023
10174
  return {
@@ -10238,9 +10389,9 @@ function redactSecrets(cfg) {
10238
10389
  function getPath(obj, path14) {
10239
10390
  const parts = path14.split(".");
10240
10391
  let cur = obj;
10241
- for (const part of parts) {
10392
+ for (const part2 of parts) {
10242
10393
  if (cur == null || typeof cur !== "object") return void 0;
10243
- cur = cur[part];
10394
+ cur = cur[part2];
10244
10395
  }
10245
10396
  return cur;
10246
10397
  }
@@ -10248,9 +10399,9 @@ function setPath(obj, path14, value) {
10248
10399
  const parts = path14.split(".");
10249
10400
  let cur = obj;
10250
10401
  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];
10402
+ const part2 = parts[i];
10403
+ if (cur[part2] == null || typeof cur[part2] !== "object") cur[part2] = {};
10404
+ cur = cur[part2];
10254
10405
  }
10255
10406
  cur[parts[parts.length - 1]] = value;
10256
10407
  return obj;
@@ -10259,9 +10410,9 @@ function unsetPath(obj, path14) {
10259
10410
  const parts = path14.split(".");
10260
10411
  let cur = obj;
10261
10412
  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];
10413
+ const part2 = parts[i];
10414
+ if (cur[part2] == null || typeof cur[part2] !== "object") return obj;
10415
+ cur = cur[part2];
10265
10416
  }
10266
10417
  delete cur[parts[parts.length - 1]];
10267
10418
  return obj;
@@ -10375,10 +10526,10 @@ async function memListCommand(type, flags) {
10375
10526
  const backend = await getBackend();
10376
10527
  const limit = flags.limit ? parsePositiveInt(flags.limit, 100, "limit") : 100;
10377
10528
  const offset = flags.offset ? parsePositiveInt(flags.offset, 0, "offset") : 0;
10378
- const status = flags.status ?? "active";
10529
+ const status2 = flags.status ?? "active";
10379
10530
  const [records, total] = await Promise.all([
10380
- backend.list(type, { limit, offset, status }),
10381
- backend.count(type, { status })
10531
+ backend.list(type, { limit, offset, status: status2 }),
10532
+ backend.count(type, { status: status2 })
10382
10533
  ]);
10383
10534
  if (isAgentMode()) {
10384
10535
  json({ items: records, returned: records.length, total, limit, offset });
@@ -10581,7 +10732,7 @@ async function memDoctorCommand() {
10581
10732
  return emit(checks, { vectorSearchAvailable: true });
10582
10733
  }
10583
10734
  checks.push({ name: "memory config exists", ok: true, detail: `backend=${cfg.backend}` });
10584
- const available = listBackendPlugins().map((p10) => p10.name);
10735
+ const available = listBackendPlugins().map((p9) => p9.name);
10585
10736
  if (!available.includes(cfg.backend)) {
10586
10737
  checks.push({
10587
10738
  name: `backend plugin "${cfg.backend}" resolves`,
@@ -10712,10 +10863,10 @@ async function memExportCommand(outfile) {
10712
10863
  const pageSize = 500;
10713
10864
  let written = 0;
10714
10865
  for (const type of all) {
10715
- for (const status of ["active", "archived"]) {
10866
+ for (const status2 of ["active", "archived"]) {
10716
10867
  let offset = 0;
10717
10868
  while (true) {
10718
- const page = await backend.list(type, { limit: pageSize, offset, status });
10869
+ const page = await backend.list(type, { limit: pageSize, offset, status: status2 });
10719
10870
  for (const r of page) {
10720
10871
  await writeLine(stream, JSON.stringify(r) + "\n");
10721
10872
  written++;
@@ -10925,12 +11076,12 @@ async function memReindexSearchableCommand(flags) {
10925
11076
  // src/commands/mem.ts
10926
11077
  function memStatusCommand() {
10927
11078
  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
11079
+ const plugins = listBackendPlugins().map((p9) => ({
11080
+ name: p9.name,
11081
+ description: p9.description,
11082
+ version: p9.version,
11083
+ schemaVersion: p9.schemaVersion,
11084
+ capabilities: p9.capabilities
10934
11085
  }));
10935
11086
  const upgrade = semanticSearchUpgradeHint();
10936
11087
  const payload = {
@@ -11052,9 +11203,6 @@ async function cacheUpdateAllCommand() {
11052
11203
  error("Not configured. Run `one init` first.");
11053
11204
  }
11054
11205
  const api = new OneApi(apiKey, getApiBase());
11055
- const ac = getAccessControlFromAllSources();
11056
- const permissions = ac.permissions || "admin";
11057
- const actionIds = ac.actionIds || ["*"];
11058
11206
  const entries = listCacheEntries();
11059
11207
  if (entries.length === 0) {
11060
11208
  if (isAgentMode()) {
@@ -11071,44 +11219,9 @@ async function cacheUpdateAllCommand() {
11071
11219
  const errors = [];
11072
11220
  for (const e of entries) {
11073
11221
  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
- }
11222
+ const result = await api.getActionDetailsWithMeta(e.entry.key);
11223
+ writeCache(e.filePath, makeCacheEntry(e.entry.key, result.data, result.etag));
11224
+ updated++;
11112
11225
  } catch (err) {
11113
11226
  failed++;
11114
11227
  errors.push({
@@ -11174,14 +11287,14 @@ Before using any feature, read its guide section first: \`one guide actions\`, \
11174
11287
  ## Features
11175
11288
 
11176
11289
  ### 1. Actions \u2014 Execute API calls on 750+ platforms
11177
- Search for actions, read their docs, and execute them. This is the core workflow.
11290
+ Find the actions a task needs with their docs, in one call, then execute them. This is the core workflow.
11178
11291
 
11179
11292
  **Quick start:**
11180
11293
  \`\`\`bash
11181
11294
  one --agent connection list # See connected platforms + your access on each
11182
11295
  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)
11296
+ one --agent actions find <platform> "<intent>" [<platform> "<intent>" ...] --task "<the job, in general terms>" # Find every action, with its docs (READ them)
11297
+ one --agent actions load <actionId> --section "<name>" # More of a doc: a section it left out, --full, --toc
11185
11298
  one --agent actions execute <platform> <actionId> <key> -d '{}' # Execute it
11186
11299
  \`\`\`
11187
11300
 
@@ -11244,7 +11357,7 @@ one --agent relay deliveries --endpoint-id <id> # Check delivery
11244
11357
  - \`passthrough\` actions map webhook fields to another platform's API using Handlebars: \`{{payload.data.object.email}}\`
11245
11358
  - Template context: \`{{relayEventId}}\`, \`{{platform}}\`, \`{{eventType}}\`, \`{{payload}}\`, \`{{timestamp}}\`, \`{{connectionId}}\`
11246
11359
  - \`--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
11360
+ - Use \`actions find\` (and \`actions load\` for more) to learn both the incoming payload shape AND the destination API shape before building templates
11248
11361
 
11249
11362
  ### 4. Memory + Sync \u2014 Unified store with hybrid FTS + semantic search
11250
11363
  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 +11366,7 @@ One ships a local memory store (a real Postgres process bootstrapped on demand v
11253
11366
 
11254
11367
  Request specific sections:
11255
11368
  - \`one guide overview\` \u2014 This section
11256
- - \`one guide actions\` \u2014 Actions reference (search, knowledge, execute)
11369
+ - \`one guide actions\` \u2014 Actions reference (find, load, execute)
11257
11370
  - \`one guide flows\` \u2014 Workflow engine reference (step types, selectors, examples)
11258
11371
  - \`one guide relay\` \u2014 Webhook relay reference (templates, passthrough actions)
11259
11372
  - \`one guide cache\` \u2014 Cache management (TTL, flags, commands)
@@ -11264,7 +11377,7 @@ Request specific sections:
11264
11377
 
11265
11378
  - **Always use \`--agent\` flag** for structured JSON output
11266
11379
  - 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
11380
+ - Always use the **exact action ID** from a find answer \u2014 don't guess
11268
11381
  - Always read **knowledge** before executing any action
11269
11382
  - Connection keys come from \`one connection list\` \u2014 don't hardcode them
11270
11383
  - \`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 +11385,9 @@ Request specific sections:
11272
11385
  `;
11273
11386
  var GUIDE_ACTIONS = `# One Actions \u2014 Reference
11274
11387
 
11275
- ## Workflow: search \u2192 knowledge \u2192 execute
11388
+ ## Workflow: find \u2192 execute
11276
11389
 
11277
- Always follow this sequence. Never skip the knowledge step.
11390
+ Always follow this sequence. Never execute without reading the action's documentation, which \`actions find\` returns.
11278
11391
 
11279
11392
  ### 1. List Connections
11280
11393
 
@@ -11288,9 +11401,9 @@ Returns platforms, status, connection keys, tags, and an \`access\` field per co
11288
11401
  |----------|---------|
11289
11402
  | \`{"policy": "full"}\` | Every action on the connection |
11290
11403
  | \`{"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\` |
11404
+ | \`{"policy": "actions", "actions": [{"actionId", "title", "method"}]}\` | Only these exact actions \u2014 use them directly: \`actions load <actionId>\` reads their docs, no find needed |
11292
11405
 
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).
11406
+ 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
11407
 
11295
11408
  Read \`access\` before planning \u2014 it prevents proposing an action the config will reject. Change it with \`one config\`.
11296
11409
 
@@ -11302,60 +11415,71 @@ one --agent connection delete <connection-key>
11302
11415
 
11303
11416
  Removes a connection by its key. In agent mode, returns \`{"deleted": true, "platform": "...", "key": "..."}\`. The connection key comes from \`one connection list\`.
11304
11417
 
11305
- ### 2. Search Actions
11418
+ ### 2. Find Actions
11306
11419
 
11307
11420
  \`\`\`bash
11308
- one --agent actions search <platform> "<query>" -t execute
11421
+ one --agent actions find <platform> "<intent>" [<platform> "<intent>" ...] --task "<the job, in general terms>"
11309
11422
  \`\`\`
11310
11423
 
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
11424
+ 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
11425
 
11315
- ### 3. Get Knowledge
11316
-
11317
- \`\`\`bash
11318
- one --agent actions knowledge <platform> <actionId>
11319
- \`\`\`
11426
+ - **\`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.
11427
+ - **\`--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.
11428
+ - **\`-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\`.
11429
+ - **\`--ai-model\`** (optional) names the model running the CLI (e.g. \`claude-sonnet-5\`); it will be used to tune documentation per model.
11320
11430
 
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:
11431
+ In \`--agent\` mode:
11324
11432
 
11325
11433
  \`\`\`json
11326
11434
  {
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 }
11435
+ "answers": [
11436
+ {
11437
+ "platform": "gmail",
11438
+ "intent": "send an email",
11439
+ "status": "Chosen with confidence 0.99.",
11440
+ "selector": "model",
11441
+ "confidence": 0.99,
11442
+ "selected": [
11443
+ { "actionId": "conn_mod_def::...", "title": "Send Email", "method": "POST", "path": "/v1/gmail/send-email",
11444
+ "knowledge": "...digest markdown, ends with the exact actions load command for what it left out...", "truncated": true }
11445
+ ],
11446
+ "alsoSelected": [],
11447
+ "runnerUp": { "actionId": "...", "title": "...", "method": "...", "path": "...", "knowledge": "...", "truncated": false },
11448
+ "alternatives": [ { "actionId": "...", "title": "...", "method": "...", "path": "..." } ]
11449
+ }
11334
11450
  ],
11335
- "omitted": 2,
11336
- "omittedChars": 19836,
11337
- "more": { "section": "one --agent actions knowledge <platform> <actionId> --section <id>[,<id>...]", "full": "..." }
11451
+ "guide": "Run an action with: one --agent actions execute <platform> <actionId> <connectionKey> ..."
11338
11452
  }
11339
11453
  \`\`\`
11340
11454
 
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:
11455
+ - **\`selected\`** \u2014 the action(s) to use, documented. More than one means the intent needs them together (look up, then update).
11456
+ - **\`alsoSelected\`** \u2014 also needed, listed rather than documented to keep the answer small: \`actions load\` them.
11457
+ - **\`runnerUp\`** \u2014 only when the model was unsure: a **substitute** for the pick. Use one or the other, **never both**.
11458
+ - **\`alternatives\`** \u2014 other candidates, undocumented.
11459
+ - **\`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).
11460
+ - **\`guide\`** \u2014 how to execute, stated once for every action.
11461
+ - \`truncated: false\` means \`knowledge\` is the whole document; small docs are never trimmed.
11344
11462
 
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
- \`\`\`
11463
+ 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
11464
 
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.
11465
+ 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
11466
 
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:
11467
+ Find reads documentation through the local cache, so a later \`actions execute\` of the same action makes a single API call.
11468
+
11469
+ ### 3. Load More of a Document
11354
11470
 
11355
11471
  \`\`\`bash
11356
- one --agent actions knowledge <platform> <actionId> --toc
11472
+ one --agent actions load <actionId> --section "Response Fields"
11473
+ one --agent actions load <actionId> --section response,optional
11474
+ one --agent actions load <actionId> --full
11475
+ one --agent actions load <actionId> --toc
11476
+ one --agent actions load <actionId> # the digest: how to read an alternative
11357
11477
  \`\`\`
11358
11478
 
11479
+ 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.
11480
+
11481
+ 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.
11482
+
11359
11483
  ### 4. Execute
11360
11484
 
11361
11485
  \`\`\`bash
@@ -11375,7 +11499,7 @@ one --agent actions execute <platform> <actionId> <connectionKey> [options]
11375
11499
  - \`--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
11500
  - \`--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
11501
 
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.
11502
+ 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
11503
 
11380
11504
  **Do NOT** pass path or query parameters in \`-d\`. Use the correct flags.
11381
11505
 
@@ -11414,7 +11538,7 @@ All errors return JSON: \`{"error": "message"}\`. Check the \`error\` key.
11414
11538
 
11415
11539
  - Platform names are **lowercase**; multi-word names use dashes (e.g., \`hubspot\`, \`ship-station\`)
11416
11540
  - JSON flags use single quotes around the JSON to avoid shell escaping
11417
- - If search returns no results, try broader queries
11541
+ - If find says no action fits, rephrase the intent by outcome (\`"list invoices"\`, not an endpoint name) or check the platform name
11418
11542
  - Access control settings from \`one config\` may restrict execution
11419
11543
  `;
11420
11544
  var GUIDE_FLOWS = generateFlowGuide();
@@ -11529,9 +11653,9 @@ var GUIDE_CACHE = `# One Cache \u2014 Reference
11529
11653
 
11530
11654
  ## Overview
11531
11655
 
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.
11656
+ 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
11657
 
11534
- Cache location: \`~/.one/cache/knowledge/\` and \`~/.one/cache/search/\`
11658
+ Cache location: \`~/.one/cache/knowledge/\`
11535
11659
 
11536
11660
  ## How It Works
11537
11661
 
@@ -11539,7 +11663,7 @@ Cache location: \`~/.one/cache/knowledge/\` and \`~/.one/cache/search/\`
11539
11663
  - **Subsequent calls (within TTL)**: serves from cache instantly, no API call
11540
11664
  - **After TTL expires**: makes a conditional request (ETag). If content unchanged, refreshes the cache timestamp. If changed, writes fresh data.
11541
11665
  - **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
11666
+ - **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
11667
 
11544
11668
  Default TTL: 3600 seconds (1 hour). Configure via \`ONE_CACHE_TTL\` env var or \`cacheTtl\` in \`~/.one/config.json\`.
11545
11669
 
@@ -11547,44 +11671,27 @@ Default TTL: 3600 seconds (1 hour). Configure via \`ONE_CACHE_TTL\` env var or \
11547
11671
 
11548
11672
  | Cached | Not Cached |
11549
11673
  |--------|-----------|
11550
- | \`actions knowledge\` (API docs, change infrequently) | \`actions execute\` responses (live data, always fresh) |
11551
- | \`actions search\` results | \`connection list\` (changes with add/remove) |
11674
+ | Action docs read by \`actions find\` / \`actions load\` (change infrequently) | \`actions execute\` responses (live data, always fresh) |
11675
+ | | \`actions find\` picks (the decision model answers every call) |
11676
+ | | \`connection list\` (changes with add/remove) |
11552
11677
  | Action details used by execute / flow / sync preflight (method, path, schema) | |
11553
11678
 
11554
- ## Agent Mode \`_cache\` Metadata
11679
+ ## Cache Status
11555
11680
 
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.
11681
+ \`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
11682
 
11574
11683
  ## Cache Flags
11575
11684
 
11576
11685
  \`\`\`bash
11577
11686
  # Skip cache, fetch fresh (result still gets cached for next time)
11578
- one --agent actions knowledge <platform> <actionId> --no-cache
11687
+ one --agent actions load <actionId> --no-cache
11688
+ one --agent actions find <platform> "<intent>" --no-cache
11579
11689
 
11580
11690
  # Check cache status without fetching
11581
- one --agent actions knowledge <platform> <actionId> --cache-status
11691
+ one --agent actions load <actionId> --cache-status
11582
11692
 
11583
11693
  # 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
11694
+ one --agent actions load <actionId> --section "Response Fields"
11588
11695
 
11589
11696
  # Same for execute's action-details preflight (the action itself always runs live)
11590
11697
  one --agent actions execute <platform> <actionId> <key> --no-cache
@@ -11597,7 +11704,7 @@ In \`--agent\` mode, execute responses include \`"_preflight": {"cache": "hit"|"
11597
11704
  \`\`\`bash
11598
11705
  one cache list # List all cached entries with age and status
11599
11706
  one cache list --expired # List only expired entries
11600
- one cache clear # Delete all cached knowledge and search data
11707
+ one cache clear # Delete all cached action documentation
11601
11708
  one cache clear <actionId> # Delete one specific entry
11602
11709
  one cache update-all # Re-fetch fresh data for all cached entries
11603
11710
  \`\`\`
@@ -11627,6 +11734,8 @@ The unified memory store is a local, pluggable database (\`embedded-postgres\` b
11627
11734
  The first \`one mem\` call on a fresh install auto-initializes:
11628
11735
  - Backend: \`embedded-postgres\` (Postgres 18 via pgserve; downloads ~52MB of binaries on first use, ~2s on later boots)
11629
11736
  - Cluster path: \`~/.one/pg/cluster/\`, daemon PID/port at \`~/.one/pg/.pgserve.json\`
11737
+ - Port: \`5434\` by default. If another program already holds it (a database tunnel, another Postgres), the daemon starts on the next free port and records it in \`.pgserve.json\`. A port pinned with \`mem config set embedded-postgres.port <n>\` is never moved \u2014 a conflict there is an error naming the port.
11738
+ - Self-healing: a running daemon is reused only when the Postgres on its port reports this cluster's data directory. A Postgres left holding the cluster by a dead or stuck pgserve is stopped and a fresh daemon started. \`pgserve.log\` is trimmed to its last 1 MB once it passes 10 MB.
11630
11739
  - Embedding provider: \`openai\` if a key is already resolvable AND pgvector is loadable; else \`none\`
11631
11740
 
11632
11741
  If pgvector isn't installed in the bundled Postgres (the default binary distribution doesn't ship it yet), the schema applies cleanly without an \`embedding\` column, all FTS paths work, and \`mem doctor\` emits an \`_upgrade\` block pointing at \`brew install pgvector\` when an OpenAI key is present.
@@ -11858,7 +11967,7 @@ Why the block:
11858
11967
  enrichment locally \u2014 server-side fan-out on top of that creates 5xx, not value
11859
11968
 
11860
11969
  How to build a profile:
11861
- 1. \`one actions search <platform> "<model>"\` surfaces passthrough actions.
11970
+ 1. \`one actions find <platform> "list <model>" -t knowledge\` surfaces passthrough actions (the pick and its alternatives).
11862
11971
  \`sync init\`'s auto-infer also drops customs before offering choices.
11863
11972
  2. Prefer GET passthrough endpoints (e.g. /gmail/v1/users/{userId}/threads)
11864
11973
  over POST custom endpoints (e.g. /gmail/get-threads).
@@ -12277,8 +12386,9 @@ Every \`sync X\` command is also exposed as \`mem sync X\` \u2014 same handlers,
12277
12386
  logs/{platform}.log # cron run logs
12278
12387
  locks/{platform}_{model}/ # cross-process sync locks
12279
12388
  ~/.one/pg/cluster/ # unified memory store \u2014 embedded Postgres data dir
12280
- ~/.one/pg/.pgserve.json # daemon PID/port file (cleared on stop)
12281
- ~/.one/pg/pgserve.log # daemon stdout/stderr
12389
+ ~/.one/pg/.pgserve.json # daemon PID/port file
12390
+ ~/.one/pg/.pgserve.lock # held while a CLI process starts the daemon
12391
+ ~/.one/pg/pgserve.log # daemon stdout/stderr (trimmed to 1 MB past 10 MB)
12282
12392
  ~/.one/config.json # apiKey + openaiApiKey + memory config block
12283
12393
  ~/.one/sync/
12284
12394
  schedules.json # global schedule registry
@@ -12289,7 +12399,7 @@ var TOPICS = [
12289
12399
  { topic: "actions", description: "Search, read docs, and execute platform actions" },
12290
12400
  { topic: "flows", description: "Build and execute multi-step workflows" },
12291
12401
  { topic: "relay", description: "Receive webhooks and forward to other platforms" },
12292
- { topic: "cache", description: "Local caching for knowledge and search responses" },
12402
+ { topic: "cache", description: "Local caching for action documentation" },
12293
12403
  { topic: "memory", description: "Unified memory store: notes, decisions, synced rows, semantic search" },
12294
12404
  { topic: "sync", description: "Sync platform data into memory for instant offline queries" },
12295
12405
  { topic: "all", description: "Complete guide (all topics combined)" }
@@ -12381,7 +12491,7 @@ function pairKey(a, b) {
12381
12491
  }
12382
12492
  function getWorkflowExamples(connectedPlatforms) {
12383
12493
  const results = [];
12384
- const platforms = connectedPlatforms.map((p10) => p10.toLowerCase());
12494
+ const platforms = connectedPlatforms.map((p9) => p9.toLowerCase());
12385
12495
  for (let i = 0; i < platforms.length; i++) {
12386
12496
  for (let j = i + 1; j < platforms.length; j++) {
12387
12497
  const key = pairKey(platforms[i], platforms[j]);
@@ -12498,17 +12608,17 @@ common mistakes to avoid. Never guess \u2014 read the skill, then act.
12498
12608
 
12499
12609
  ### Quick reference:
12500
12610
  - \`one --agent list\` \u2014 See connected platforms and connection keys
12501
- - \`one --agent actions search <platform> "<query>"\` \u2014 Find actions
12502
- - \`one --agent actions knowledge <platform> <actionId>\` \u2014 Read docs (REQUIRED before execute; a digest \u2014 add \`--section <name>\` or \`--full\` for more)
12611
+ - \`one --agent actions find <platform> "<intent>" [<platform> "<intent>" ...]\` \u2014 Find every action a task needs, with its docs (READ them before execute)
12612
+ - \`one --agent actions load <actionId> --section <name>\` \u2014 More of a doc (a digest names the exact command), or \`--full\`
12503
12613
  - \`one --agent actions execute <platform> <actionId> <connectionKey>\` \u2014 Execute action
12504
12614
  - \`one --agent flow create\` \u2014 Build multi-step workflows
12505
12615
  - \`one --agent relay create\` \u2014 Set up webhook relay (receive events, forward to other platforms)
12506
12616
  - \`one --agent guide\` \u2014 Full documentation
12507
12617
  - \`one add <platform>\` \u2014 Connect a new platform (interactive, no --agent)
12508
12618
 
12509
- ### Workflow: search -> knowledge -> execute
12510
- Always read the knowledge before executing. It tells you required parameters,
12511
- validation rules, and platform-specific details.
12619
+ ### Workflow: find -> execute
12620
+ Always read the documentation find returns before executing. It tells you
12621
+ required parameters, validation rules, and platform-specific details.
12512
12622
 
12513
12623
  ### Webhook Relay
12514
12624
  Use \`one relay\` to receive webhooks from platforms (Stripe, GitHub, etc.)
@@ -12522,8 +12632,7 @@ Handlebars templates. No middleware needed.
12522
12632
  Every command supports \`--agent\` which gives you clean, structured JSON
12523
12633
  output instead of human-formatted text. Always use it:
12524
12634
  one --agent list
12525
- one --agent actions search gmail "send email"
12526
- one --agent actions knowledge gmail <actionId>
12635
+ one --agent actions find gmail "send an email" --task "email a report to a contact"
12527
12636
  one --agent actions execute gmail <actionId> <connectionKey> -d '{...}'
12528
12637
  one --agent platforms
12529
12638
  one --agent guide
@@ -12531,8 +12640,8 @@ output instead of human-formatted text. Always use it:
12531
12640
  The \`--agent\` flag goes right after \`one\`, before the subcommand.
12532
12641
 
12533
12642
  ### Discovery Workflow (follow this every time):
12534
- 1. \`one --agent actions search <platform> "<query>"\` \u2014 Find the right action
12535
- 2. \`one --agent actions knowledge <platform> <actionId>\` \u2014 Read the docs (ALWAYS before execute)
12643
+ 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
12644
+ 2. Read each action's docs (ALWAYS before execute); \`one --agent actions load <actionId> --section <name>\` for a section a digest left out
12536
12645
  3. \`one --agent actions execute <platform> <actionId> <connectionKey>\` \u2014 Execute it
12537
12646
 
12538
12647
  ### Multi-Step Workflows:
@@ -12613,8 +12722,8 @@ You have ${connections.length} platform(s) connected:
12613
12722
  const tableHeader = " Platform Status Connection Key";
12614
12723
  const tableRows = connections.map((c) => {
12615
12724
  const platform = c.platform.padEnd(22);
12616
- const status = c.state.padEnd(14);
12617
- return ` ${platform}${status}${c.key}`;
12725
+ const status2 = c.state.padEnd(14);
12726
+ return ` ${platform}${status2}${c.key}`;
12618
12727
  });
12619
12728
  return header + "\n" + tableHeader + "\n" + tableRows.join("\n");
12620
12729
  }
@@ -12625,13 +12734,13 @@ function buildDemoActions(connections) {
12625
12734
  const connectedPlatforms = connections.map((c) => c.platform.toLowerCase());
12626
12735
  const popularPlatforms = ["gmail", "google-calendar", "slack", "shopify", "hubspot", "github"];
12627
12736
  const platformsToShow = [
12628
- ...connectedPlatforms.filter((p10) => PLATFORM_DEMO_ACTIONS[p10]),
12629
- ...popularPlatforms.filter((p10) => !connectedPlatforms.includes(p10))
12737
+ ...connectedPlatforms.filter((p9) => PLATFORM_DEMO_ACTIONS[p9]),
12738
+ ...popularPlatforms.filter((p9) => !connectedPlatforms.includes(p9))
12630
12739
  ];
12631
12740
  const seen = /* @__PURE__ */ new Set();
12632
- const unique = platformsToShow.filter((p10) => {
12633
- if (seen.has(p10)) return false;
12634
- seen.add(p10);
12741
+ const unique = platformsToShow.filter((p9) => {
12742
+ if (seen.has(p9)) return false;
12743
+ seen.add(p9);
12635
12744
  return true;
12636
12745
  }).slice(0, 6);
12637
12746
  for (const platform of unique) {
@@ -12640,7 +12749,7 @@ function buildDemoActions(connections) {
12640
12749
  const displayName = platform.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
12641
12750
  lines.push("");
12642
12751
  lines.push(`### ${displayName}`);
12643
- lines.push(`- ${demo.description}: \`one actions search ${platform} "${demo.query}"\``);
12752
+ lines.push(`- ${demo.description}: \`one actions find ${platform} "${demo.query}"\``);
12644
12753
  lines.push(`- Then get knowledge and execute to show the user the results`);
12645
12754
  }
12646
12755
  lines.push("");
@@ -12664,7 +12773,7 @@ function buildWorkflowIdeas(connections) {
12664
12773
 
12665
12774
  // src/commands/logout.ts
12666
12775
  import fs13 from "fs";
12667
- import * as p9 from "@clack/prompts";
12776
+ import * as p8 from "@clack/prompts";
12668
12777
  function formatWhoami(config2, apiKey, pc16) {
12669
12778
  const whoami = config2.whoami;
12670
12779
  const env = getEnvFromApiKey(apiKey);
@@ -12726,8 +12835,8 @@ async function logoutCommand() {
12726
12835
  infoLines.push(`${pc16.magenta("Global config:")}`);
12727
12836
  infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey, pc16));
12728
12837
  }
12729
- p9.note(infoLines.join("\n"));
12730
- const choice = await p9.select({
12838
+ p8.note(infoLines.join("\n"));
12839
+ const choice = await p8.select({
12731
12840
  message: "What would you like to log out of?",
12732
12841
  options: [
12733
12842
  { value: "project", label: "This directory", hint: "local config only" },
@@ -12735,8 +12844,8 @@ async function logoutCommand() {
12735
12844
  { value: "both", label: "Both", hint: "remove all credentials" }
12736
12845
  ]
12737
12846
  });
12738
- if (p9.isCancel(choice)) {
12739
- p9.cancel("Logout cancelled.");
12847
+ if (p8.isCancel(choice)) {
12848
+ p8.cancel("Logout cancelled.");
12740
12849
  return;
12741
12850
  }
12742
12851
  targetScope = choice;
@@ -12744,18 +12853,18 @@ async function logoutCommand() {
12744
12853
  const infoLines = ["You are logged in.", ""];
12745
12854
  infoLines.push(`${pc16.dim("Stored in")} ${pc16.cyan("local config")}`);
12746
12855
  infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey, pc16));
12747
- p9.note(infoLines.join("\n"));
12856
+ p8.note(infoLines.join("\n"));
12748
12857
  targetScope = "project";
12749
12858
  } else if (hasGlobal) {
12750
12859
  const infoLines = ["You are logged in.", ""];
12751
12860
  infoLines.push(`${pc16.dim("Stored in")} ${pc16.magenta("global config")}`);
12752
12861
  infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey, pc16));
12753
- p9.note(infoLines.join("\n"));
12862
+ p8.note(infoLines.join("\n"));
12754
12863
  targetScope = "global";
12755
12864
  } else {
12756
- p9.log.warn("Credentials are set via environment variable or .onerc, not a config file.");
12757
- p9.log.info("Remove the ONE_SECRET variable from your environment or .onerc file.");
12758
- p9.outro("Nothing to remove.");
12865
+ p8.log.warn("Credentials are set via environment variable or .onerc, not a config file.");
12866
+ p8.log.info("Remove the ONE_SECRET variable from your environment or .onerc file.");
12867
+ p8.outro("Nothing to remove.");
12759
12868
  return;
12760
12869
  }
12761
12870
  const scopeLabels = {
@@ -12763,11 +12872,11 @@ async function logoutCommand() {
12763
12872
  global: "global",
12764
12873
  both: "all"
12765
12874
  };
12766
- const confirm7 = await p9.confirm({
12875
+ const confirm7 = await p8.confirm({
12767
12876
  message: `Remove ${scopeLabels[targetScope]} credentials?`
12768
12877
  });
12769
- if (p9.isCancel(confirm7) || !confirm7) {
12770
- p9.cancel("Logout cancelled.");
12878
+ if (p8.isCancel(confirm7) || !confirm7) {
12879
+ p8.cancel("Logout cancelled.");
12771
12880
  return;
12772
12881
  }
12773
12882
  if (targetScope === "project" || targetScope === "both") {
@@ -12778,9 +12887,9 @@ async function logoutCommand() {
12778
12887
  const globalPath = getGlobalConfigPath();
12779
12888
  if (fs13.existsSync(globalPath)) fs13.unlinkSync(globalPath);
12780
12889
  }
12781
- p9.log.success("Credentials cleared.");
12782
- p9.log.info("Your API key is still active. Manage keys at app.withone.ai/settings");
12783
- p9.outro("Logged out.");
12890
+ p8.log.success("Credentials cleared.");
12891
+ p8.log.info("Your API key is still active. Manage keys at app.withone.ai/settings");
12892
+ p8.outro("Logged out.");
12784
12893
  }
12785
12894
 
12786
12895
  // src/cli.ts
@@ -12801,9 +12910,9 @@ program.name("one").option("--agent", "Machine-readable JSON output (no colors,
12801
12910
 
12802
12911
  Workflow (use these in order):
12803
12912
  1. one list List connected platforms, keys, and your access on each
12804
- 2. one actions search <platform> <q> Search for actions using natural language
12805
- 3. one actions knowledge <plat> <id> Get docs for an action (ALWAYS do this before execute; --section/--full for more)
12806
- 4. one actions execute <p> <id> <key> Execute the action
12913
+ 2. one actions find <p> <intent> ... Find the action for every operation a task needs, with its docs (ALWAYS read them before execute)
12914
+ 3. one actions execute <p> <id> <key> Execute the action
12915
+ one actions load <id> --section <s> More of an action's docs: a section a digest left out, --full, or --toc
12807
12916
 
12808
12917
  Guide:
12809
12918
  one guide [topic] Full CLI guide (topics: overview, actions, workflows, memory, sync, all)
@@ -12850,11 +12959,9 @@ program.name("one").option("--agent", "Machine-readable JSON output (no colors,
12850
12959
  $ one list
12851
12960
  # Find: gmail operational live::gmail::default::abc123
12852
12961
 
12853
- $ one actions search gmail "send email" -t execute
12854
- # Find: POST Send Email conn_mod_def::xxx::yyy
12855
-
12856
- $ one actions knowledge gmail conn_mod_def::xxx::yyy
12857
- # Read the docs: required fields are to, subject, body, connectionKey
12962
+ $ one actions find gmail "send an email" --task "email a report to a contact"
12963
+ # Send Email \xB7 POST /v1/gmail/send-email \xB7 actionId: conn_mod_def::xxx::yyy
12964
+ # ...its docs: required fields are to, subject, body, connectionKey
12858
12965
 
12859
12966
  $ one actions execute gmail conn_mod_def::xxx::yyy live::gmail::default::abc123 \\
12860
12967
  -d '{"to":"j@example.com","subject":"Hello","body":"Hi!","connectionKey":"live::gmail::default::abc123"}'
@@ -12961,22 +13068,22 @@ configSkills.command("sync").description("Re-copy packaged skill files over the
12961
13068
  console.log(`\u2717 Sync failed${result.error ? ": " + result.error : ""}`);
12962
13069
  });
12963
13070
  configSkills.command("status").description("Show installed skill version and whether it matches the current CLI").action(async () => {
12964
- const status = getSkillStatus();
13071
+ const status2 = getSkillStatus();
12965
13072
  if (isAgentMode()) {
12966
- json({ command: "config skills status", ...status });
13073
+ json({ command: "config skills status", ...status2 });
12967
13074
  return;
12968
13075
  }
12969
- if (!status.installed) {
13076
+ if (!status2.installed) {
12970
13077
  console.log("Skill is not installed. Run 'one init' to install it.");
12971
- console.log(`Canonical path (empty): ${status.canonicalPath}`);
13078
+ console.log(`Canonical path (empty): ${status2.canonicalPath}`);
12972
13079
  return;
12973
13080
  }
12974
- const marker = status.installedVersion ?? "(no marker \u2014 pre-sync install)";
12975
- const state = status.upToDate ? "\u2713 up to date" : "\u26A0 stale \u2014 will sync on next command";
13081
+ const marker = status2.installedVersion ?? "(no marker \u2014 pre-sync install)";
13082
+ const state = status2.upToDate ? "\u2713 up to date" : "\u26A0 stale \u2014 will sync on next command";
12976
13083
  console.log(`Skill: ${state}`);
12977
13084
  console.log(` installed: ${marker}`);
12978
- console.log(` current: ${status.currentVersion}`);
12979
- console.log(` path: ${status.canonicalPath}`);
13085
+ console.log(` current: ${status2.currentVersion}`);
13086
+ console.log(` path: ${status2.canonicalPath}`);
12980
13087
  });
12981
13088
  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) => {
12982
13089
  const resolved = resolveConfig();
@@ -12991,12 +13098,12 @@ config.command("reset").description("Remove the project config for the current d
12991
13098
  return;
12992
13099
  }
12993
13100
  if (!isAgentMode()) {
12994
- const p10 = await import("@clack/prompts");
12995
- const confirmed = await p10.confirm({
13101
+ const p9 = await import("@clack/prompts");
13102
+ const confirmed = await p9.confirm({
12996
13103
  message: "Delete the global config? This removes your API key for all projects without a project config.",
12997
13104
  initialValue: false
12998
13105
  });
12999
- if (p10.isCancel(confirmed) || !confirmed) {
13106
+ if (p9.isCancel(confirmed) || !confirmed) {
13000
13107
  console.log("Cancelled.");
13001
13108
  return;
13002
13109
  }
@@ -13034,12 +13141,12 @@ config.command("reset").description("Remove the project config for the current d
13034
13141
  fallbackLabel = "no config";
13035
13142
  }
13036
13143
  if (!isAgentMode()) {
13037
- const p10 = await import("@clack/prompts");
13038
- const confirmed = await p10.confirm({
13144
+ const p9 = await import("@clack/prompts");
13145
+ const confirmed = await p9.confirm({
13039
13146
  message: `Delete project config for ${path13.basename(resolved.projectRoot)}? Will fall back to ${fallbackLabel}.`,
13040
13147
  initialValue: false
13041
13148
  });
13042
- if (p10.isCancel(confirmed) || !confirmed) {
13149
+ if (p9.isCancel(confirmed) || !confirmed) {
13043
13150
  console.log("Cancelled.");
13044
13151
  return;
13045
13152
  }
@@ -13068,12 +13175,12 @@ connection.command("delete <connection-key>").alias("rm").description("Delete a
13068
13175
  program.command("platforms").alias("p").description("List available platforms").option("-c, --category <category>", "Filter by category").option("--json", "Output as JSON").action(async (options) => {
13069
13176
  await platformsCommand(options);
13070
13177
  });
13071
- var actions = program.command("actions").alias("a").description("Search, explore, and execute platform actions (workflow: search \u2192 knowledge \u2192 execute)");
13072
- 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) => {
13073
- await actionsSearchCommand(platform, query, options);
13178
+ var actions = program.command("actions").alias("a").description("Find, read, and execute platform actions (workflow: find \u2192 execute)");
13179
+ 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)").action(async (pairs, options) => {
13180
+ await actionsFindCommand(pairs, options);
13074
13181
  });
13075
- 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) => {
13076
- await actionsKnowledgeCommand(platform, actionId, options);
13182
+ 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) => {
13183
+ await actionsLoadCommand(actionIds, options);
13077
13184
  });
13078
13185
  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) => {
13079
13186
  if (options.parallel) {