@withone/cli 1.57.1 → 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/README.md +32 -39
- package/dist/{chunk-QCXFSOTS.js → chunk-6EQDEYVD.js} +28 -101
- package/dist/{flow-runner-QQ675PJD.js → flow-runner-L3JG2WCY.js} +1 -1
- package/dist/index.js +720 -616
- package/package.json +1 -1
- package/skills/one/SKILL.md +37 -37
- package/skills/one/references/flows.md +7 -7
- package/skills/one/references/relay.md +7 -14
package/dist/index.js
CHANGED
|
@@ -5,11 +5,8 @@ import {
|
|
|
5
5
|
OneApi,
|
|
6
6
|
PERMISSION_METHODS,
|
|
7
7
|
TimeoutError,
|
|
8
|
-
buildActionKnowledgeWithGuidance,
|
|
9
|
-
buildCacheMeta,
|
|
10
8
|
clearAll,
|
|
11
9
|
clearEntry,
|
|
12
|
-
filterByPermissions,
|
|
13
10
|
flowRequiresBash,
|
|
14
11
|
formatAge,
|
|
15
12
|
generateFlowGuide,
|
|
@@ -28,11 +25,10 @@ import {
|
|
|
28
25
|
resolveActionDetails,
|
|
29
26
|
resolveFlowPath,
|
|
30
27
|
saveFlow,
|
|
31
|
-
searchCachePath,
|
|
32
28
|
validateActionInput,
|
|
33
29
|
walkSteps,
|
|
34
30
|
writeCache
|
|
35
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-6EQDEYVD.js";
|
|
36
32
|
import {
|
|
37
33
|
memSqlCommand
|
|
38
34
|
} from "./chunk-GKAIRI4Y.js";
|
|
@@ -165,11 +161,11 @@ import { fileURLToPath as fileURLToPath3 } from "url";
|
|
|
165
161
|
import fs from "fs";
|
|
166
162
|
import path from "path";
|
|
167
163
|
import { parse as parseToml, stringify as stringifyToml } from "smol-toml";
|
|
168
|
-
function expandPath(
|
|
169
|
-
if (
|
|
170
|
-
return path.join(homeDir(),
|
|
164
|
+
function expandPath(p9) {
|
|
165
|
+
if (p9.startsWith("~/")) {
|
|
166
|
+
return path.join(homeDir(), p9.slice(2));
|
|
171
167
|
}
|
|
172
|
-
return
|
|
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
|
-
(
|
|
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((
|
|
2626
|
-
const name =
|
|
2627
|
-
const slug =
|
|
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:
|
|
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
|
|
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((
|
|
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
|
|
3331
|
+
const find2 = (list, parent) => {
|
|
3337
3332
|
for (const n of list) {
|
|
3338
3333
|
if (n === target) return parent;
|
|
3339
|
-
const r =
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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(`
|
|
3927
|
+
spinner4.start(`Finding actions for ${requests.length} intent${requests.length === 1 ? "" : "s"}...`);
|
|
3522
3928
|
try {
|
|
3523
|
-
const
|
|
3524
|
-
|
|
3525
|
-
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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("
|
|
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
|
|
3638
|
-
const cachePath = knowledgeCachePath(actionId);
|
|
3949
|
+
async function actionsLoadCommand(actionIds, options) {
|
|
3639
3950
|
if (options.cacheStatus) {
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
path: cachePath
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
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,
|
|
3971
|
+
const { apiKey, permissions, connectionKeys, actionIds: allowed, knowledgeAgent } = getConfig();
|
|
3662
3972
|
const api = new OneApi(apiKey, getApiBase());
|
|
3663
|
-
|
|
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
|
|
3975
|
+
spinner4.start(`Loading ${actionIds.length === 1 ? "the action" : `${actionIds.length} actions`}...`);
|
|
3686
3976
|
try {
|
|
3687
|
-
const
|
|
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
|
-
|
|
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("
|
|
3982
|
+
spinner4.stop("Loaded");
|
|
3810
3983
|
console.log();
|
|
3811
|
-
console.log(
|
|
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("
|
|
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(
|
|
5053
|
-
if (
|
|
5054
|
-
return `${pc9.green("\u2713")} ${
|
|
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 (
|
|
5057
|
-
return `${pc9.dim("\u25CB")} ${
|
|
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("!")} ${
|
|
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
|
|
5076
|
-
console.log(` ${renderDryRef(
|
|
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
|
|
5284
|
-
console.log(` ${pc9.dim(ts)} ${
|
|
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(
|
|
5622
|
-
switch (
|
|
5772
|
+
function colorStatus(status2) {
|
|
5773
|
+
switch (status2) {
|
|
5623
5774
|
case "completed":
|
|
5624
|
-
return pc9.green(
|
|
5775
|
+
return pc9.green(status2);
|
|
5625
5776
|
case "running":
|
|
5626
|
-
return pc9.cyan(
|
|
5777
|
+
return pc9.cyan(status2);
|
|
5627
5778
|
case "paused":
|
|
5628
|
-
return pc9.yellow(
|
|
5779
|
+
return pc9.yellow(status2);
|
|
5629
5780
|
case "failed":
|
|
5630
|
-
return pc9.red(
|
|
5781
|
+
return pc9.red(status2);
|
|
5631
5782
|
default:
|
|
5632
|
-
return
|
|
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((
|
|
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
|
|
6836
|
+
for (const part2 of parts) {
|
|
6686
6837
|
if (typeof value !== "object" || value === null) return "";
|
|
6687
|
-
value = value[
|
|
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
|
|
6865
|
+
for (const part2 of parts) {
|
|
6715
6866
|
if (current === null || current === void 0 || typeof current !== "object") return void 0;
|
|
6716
|
-
current = current[
|
|
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
|
|
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((
|
|
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
|
|
6924
|
-
const t = byId.get(
|
|
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:
|
|
7078
|
+
writes.push({ merged: t, id: p9.id });
|
|
6928
7079
|
}
|
|
6929
7080
|
}
|
|
6930
7081
|
}
|
|
@@ -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
|
|
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;
|
|
@@ -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
|
|
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((
|
|
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
|
|
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((
|
|
8964
|
-
platform:
|
|
8965
|
-
model:
|
|
8966
|
-
description:
|
|
8967
|
-
hasEnrich: !!
|
|
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: !!
|
|
8973
|
-
hasIdentityKeys: !!
|
|
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
|
|
9138
|
+
for (const p9 of profiles) {
|
|
8988
9139
|
const extras = [];
|
|
8989
|
-
if (
|
|
8990
|
-
if (
|
|
8991
|
-
if (
|
|
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(`${
|
|
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
|
|
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
|
|
9253
|
-
const rate = `${
|
|
9254
|
-
const mark =
|
|
9255
|
-
const trailer =
|
|
9256
|
-
console.log(` ${mark} ${rate.padStart(5)} ${
|
|
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((
|
|
9277
|
-
if (
|
|
9427
|
+
perPath.forEach((p9, i) => {
|
|
9428
|
+
if (p9.found) {
|
|
9278
9429
|
perPathAgg[i].hits++;
|
|
9279
|
-
if (!perPathAgg[i].sample) perPathAgg[i].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((
|
|
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((
|
|
9451
|
+
await maybeAutoMigrateLegacy(platform, toSync.map((p9) => p9.model));
|
|
9301
9452
|
}
|
|
9302
|
-
const profileDrift = toSync.map((
|
|
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
|
|
9351
|
-
console.log(` ${pc11.bold(r.model)} \u2014 ${r.recordsSynced} records, ${r.pagesProcessed} pages, ${r.duration} [${
|
|
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
|
}
|
|
@@ -9475,8 +9626,8 @@ async function syncDeleteCommand(platformModel, options) {
|
|
|
9475
9626
|
return;
|
|
9476
9627
|
}
|
|
9477
9628
|
if (!options.yes && !isAgentMode()) {
|
|
9478
|
-
const confirmed = await
|
|
9479
|
-
if (
|
|
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;
|
|
@@ -9518,11 +9669,11 @@ async function maybeAutoMigrateLegacy(platform, models) {
|
|
|
9518
9669
|
await memMigrateCommand3({ platform, yes: true });
|
|
9519
9670
|
return;
|
|
9520
9671
|
}
|
|
9521
|
-
const shouldMigrate = await
|
|
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 (
|
|
9676
|
+
if (p6.isCancel(shouldMigrate) || !shouldMigrate) return;
|
|
9526
9677
|
const { memMigrateCommand: memMigrateCommand2 } = await import("./migrate-TACDLGPD.js");
|
|
9527
9678
|
await memMigrateCommand2({ platform, yes: true });
|
|
9528
9679
|
}
|
|
@@ -9586,14 +9737,14 @@ async function syncListCommand(platform) {
|
|
|
9586
9737
|
const state = await readSyncState();
|
|
9587
9738
|
const { getBackend: getBackend2 } = await import("./runtime-SX36HGBA.js");
|
|
9588
9739
|
const backend = await getBackend2();
|
|
9589
|
-
const syncs = await Promise.all(profiles.map(async (
|
|
9590
|
-
const modelState = state[
|
|
9591
|
-
const type = `${
|
|
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(
|
|
9744
|
+
const legacyDbSize = getDatabaseSize(p9.platform);
|
|
9594
9745
|
return {
|
|
9595
|
-
platform:
|
|
9596
|
-
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
|
|
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 ${
|
|
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((
|
|
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,
|
|
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((
|
|
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
|
|
9807
|
+
const confirmed = await p6.confirm({
|
|
9657
9808
|
message: `Remove ${target}? (${totalRecords} records, ${dbSize} on disk)`
|
|
9658
9809
|
});
|
|
9659
|
-
if (
|
|
9810
|
+
if (p6.isCancel(confirmed) || !confirmed) {
|
|
9660
9811
|
cancel("Cancelled.");
|
|
9661
9812
|
return;
|
|
9662
9813
|
}
|
|
@@ -9891,7 +10042,7 @@ function registerSyncSubcommands(sync) {
|
|
|
9891
10042
|
}
|
|
9892
10043
|
|
|
9893
10044
|
// src/commands/mem/init.ts
|
|
9894
|
-
import * as
|
|
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
|
|
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 (
|
|
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
|
|
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 (
|
|
10117
|
+
if (p7.isCancel(backend)) error("Cancelled.");
|
|
9967
10118
|
const perBackend = {};
|
|
9968
10119
|
if (backend === "embedded-postgres") {
|
|
9969
|
-
const dataDir = flags.dbPath ?? await
|
|
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 (
|
|
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
|
|
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 (
|
|
10133
|
+
if (p7.isCancel(connectionString)) error("Cancelled.");
|
|
9983
10134
|
perBackend.postgres = { connectionString };
|
|
9984
10135
|
}
|
|
9985
|
-
const provider = flags.embedding ?? await
|
|
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 (
|
|
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
|
|
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 (
|
|
10158
|
+
if (p7.isCancel(entered)) error("Cancelled.");
|
|
10008
10159
|
apiKey = entered || envKey;
|
|
10009
10160
|
}
|
|
10010
|
-
const embedAdd = flags.embedOnAdd ?? await
|
|
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 (
|
|
10165
|
+
if (p7.isCancel(embedAdd)) error("Cancelled.");
|
|
10015
10166
|
embedOnAdd = embedAdd;
|
|
10016
|
-
const embedSync = flags.embedOnSync ?? await
|
|
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 (
|
|
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
|
|
10392
|
+
for (const part2 of parts) {
|
|
10242
10393
|
if (cur == null || typeof cur !== "object") return void 0;
|
|
10243
|
-
cur = cur[
|
|
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
|
|
10252
|
-
if (cur[
|
|
10253
|
-
cur = cur[
|
|
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
|
|
10263
|
-
if (cur[
|
|
10264
|
-
cur = cur[
|
|
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
|
|
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((
|
|
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
|
|
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((
|
|
10929
|
-
name:
|
|
10930
|
-
description:
|
|
10931
|
-
version:
|
|
10932
|
-
schemaVersion:
|
|
10933
|
-
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
|
-
|
|
11075
|
-
|
|
11076
|
-
|
|
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
|
-
|
|
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
|
|
11184
|
-
one --agent actions
|
|
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
|
|
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 (
|
|
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
|
|
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:
|
|
11388
|
+
## Workflow: find \u2192 execute
|
|
11276
11389
|
|
|
11277
|
-
Always follow this sequence. Never
|
|
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
|
|
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
|
|
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.
|
|
11418
|
+
### 2. Find Actions
|
|
11306
11419
|
|
|
11307
11420
|
\`\`\`bash
|
|
11308
|
-
one --agent actions
|
|
11421
|
+
one --agent actions find <platform> "<intent>" [<platform> "<intent>" ...] --task "<the job, in general terms>"
|
|
11309
11422
|
\`\`\`
|
|
11310
11423
|
|
|
11311
|
-
|
|
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
|
-
|
|
11316
|
-
|
|
11317
|
-
|
|
11318
|
-
|
|
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
|
-
|
|
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
|
-
"
|
|
11328
|
-
|
|
11329
|
-
|
|
11330
|
-
|
|
11331
|
-
|
|
11332
|
-
|
|
11333
|
-
|
|
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
|
-
"
|
|
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
|
-
-
|
|
11342
|
-
-
|
|
11343
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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/\`
|
|
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
|
|
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
|
|
11551
|
-
| \`actions
|
|
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
|
-
##
|
|
11679
|
+
## Cache Status
|
|
11555
11680
|
|
|
11556
|
-
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
\`\`\`
|
|
@@ -11860,7 +11967,7 @@ Why the block:
|
|
|
11860
11967
|
enrichment locally \u2014 server-side fan-out on top of that creates 5xx, not value
|
|
11861
11968
|
|
|
11862
11969
|
How to build a profile:
|
|
11863
|
-
1. \`one actions
|
|
11970
|
+
1. \`one actions find <platform> "list <model>" -t knowledge\` surfaces passthrough actions (the pick and its alternatives).
|
|
11864
11971
|
\`sync init\`'s auto-infer also drops customs before offering choices.
|
|
11865
11972
|
2. Prefer GET passthrough endpoints (e.g. /gmail/v1/users/{userId}/threads)
|
|
11866
11973
|
over POST custom endpoints (e.g. /gmail/get-threads).
|
|
@@ -12292,7 +12399,7 @@ var TOPICS = [
|
|
|
12292
12399
|
{ topic: "actions", description: "Search, read docs, and execute platform actions" },
|
|
12293
12400
|
{ topic: "flows", description: "Build and execute multi-step workflows" },
|
|
12294
12401
|
{ topic: "relay", description: "Receive webhooks and forward to other platforms" },
|
|
12295
|
-
{ topic: "cache", description: "Local caching for
|
|
12402
|
+
{ topic: "cache", description: "Local caching for action documentation" },
|
|
12296
12403
|
{ topic: "memory", description: "Unified memory store: notes, decisions, synced rows, semantic search" },
|
|
12297
12404
|
{ topic: "sync", description: "Sync platform data into memory for instant offline queries" },
|
|
12298
12405
|
{ topic: "all", description: "Complete guide (all topics combined)" }
|
|
@@ -12384,7 +12491,7 @@ function pairKey(a, b) {
|
|
|
12384
12491
|
}
|
|
12385
12492
|
function getWorkflowExamples(connectedPlatforms) {
|
|
12386
12493
|
const results = [];
|
|
12387
|
-
const platforms = connectedPlatforms.map((
|
|
12494
|
+
const platforms = connectedPlatforms.map((p9) => p9.toLowerCase());
|
|
12388
12495
|
for (let i = 0; i < platforms.length; i++) {
|
|
12389
12496
|
for (let j = i + 1; j < platforms.length; j++) {
|
|
12390
12497
|
const key = pairKey(platforms[i], platforms[j]);
|
|
@@ -12501,17 +12608,17 @@ common mistakes to avoid. Never guess \u2014 read the skill, then act.
|
|
|
12501
12608
|
|
|
12502
12609
|
### Quick reference:
|
|
12503
12610
|
- \`one --agent list\` \u2014 See connected platforms and connection keys
|
|
12504
|
-
- \`one --agent actions
|
|
12505
|
-
- \`one --agent actions
|
|
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\`
|
|
12506
12613
|
- \`one --agent actions execute <platform> <actionId> <connectionKey>\` \u2014 Execute action
|
|
12507
12614
|
- \`one --agent flow create\` \u2014 Build multi-step workflows
|
|
12508
12615
|
- \`one --agent relay create\` \u2014 Set up webhook relay (receive events, forward to other platforms)
|
|
12509
12616
|
- \`one --agent guide\` \u2014 Full documentation
|
|
12510
12617
|
- \`one add <platform>\` \u2014 Connect a new platform (interactive, no --agent)
|
|
12511
12618
|
|
|
12512
|
-
### Workflow:
|
|
12513
|
-
Always read the
|
|
12514
|
-
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.
|
|
12515
12622
|
|
|
12516
12623
|
### Webhook Relay
|
|
12517
12624
|
Use \`one relay\` to receive webhooks from platforms (Stripe, GitHub, etc.)
|
|
@@ -12525,8 +12632,7 @@ Handlebars templates. No middleware needed.
|
|
|
12525
12632
|
Every command supports \`--agent\` which gives you clean, structured JSON
|
|
12526
12633
|
output instead of human-formatted text. Always use it:
|
|
12527
12634
|
one --agent list
|
|
12528
|
-
one --agent actions
|
|
12529
|
-
one --agent actions knowledge gmail <actionId>
|
|
12635
|
+
one --agent actions find gmail "send an email" --task "email a report to a contact"
|
|
12530
12636
|
one --agent actions execute gmail <actionId> <connectionKey> -d '{...}'
|
|
12531
12637
|
one --agent platforms
|
|
12532
12638
|
one --agent guide
|
|
@@ -12534,8 +12640,8 @@ output instead of human-formatted text. Always use it:
|
|
|
12534
12640
|
The \`--agent\` flag goes right after \`one\`, before the subcommand.
|
|
12535
12641
|
|
|
12536
12642
|
### Discovery Workflow (follow this every time):
|
|
12537
|
-
1. \`one --agent actions
|
|
12538
|
-
2. \`one --agent actions
|
|
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
|
|
12539
12645
|
3. \`one --agent actions execute <platform> <actionId> <connectionKey>\` \u2014 Execute it
|
|
12540
12646
|
|
|
12541
12647
|
### Multi-Step Workflows:
|
|
@@ -12616,8 +12722,8 @@ You have ${connections.length} platform(s) connected:
|
|
|
12616
12722
|
const tableHeader = " Platform Status Connection Key";
|
|
12617
12723
|
const tableRows = connections.map((c) => {
|
|
12618
12724
|
const platform = c.platform.padEnd(22);
|
|
12619
|
-
const
|
|
12620
|
-
return ` ${platform}${
|
|
12725
|
+
const status2 = c.state.padEnd(14);
|
|
12726
|
+
return ` ${platform}${status2}${c.key}`;
|
|
12621
12727
|
});
|
|
12622
12728
|
return header + "\n" + tableHeader + "\n" + tableRows.join("\n");
|
|
12623
12729
|
}
|
|
@@ -12628,13 +12734,13 @@ function buildDemoActions(connections) {
|
|
|
12628
12734
|
const connectedPlatforms = connections.map((c) => c.platform.toLowerCase());
|
|
12629
12735
|
const popularPlatforms = ["gmail", "google-calendar", "slack", "shopify", "hubspot", "github"];
|
|
12630
12736
|
const platformsToShow = [
|
|
12631
|
-
...connectedPlatforms.filter((
|
|
12632
|
-
...popularPlatforms.filter((
|
|
12737
|
+
...connectedPlatforms.filter((p9) => PLATFORM_DEMO_ACTIONS[p9]),
|
|
12738
|
+
...popularPlatforms.filter((p9) => !connectedPlatforms.includes(p9))
|
|
12633
12739
|
];
|
|
12634
12740
|
const seen = /* @__PURE__ */ new Set();
|
|
12635
|
-
const unique = platformsToShow.filter((
|
|
12636
|
-
if (seen.has(
|
|
12637
|
-
seen.add(
|
|
12741
|
+
const unique = platformsToShow.filter((p9) => {
|
|
12742
|
+
if (seen.has(p9)) return false;
|
|
12743
|
+
seen.add(p9);
|
|
12638
12744
|
return true;
|
|
12639
12745
|
}).slice(0, 6);
|
|
12640
12746
|
for (const platform of unique) {
|
|
@@ -12643,7 +12749,7 @@ function buildDemoActions(connections) {
|
|
|
12643
12749
|
const displayName = platform.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
12644
12750
|
lines.push("");
|
|
12645
12751
|
lines.push(`### ${displayName}`);
|
|
12646
|
-
lines.push(`- ${demo.description}: \`one actions
|
|
12752
|
+
lines.push(`- ${demo.description}: \`one actions find ${platform} "${demo.query}"\``);
|
|
12647
12753
|
lines.push(`- Then get knowledge and execute to show the user the results`);
|
|
12648
12754
|
}
|
|
12649
12755
|
lines.push("");
|
|
@@ -12667,7 +12773,7 @@ function buildWorkflowIdeas(connections) {
|
|
|
12667
12773
|
|
|
12668
12774
|
// src/commands/logout.ts
|
|
12669
12775
|
import fs13 from "fs";
|
|
12670
|
-
import * as
|
|
12776
|
+
import * as p8 from "@clack/prompts";
|
|
12671
12777
|
function formatWhoami(config2, apiKey, pc16) {
|
|
12672
12778
|
const whoami = config2.whoami;
|
|
12673
12779
|
const env = getEnvFromApiKey(apiKey);
|
|
@@ -12729,8 +12835,8 @@ async function logoutCommand() {
|
|
|
12729
12835
|
infoLines.push(`${pc16.magenta("Global config:")}`);
|
|
12730
12836
|
infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey, pc16));
|
|
12731
12837
|
}
|
|
12732
|
-
|
|
12733
|
-
const choice = await
|
|
12838
|
+
p8.note(infoLines.join("\n"));
|
|
12839
|
+
const choice = await p8.select({
|
|
12734
12840
|
message: "What would you like to log out of?",
|
|
12735
12841
|
options: [
|
|
12736
12842
|
{ value: "project", label: "This directory", hint: "local config only" },
|
|
@@ -12738,8 +12844,8 @@ async function logoutCommand() {
|
|
|
12738
12844
|
{ value: "both", label: "Both", hint: "remove all credentials" }
|
|
12739
12845
|
]
|
|
12740
12846
|
});
|
|
12741
|
-
if (
|
|
12742
|
-
|
|
12847
|
+
if (p8.isCancel(choice)) {
|
|
12848
|
+
p8.cancel("Logout cancelled.");
|
|
12743
12849
|
return;
|
|
12744
12850
|
}
|
|
12745
12851
|
targetScope = choice;
|
|
@@ -12747,18 +12853,18 @@ async function logoutCommand() {
|
|
|
12747
12853
|
const infoLines = ["You are logged in.", ""];
|
|
12748
12854
|
infoLines.push(`${pc16.dim("Stored in")} ${pc16.cyan("local config")}`);
|
|
12749
12855
|
infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey, pc16));
|
|
12750
|
-
|
|
12856
|
+
p8.note(infoLines.join("\n"));
|
|
12751
12857
|
targetScope = "project";
|
|
12752
12858
|
} else if (hasGlobal) {
|
|
12753
12859
|
const infoLines = ["You are logged in.", ""];
|
|
12754
12860
|
infoLines.push(`${pc16.dim("Stored in")} ${pc16.magenta("global config")}`);
|
|
12755
12861
|
infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey, pc16));
|
|
12756
|
-
|
|
12862
|
+
p8.note(infoLines.join("\n"));
|
|
12757
12863
|
targetScope = "global";
|
|
12758
12864
|
} else {
|
|
12759
|
-
|
|
12760
|
-
|
|
12761
|
-
|
|
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.");
|
|
12762
12868
|
return;
|
|
12763
12869
|
}
|
|
12764
12870
|
const scopeLabels = {
|
|
@@ -12766,11 +12872,11 @@ async function logoutCommand() {
|
|
|
12766
12872
|
global: "global",
|
|
12767
12873
|
both: "all"
|
|
12768
12874
|
};
|
|
12769
|
-
const confirm7 = await
|
|
12875
|
+
const confirm7 = await p8.confirm({
|
|
12770
12876
|
message: `Remove ${scopeLabels[targetScope]} credentials?`
|
|
12771
12877
|
});
|
|
12772
|
-
if (
|
|
12773
|
-
|
|
12878
|
+
if (p8.isCancel(confirm7) || !confirm7) {
|
|
12879
|
+
p8.cancel("Logout cancelled.");
|
|
12774
12880
|
return;
|
|
12775
12881
|
}
|
|
12776
12882
|
if (targetScope === "project" || targetScope === "both") {
|
|
@@ -12781,9 +12887,9 @@ async function logoutCommand() {
|
|
|
12781
12887
|
const globalPath = getGlobalConfigPath();
|
|
12782
12888
|
if (fs13.existsSync(globalPath)) fs13.unlinkSync(globalPath);
|
|
12783
12889
|
}
|
|
12784
|
-
|
|
12785
|
-
|
|
12786
|
-
|
|
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.");
|
|
12787
12893
|
}
|
|
12788
12894
|
|
|
12789
12895
|
// src/cli.ts
|
|
@@ -12804,9 +12910,9 @@ program.name("one").option("--agent", "Machine-readable JSON output (no colors,
|
|
|
12804
12910
|
|
|
12805
12911
|
Workflow (use these in order):
|
|
12806
12912
|
1. one list List connected platforms, keys, and your access on each
|
|
12807
|
-
2. one actions
|
|
12808
|
-
3. one actions
|
|
12809
|
-
|
|
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
|
|
12810
12916
|
|
|
12811
12917
|
Guide:
|
|
12812
12918
|
one guide [topic] Full CLI guide (topics: overview, actions, workflows, memory, sync, all)
|
|
@@ -12853,11 +12959,9 @@ program.name("one").option("--agent", "Machine-readable JSON output (no colors,
|
|
|
12853
12959
|
$ one list
|
|
12854
12960
|
# Find: gmail operational live::gmail::default::abc123
|
|
12855
12961
|
|
|
12856
|
-
$ one actions
|
|
12857
|
-
#
|
|
12858
|
-
|
|
12859
|
-
$ one actions knowledge gmail conn_mod_def::xxx::yyy
|
|
12860
|
-
# 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
|
|
12861
12965
|
|
|
12862
12966
|
$ one actions execute gmail conn_mod_def::xxx::yyy live::gmail::default::abc123 \\
|
|
12863
12967
|
-d '{"to":"j@example.com","subject":"Hello","body":"Hi!","connectionKey":"live::gmail::default::abc123"}'
|
|
@@ -12964,22 +13068,22 @@ configSkills.command("sync").description("Re-copy packaged skill files over the
|
|
|
12964
13068
|
console.log(`\u2717 Sync failed${result.error ? ": " + result.error : ""}`);
|
|
12965
13069
|
});
|
|
12966
13070
|
configSkills.command("status").description("Show installed skill version and whether it matches the current CLI").action(async () => {
|
|
12967
|
-
const
|
|
13071
|
+
const status2 = getSkillStatus();
|
|
12968
13072
|
if (isAgentMode()) {
|
|
12969
|
-
json({ command: "config skills status", ...
|
|
13073
|
+
json({ command: "config skills status", ...status2 });
|
|
12970
13074
|
return;
|
|
12971
13075
|
}
|
|
12972
|
-
if (!
|
|
13076
|
+
if (!status2.installed) {
|
|
12973
13077
|
console.log("Skill is not installed. Run 'one init' to install it.");
|
|
12974
|
-
console.log(`Canonical path (empty): ${
|
|
13078
|
+
console.log(`Canonical path (empty): ${status2.canonicalPath}`);
|
|
12975
13079
|
return;
|
|
12976
13080
|
}
|
|
12977
|
-
const marker =
|
|
12978
|
-
const state =
|
|
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";
|
|
12979
13083
|
console.log(`Skill: ${state}`);
|
|
12980
13084
|
console.log(` installed: ${marker}`);
|
|
12981
|
-
console.log(` current: ${
|
|
12982
|
-
console.log(` path: ${
|
|
13085
|
+
console.log(` current: ${status2.currentVersion}`);
|
|
13086
|
+
console.log(` path: ${status2.canonicalPath}`);
|
|
12983
13087
|
});
|
|
12984
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) => {
|
|
12985
13089
|
const resolved = resolveConfig();
|
|
@@ -12994,12 +13098,12 @@ config.command("reset").description("Remove the project config for the current d
|
|
|
12994
13098
|
return;
|
|
12995
13099
|
}
|
|
12996
13100
|
if (!isAgentMode()) {
|
|
12997
|
-
const
|
|
12998
|
-
const confirmed = await
|
|
13101
|
+
const p9 = await import("@clack/prompts");
|
|
13102
|
+
const confirmed = await p9.confirm({
|
|
12999
13103
|
message: "Delete the global config? This removes your API key for all projects without a project config.",
|
|
13000
13104
|
initialValue: false
|
|
13001
13105
|
});
|
|
13002
|
-
if (
|
|
13106
|
+
if (p9.isCancel(confirmed) || !confirmed) {
|
|
13003
13107
|
console.log("Cancelled.");
|
|
13004
13108
|
return;
|
|
13005
13109
|
}
|
|
@@ -13037,12 +13141,12 @@ config.command("reset").description("Remove the project config for the current d
|
|
|
13037
13141
|
fallbackLabel = "no config";
|
|
13038
13142
|
}
|
|
13039
13143
|
if (!isAgentMode()) {
|
|
13040
|
-
const
|
|
13041
|
-
const confirmed = await
|
|
13144
|
+
const p9 = await import("@clack/prompts");
|
|
13145
|
+
const confirmed = await p9.confirm({
|
|
13042
13146
|
message: `Delete project config for ${path13.basename(resolved.projectRoot)}? Will fall back to ${fallbackLabel}.`,
|
|
13043
13147
|
initialValue: false
|
|
13044
13148
|
});
|
|
13045
|
-
if (
|
|
13149
|
+
if (p9.isCancel(confirmed) || !confirmed) {
|
|
13046
13150
|
console.log("Cancelled.");
|
|
13047
13151
|
return;
|
|
13048
13152
|
}
|
|
@@ -13071,12 +13175,12 @@ connection.command("delete <connection-key>").alias("rm").description("Delete a
|
|
|
13071
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) => {
|
|
13072
13176
|
await platformsCommand(options);
|
|
13073
13177
|
});
|
|
13074
|
-
var actions = program.command("actions").alias("a").description("
|
|
13075
|
-
actions.command("
|
|
13076
|
-
await
|
|
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);
|
|
13077
13181
|
});
|
|
13078
|
-
actions.command("
|
|
13079
|
-
await
|
|
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);
|
|
13080
13184
|
});
|
|
13081
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) => {
|
|
13082
13186
|
if (options.parallel) {
|