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