@withone/cli 2.3.1 → 2.4.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 +22 -0
- package/dist/{chunk-IPAVHPRZ.js → chunk-7FPQOAQ4.js} +1 -1
- package/dist/{chunk-FUCAK5RA.js → chunk-NOFJ4NYD.js} +19 -1
- package/dist/{chunk-SN6WYDOE.js → chunk-XKUTG7JD.js} +1 -1
- package/dist/index.js +875 -317
- package/dist/{migrate-GN3I6EZM.js → migrate-3LSEIPRF.js} +2 -2
- package/dist/{schema-G7XYVIZG.js → schema-FICQRMZ7.js} +1 -1
- package/dist/{sql-6I4LWPZF.js → sql-AKQSXRV2.js} +2 -2
- package/package.json +1 -1
- package/skills/one/SKILL.md +10 -0
package/dist/index.js
CHANGED
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
} from "./chunk-6FA7KUNQ.js";
|
|
32
32
|
import {
|
|
33
33
|
memSqlCommand
|
|
34
|
-
} from "./chunk-
|
|
34
|
+
} from "./chunk-7FPQOAQ4.js";
|
|
35
35
|
import {
|
|
36
36
|
collectIdentityKeys,
|
|
37
37
|
countRecords,
|
|
@@ -62,7 +62,7 @@ import {
|
|
|
62
62
|
writeDraftProfile,
|
|
63
63
|
writePageToMemory,
|
|
64
64
|
writeProfile
|
|
65
|
-
} from "./chunk-
|
|
65
|
+
} from "./chunk-XKUTG7JD.js";
|
|
66
66
|
import {
|
|
67
67
|
getByDotPath
|
|
68
68
|
} from "./chunk-44CV5IMX.js";
|
|
@@ -86,7 +86,7 @@ import {
|
|
|
86
86
|
semanticSearchUpgradeLine,
|
|
87
87
|
setAgentMode,
|
|
88
88
|
silenceWarningsInAgentMode
|
|
89
|
-
} from "./chunk-
|
|
89
|
+
} from "./chunk-NOFJ4NYD.js";
|
|
90
90
|
import {
|
|
91
91
|
SCHEMA_VERSION,
|
|
92
92
|
addRecord,
|
|
@@ -147,7 +147,7 @@ import {
|
|
|
147
147
|
|
|
148
148
|
// src/cli.ts
|
|
149
149
|
import { createRequire as createRequire3 } from "module";
|
|
150
|
-
import
|
|
150
|
+
import path15 from "path";
|
|
151
151
|
import { Command } from "commander";
|
|
152
152
|
|
|
153
153
|
// src/commands/init.ts
|
|
@@ -962,24 +962,24 @@ async function configCommand() {
|
|
|
962
962
|
p.outro("No changes made.");
|
|
963
963
|
return;
|
|
964
964
|
}
|
|
965
|
-
const
|
|
966
|
-
|
|
965
|
+
const spinner = createSpinner();
|
|
966
|
+
spinner.start("Validating API key...");
|
|
967
967
|
let isValid = false;
|
|
968
968
|
try {
|
|
969
969
|
const api = new OneApi(apiKey, `${normalized}/v1`);
|
|
970
970
|
isValid = Boolean(await api.validateApiKey());
|
|
971
971
|
} catch (err) {
|
|
972
|
-
|
|
972
|
+
spinner.stop("Connection failed");
|
|
973
973
|
const msg = err instanceof Error ? err.message : String(err);
|
|
974
974
|
p.log.error(`Could not reach ${pc2.cyan(normalized)}: ${msg}`);
|
|
975
975
|
return;
|
|
976
976
|
}
|
|
977
977
|
if (!isValid) {
|
|
978
|
-
|
|
978
|
+
spinner.stop("Invalid API key");
|
|
979
979
|
p.log.error(`Invalid API key for ${pc2.cyan(normalized)}.`);
|
|
980
980
|
return;
|
|
981
981
|
}
|
|
982
|
-
|
|
982
|
+
spinner.stop("API key validated");
|
|
983
983
|
updateApiBase(normalized);
|
|
984
984
|
newApiKey = apiKey;
|
|
985
985
|
} else if (isCustomBase) {
|
|
@@ -998,24 +998,24 @@ async function configCommand() {
|
|
|
998
998
|
p.outro("No changes made.");
|
|
999
999
|
return;
|
|
1000
1000
|
}
|
|
1001
|
-
const
|
|
1002
|
-
|
|
1001
|
+
const spinner = createSpinner();
|
|
1002
|
+
spinner.start("Validating API key...");
|
|
1003
1003
|
let isValid = false;
|
|
1004
1004
|
try {
|
|
1005
1005
|
const api = new OneApi(apiKey, "https://api.withone.ai/v1");
|
|
1006
1006
|
isValid = Boolean(await api.validateApiKey());
|
|
1007
1007
|
} catch (err) {
|
|
1008
|
-
|
|
1008
|
+
spinner.stop("Connection failed");
|
|
1009
1009
|
const msg = err instanceof Error ? err.message : String(err);
|
|
1010
1010
|
p.log.error(`Could not reach ${pc2.cyan("https://api.withone.ai")}: ${msg}`);
|
|
1011
1011
|
return;
|
|
1012
1012
|
}
|
|
1013
1013
|
if (!isValid) {
|
|
1014
|
-
|
|
1014
|
+
spinner.stop("Invalid API key");
|
|
1015
1015
|
p.log.error(`Invalid API key. Get a valid key at ${getApiKeyUrl()}`);
|
|
1016
1016
|
return;
|
|
1017
1017
|
}
|
|
1018
|
-
|
|
1018
|
+
spinner.stop("API key validated");
|
|
1019
1019
|
updateApiBase(null);
|
|
1020
1020
|
newApiKey = apiKey;
|
|
1021
1021
|
}
|
|
@@ -1053,16 +1053,16 @@ async function configCommand() {
|
|
|
1053
1053
|
p.outro("Configuration updated.");
|
|
1054
1054
|
}
|
|
1055
1055
|
async function selectConnections(apiKey) {
|
|
1056
|
-
const
|
|
1057
|
-
|
|
1056
|
+
const spinner = createSpinner();
|
|
1057
|
+
spinner.start("Fetching connections...");
|
|
1058
1058
|
let connections;
|
|
1059
1059
|
try {
|
|
1060
1060
|
const api = new OneApi(apiKey, getApiBase());
|
|
1061
1061
|
const rawConnections = await api.listConnections();
|
|
1062
1062
|
connections = rawConnections.map((c) => ({ platform: c.platform, key: c.key }));
|
|
1063
|
-
|
|
1063
|
+
spinner.stop(`Found ${connections.length} connection(s)`);
|
|
1064
1064
|
} catch {
|
|
1065
|
-
|
|
1065
|
+
spinner.stop("Could not fetch connections");
|
|
1066
1066
|
const manual = await p.text({
|
|
1067
1067
|
message: "Enter connection keys manually (comma-separated):",
|
|
1068
1068
|
placeholder: "conn_key_1, conn_key_2",
|
|
@@ -1635,7 +1635,7 @@ ${describeInstallContext(context)}`
|
|
|
1635
1635
|
await open2(authUrl);
|
|
1636
1636
|
} catch {
|
|
1637
1637
|
}
|
|
1638
|
-
spin.start("Waiting for
|
|
1638
|
+
spin.start("Waiting for browser sign-in (5 min timeout)");
|
|
1639
1639
|
const timeout = new Promise((_, reject) => {
|
|
1640
1640
|
const timer = setTimeout(() => {
|
|
1641
1641
|
reject(new Error("timeout"));
|
|
@@ -1686,25 +1686,25 @@ async function loginCommand() {
|
|
|
1686
1686
|
let targetScope = "global";
|
|
1687
1687
|
const existingKey = getApiKey();
|
|
1688
1688
|
if (existingKey) {
|
|
1689
|
-
const
|
|
1689
|
+
const pc18 = (await import("picocolors")).default;
|
|
1690
1690
|
const resolved = resolveConfig();
|
|
1691
1691
|
const whoami2 = resolved.config?.whoami;
|
|
1692
1692
|
const env2 = getEnvFromApiKey(existingKey);
|
|
1693
|
-
const envLabel2 = env2 === "test" ?
|
|
1694
|
-
const currentScope = resolved.scope === "project" ?
|
|
1693
|
+
const envLabel2 = env2 === "test" ? pc18.yellow("test") : pc18.green("live");
|
|
1694
|
+
const currentScope = resolved.scope === "project" ? pc18.cyan("local config") : pc18.magenta("global config");
|
|
1695
1695
|
const lines = ["You are already logged in.", ""];
|
|
1696
1696
|
if (whoami2) {
|
|
1697
1697
|
const contextParts2 = [];
|
|
1698
1698
|
if (whoami2.organization) contextParts2.push(whoami2.organization.name);
|
|
1699
1699
|
if (whoami2.project) contextParts2.push(whoami2.project.name);
|
|
1700
1700
|
const scopeDisplay2 = contextParts2.length > 0 ? contextParts2.join(" / ") : "Personal";
|
|
1701
|
-
lines.push(`${
|
|
1702
|
-
lines.push(`${whoami2.user.name} ${
|
|
1703
|
-
if (whoami2.organization) lines.push(`${
|
|
1704
|
-
if (whoami2.project) lines.push(`${
|
|
1701
|
+
lines.push(`${pc18.bold(scopeDisplay2)} ${pc18.dim("\xB7")} ${envLabel2}`);
|
|
1702
|
+
lines.push(`${whoami2.user.name} ${pc18.dim(`(${whoami2.user.email})`)}`);
|
|
1703
|
+
if (whoami2.organization) lines.push(`${pc18.dim("Org:")} ${whoami2.organization.name}`);
|
|
1704
|
+
if (whoami2.project) lines.push(`${pc18.dim("Project:")} ${whoami2.project.name}`);
|
|
1705
1705
|
}
|
|
1706
1706
|
lines.push("");
|
|
1707
|
-
lines.push(`${
|
|
1707
|
+
lines.push(`${pc18.dim("Stored in")} ${currentScope}`);
|
|
1708
1708
|
p2.note(lines.join("\n"));
|
|
1709
1709
|
const scopeChoice = await p2.select({
|
|
1710
1710
|
message: "Where would you like to log in?",
|
|
@@ -1723,42 +1723,42 @@ async function loginCommand() {
|
|
|
1723
1723
|
if (!result) return;
|
|
1724
1724
|
const { apiKey, whoami, keyName, grant, knowledgeOnly } = result;
|
|
1725
1725
|
saveCredentials(apiKey, targetScope, { keyName, whoami, knowledgeOnly });
|
|
1726
|
-
const
|
|
1726
|
+
const pc17 = (await import("picocolors")).default;
|
|
1727
1727
|
const env = getEnvFromApiKey(apiKey);
|
|
1728
1728
|
const contextParts = [];
|
|
1729
1729
|
if (whoami.organization) contextParts.push(whoami.organization.name);
|
|
1730
1730
|
if (whoami.project) contextParts.push(whoami.project.name);
|
|
1731
1731
|
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
1732
|
-
const envLabel = env === "test" ?
|
|
1733
|
-
const configLabel = targetScope === "project" ?
|
|
1732
|
+
const envLabel = env === "test" ? pc17.yellow("test") : pc17.green("live");
|
|
1733
|
+
const configLabel = targetScope === "project" ? pc17.cyan("local config") : pc17.magenta("global config");
|
|
1734
1734
|
const infoLines = [
|
|
1735
|
-
`${
|
|
1736
|
-
`${whoami.user.name} ${
|
|
1735
|
+
`${pc17.bold(scopeDisplay)} ${pc17.dim("\xB7")} ${envLabel}`,
|
|
1736
|
+
`${whoami.user.name} ${pc17.dim(`(${whoami.user.email})`)}`
|
|
1737
1737
|
];
|
|
1738
|
-
if (keyName) infoLines.push(`${
|
|
1739
|
-
infoLines.push(...grantNoteLines(grant,
|
|
1740
|
-
if (whoami.organization) infoLines.push(`${
|
|
1741
|
-
if (whoami.project) infoLines.push(`${
|
|
1738
|
+
if (keyName) infoLines.push(`${pc17.dim("Key:")} ${keyName}`);
|
|
1739
|
+
infoLines.push(...grantNoteLines(grant, pc17.dim("Access:")));
|
|
1740
|
+
if (whoami.organization) infoLines.push(`${pc17.dim("Org:")} ${whoami.organization.name}`);
|
|
1741
|
+
if (whoami.project) infoLines.push(`${pc17.dim("Project:")} ${whoami.project.name}`);
|
|
1742
1742
|
infoLines.push("");
|
|
1743
|
-
infoLines.push(`${
|
|
1743
|
+
infoLines.push(`${pc17.dim("Stored in")} ${configLabel}`);
|
|
1744
1744
|
p2.note(infoLines.join("\n"), "Logged in");
|
|
1745
1745
|
console.log();
|
|
1746
|
-
console.log(` ${
|
|
1747
|
-
console.log(` ${
|
|
1746
|
+
console.log(` ${pc17.dim("Next steps:")}`);
|
|
1747
|
+
console.log(` ${pc17.cyan("one add <platform>")} ${pc17.dim("\u2014")} Connect a platform (e.g. gmail, slack, stripe)`);
|
|
1748
1748
|
console.log();
|
|
1749
|
-
console.log(
|
|
1749
|
+
console.log(pc17.bold(" Copy-paste this to your AI agent:"));
|
|
1750
1750
|
console.log();
|
|
1751
|
-
console.log(
|
|
1752
|
-
console.log(
|
|
1753
|
-
console.log(
|
|
1754
|
-
console.log(
|
|
1755
|
-
console.log(
|
|
1756
|
-
console.log(
|
|
1757
|
-
console.log(
|
|
1758
|
-
console.log(
|
|
1759
|
-
console.log(
|
|
1760
|
-
console.log(
|
|
1761
|
-
console.log(
|
|
1751
|
+
console.log(pc17.cyan(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1752
|
+
console.log(pc17.cyan(" \u2502"));
|
|
1753
|
+
console.log(pc17.cyan(" \u2502 The One CLI (`one`) is now installed on this machine. It"));
|
|
1754
|
+
console.log(pc17.cyan(" \u2502 lets you interact with 750+ third-party platforms (Gmail,"));
|
|
1755
|
+
console.log(pc17.cyan(" \u2502 Slack, Shopify, HubSpot, Stripe, GitHub, etc.) through"));
|
|
1756
|
+
console.log(pc17.cyan(" \u2502 their APIs. Whenever you need to interact with any"));
|
|
1757
|
+
console.log(pc17.cyan(" \u2502 third-party platform or external service, use the `one`"));
|
|
1758
|
+
console.log(pc17.cyan(" \u2502 skill. Please save this to your project instructions or"));
|
|
1759
|
+
console.log(pc17.cyan(" \u2502 memory so you remember it in future conversations."));
|
|
1760
|
+
console.log(pc17.cyan(" \u2502"));
|
|
1761
|
+
console.log(pc17.cyan(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
|
|
1762
1762
|
console.log();
|
|
1763
1763
|
p2.outro("Happy building!");
|
|
1764
1764
|
}
|
|
@@ -2109,16 +2109,16 @@ ${pc4.cyan(getApiKeyUrl())}`, `API Key ${scopeLabel(scope)}`);
|
|
|
2109
2109
|
process.exit(0);
|
|
2110
2110
|
}
|
|
2111
2111
|
newKey = inputKey;
|
|
2112
|
-
const
|
|
2113
|
-
|
|
2112
|
+
const spinner = createSpinner();
|
|
2113
|
+
spinner.start("Validating API key...");
|
|
2114
2114
|
const api = new OneApi(newKey, getApiBase());
|
|
2115
2115
|
const validated = await api.validateApiKey();
|
|
2116
2116
|
if (!validated) {
|
|
2117
|
-
|
|
2117
|
+
spinner.stop("Invalid API key");
|
|
2118
2118
|
p3.cancel(`Invalid API key. Get a valid key at ${getApiKeyUrl()}`);
|
|
2119
2119
|
process.exit(1);
|
|
2120
2120
|
}
|
|
2121
|
-
|
|
2121
|
+
spinner.stop("API key validated");
|
|
2122
2122
|
whoamiResult = validated;
|
|
2123
2123
|
}
|
|
2124
2124
|
const env = getEnvFromApiKey(newKey);
|
|
@@ -2335,10 +2335,10 @@ async function promptSkillInstall() {
|
|
|
2335
2335
|
p3.log.info("No agents selected.");
|
|
2336
2336
|
return false;
|
|
2337
2337
|
}
|
|
2338
|
-
const
|
|
2339
|
-
|
|
2338
|
+
const spinner = createSpinner();
|
|
2339
|
+
spinner.start("Installing skill...");
|
|
2340
2340
|
const { installed, failed } = installSkillForAgents(selectedIds);
|
|
2341
|
-
|
|
2341
|
+
spinner.stop(installed.length > 0 ? "Skill installed" : "Installation failed");
|
|
2342
2342
|
for (const name of installed) {
|
|
2343
2343
|
p3.log.success(`${name}: ${pc4.green("\u2713")} skill installed`);
|
|
2344
2344
|
}
|
|
@@ -2434,16 +2434,16 @@ ${pc4.cyan(getApiKeyUrl())}`, `API Key ${scopeLabel(scope)}`);
|
|
|
2434
2434
|
process.exit(0);
|
|
2435
2435
|
}
|
|
2436
2436
|
apiKey = inputKey;
|
|
2437
|
-
const
|
|
2438
|
-
|
|
2437
|
+
const spinner = createSpinner();
|
|
2438
|
+
spinner.start("Validating API key...");
|
|
2439
2439
|
const api = new OneApi(apiKey, getApiBase());
|
|
2440
2440
|
const whoami = await api.validateApiKey();
|
|
2441
2441
|
if (!whoami) {
|
|
2442
|
-
|
|
2442
|
+
spinner.stop("Invalid API key");
|
|
2443
2443
|
p3.cancel(`Invalid API key. Get a valid key at ${getApiKeyUrl()}`);
|
|
2444
2444
|
process.exit(1);
|
|
2445
2445
|
}
|
|
2446
|
-
|
|
2446
|
+
spinner.stop("API key validated");
|
|
2447
2447
|
const env2 = getEnvFromApiKey(apiKey);
|
|
2448
2448
|
const contextParts = [];
|
|
2449
2449
|
if (whoami.organization) contextParts.push(whoami.organization.name);
|
|
@@ -2558,16 +2558,16 @@ async function promptConnectIntegrations(apiKey, connParams) {
|
|
|
2558
2558
|
p3.log.warn("Could not open browser automatically.");
|
|
2559
2559
|
p3.note(url, "Open manually");
|
|
2560
2560
|
}
|
|
2561
|
-
const
|
|
2562
|
-
|
|
2561
|
+
const spinner = createSpinner();
|
|
2562
|
+
spinner.start("Waiting for connection... (complete auth in browser)");
|
|
2563
2563
|
try {
|
|
2564
2564
|
await api.waitForConnection(platform, 5 * 60 * 1e3, 5e3);
|
|
2565
|
-
|
|
2565
|
+
spinner.stop(`${label} connected!`);
|
|
2566
2566
|
p3.log.success(`${pc4.green("\u2713")} ${label} is now available to your AI agents`);
|
|
2567
2567
|
connected.push(platform);
|
|
2568
2568
|
first = false;
|
|
2569
2569
|
} catch (error2) {
|
|
2570
|
-
|
|
2570
|
+
spinner.stop("Connection timed out");
|
|
2571
2571
|
if (error2 instanceof TimeoutError) {
|
|
2572
2572
|
p3.log.warn(`No worries. Connect later with: ${pc4.cyan(`one add ${platform}`)}`);
|
|
2573
2573
|
}
|
|
@@ -2719,14 +2719,14 @@ async function connectionAddCommand(platformArg, options) {
|
|
|
2719
2719
|
process.exit(1);
|
|
2720
2720
|
}
|
|
2721
2721
|
const api = new OneApi(apiKey, getApiBase());
|
|
2722
|
-
const
|
|
2723
|
-
|
|
2722
|
+
const spinner = createSpinner();
|
|
2723
|
+
spinner.start("Loading platforms...");
|
|
2724
2724
|
let platforms;
|
|
2725
2725
|
try {
|
|
2726
2726
|
platforms = await api.listPlatforms();
|
|
2727
|
-
|
|
2727
|
+
spinner.stop(`${platforms.length} platforms available`);
|
|
2728
2728
|
} catch (error2) {
|
|
2729
|
-
|
|
2729
|
+
spinner.stop("Failed to load platforms");
|
|
2730
2730
|
p4.cancel(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
2731
2731
|
process.exit(1);
|
|
2732
2732
|
}
|
|
@@ -2798,14 +2798,14 @@ Run ${pc6.cyan("one platforms")} to see available platforms.`);
|
|
|
2798
2798
|
p4.note(`Open this URL manually:
|
|
2799
2799
|
${url}`);
|
|
2800
2800
|
}
|
|
2801
|
-
const pollSpinner =
|
|
2801
|
+
const pollSpinner = createSpinner();
|
|
2802
2802
|
pollSpinner.start("Waiting for connection... (complete auth in browser)");
|
|
2803
2803
|
try {
|
|
2804
2804
|
const connection2 = await api.waitForConnection(platform, 5 * 60 * 1e3, 5e3);
|
|
2805
2805
|
pollSpinner.stop(`${platform} connected!`);
|
|
2806
2806
|
const tag = options?.tag?.trim();
|
|
2807
2807
|
if (tag) {
|
|
2808
|
-
const tagSpinner =
|
|
2808
|
+
const tagSpinner = createSpinner();
|
|
2809
2809
|
tagSpinner.start(`Tagging connection "${tag}"...`);
|
|
2810
2810
|
try {
|
|
2811
2811
|
await api.updateConnectionTags(connection2.id, [tag]);
|
|
@@ -2844,8 +2844,8 @@ async function connectionListCommand(options) {
|
|
|
2844
2844
|
error("Not configured. Run `one init` first.");
|
|
2845
2845
|
}
|
|
2846
2846
|
const api = new OneApi(apiKey, getApiBase());
|
|
2847
|
-
const
|
|
2848
|
-
|
|
2847
|
+
const spinner = createSpinner();
|
|
2848
|
+
spinner.start("Loading connections...");
|
|
2849
2849
|
try {
|
|
2850
2850
|
const allConnections = await api.listConnections();
|
|
2851
2851
|
const ac = getAccessControlFromAllSources();
|
|
@@ -2887,7 +2887,7 @@ async function connectionListCommand(options) {
|
|
|
2887
2887
|
return;
|
|
2888
2888
|
}
|
|
2889
2889
|
const displayed = limitArg !== void 0 ? filtered.slice(0, limitArg) : filtered;
|
|
2890
|
-
|
|
2890
|
+
spinner.stop(`${filtered.length} connection${filtered.length === 1 ? "" : "s"} found`);
|
|
2891
2891
|
if (filtered.length === 0) {
|
|
2892
2892
|
if (searchQuery) {
|
|
2893
2893
|
p4.note(
|
|
@@ -2949,7 +2949,7 @@ Change it with: ${pc6.cyan("one config")}`, "Access");
|
|
|
2949
2949
|
p4.note(`Add more with: ${pc6.cyan("one connection add <platform>")}`, "Tip");
|
|
2950
2950
|
}
|
|
2951
2951
|
} catch (error2) {
|
|
2952
|
-
|
|
2952
|
+
spinner.stop("Failed to load connections");
|
|
2953
2953
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
2954
2954
|
}
|
|
2955
2955
|
}
|
|
@@ -2959,13 +2959,13 @@ async function connectionDeleteCommand(connectionKey, options) {
|
|
|
2959
2959
|
error("Not configured. Run `one init` first.");
|
|
2960
2960
|
}
|
|
2961
2961
|
const api = new OneApi(apiKey, getApiBase());
|
|
2962
|
-
const
|
|
2963
|
-
|
|
2962
|
+
const spinner = createSpinner();
|
|
2963
|
+
spinner.start("Finding connection...");
|
|
2964
2964
|
let allConnections;
|
|
2965
2965
|
try {
|
|
2966
2966
|
allConnections = await api.listConnections();
|
|
2967
2967
|
} catch (error2) {
|
|
2968
|
-
|
|
2968
|
+
spinner.stop("Failed to load connections");
|
|
2969
2969
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
2970
2970
|
return;
|
|
2971
2971
|
}
|
|
@@ -2974,12 +2974,12 @@ async function connectionDeleteCommand(connectionKey, options) {
|
|
|
2974
2974
|
const connections = allowedKeys.includes("*") ? allConnections : allConnections.filter((conn) => allowedKeys.includes(conn.key));
|
|
2975
2975
|
const match = connections.find((conn) => conn.key === connectionKey);
|
|
2976
2976
|
if (!match) {
|
|
2977
|
-
|
|
2977
|
+
spinner.stop("Connection not found");
|
|
2978
2978
|
error(`No connection found with key: ${connectionKey}`);
|
|
2979
2979
|
return;
|
|
2980
2980
|
}
|
|
2981
2981
|
const connection2 = match;
|
|
2982
|
-
|
|
2982
|
+
spinner.stop(`Found ${connection2.platform} (${connection2.state})`);
|
|
2983
2983
|
if (!isAgentMode() && !options?.force) {
|
|
2984
2984
|
console.log();
|
|
2985
2985
|
console.log(` ${getStatusIndicator(connection2.state)} ${connection2.platform} ${pc6.dim(connection2.key)}`);
|
|
@@ -3068,11 +3068,11 @@ async function platformsCommand(options) {
|
|
|
3068
3068
|
options.json = true;
|
|
3069
3069
|
}
|
|
3070
3070
|
const api = new OneApi(apiKey, getApiBase());
|
|
3071
|
-
const
|
|
3072
|
-
|
|
3071
|
+
const spinner = createSpinner();
|
|
3072
|
+
spinner.start("Loading platforms...");
|
|
3073
3073
|
try {
|
|
3074
3074
|
const platforms = await api.listPlatforms();
|
|
3075
|
-
|
|
3075
|
+
spinner.stop(`${platforms.length} platforms available`);
|
|
3076
3076
|
let filtered = platforms;
|
|
3077
3077
|
if (options.category) {
|
|
3078
3078
|
filtered = platforms.filter((plat) => (plat.category || "Other") === options.category);
|
|
@@ -3126,7 +3126,7 @@ async function platformsCommand(options) {
|
|
|
3126
3126
|
console.log();
|
|
3127
3127
|
p5.note(`Connect with: ${pc7.cyan("one connection add <platform>")}`, "Tip");
|
|
3128
3128
|
} catch (error2) {
|
|
3129
|
-
|
|
3129
|
+
spinner.stop("Failed to load platforms");
|
|
3130
3130
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
3131
3131
|
}
|
|
3132
3132
|
}
|
|
@@ -3789,7 +3789,7 @@ var CUSTOM_ACTION_NOTE = '\n\nThis is a custom action: ALSO include "connectionK
|
|
|
3789
3789
|
function codeGuideAction(action, knowledge, platform, tags, apiBase) {
|
|
3790
3790
|
const base = apiBase.replace(/\/$/, "");
|
|
3791
3791
|
const method = action.method.toUpperCase();
|
|
3792
|
-
const
|
|
3792
|
+
const path16 = action.path.startsWith("/") ? action.path : `/${action.path}`;
|
|
3793
3793
|
const connEnv = `ONE_${platformEnvSegment(platform)}_CONNECTION_KEY`;
|
|
3794
3794
|
const customNote = tags.includes("custom") ? CUSTOM_ACTION_NOTE : "";
|
|
3795
3795
|
return `### ${actionHeading(action)}
|
|
@@ -3798,7 +3798,7 @@ function codeGuideAction(action, knowledge, platform, tags, apiBase) {
|
|
|
3798
3798
|
${knowledge ?? NO_KNOWLEDGE}
|
|
3799
3799
|
|
|
3800
3800
|
## Calling this action from code
|
|
3801
|
-
URL: ${base}/passthrough${
|
|
3801
|
+
URL: ${base}/passthrough${path16}
|
|
3802
3802
|
Method: ${method}
|
|
3803
3803
|
Headers:
|
|
3804
3804
|
- x-one-secret: the value of the ONE_SECRET env var
|
|
@@ -3809,7 +3809,7 @@ Headers:
|
|
|
3809
3809
|
Environment variables: ONE_SECRET (their One API key) and ${connEnv} (the key of their ${platform} connection), both from the One dashboard.
|
|
3810
3810
|
|
|
3811
3811
|
\`\`\`typescript
|
|
3812
|
-
const response = await fetch("${base}/passthrough${
|
|
3812
|
+
const response = await fetch("${base}/passthrough${path16}", {
|
|
3813
3813
|
method: "${method}",
|
|
3814
3814
|
headers: {
|
|
3815
3815
|
"x-one-secret": process.env.ONE_SECRET,
|
|
@@ -3954,8 +3954,8 @@ async function actionsFindCommand(pairs, options) {
|
|
|
3954
3954
|
const { apiKey, permissions, connectionKeys, actionIds, knowledgeAgent } = getConfig();
|
|
3955
3955
|
const api = new OneApi(apiKey, getApiBase());
|
|
3956
3956
|
const settings = { knowledgeAgent, permissions, actionIds, connectionKeys, apiBase: getApiBase() };
|
|
3957
|
-
const
|
|
3958
|
-
|
|
3957
|
+
const spinner = createSpinner();
|
|
3958
|
+
spinner.start(`Finding actions for ${requests.length} intent${requests.length === 1 ? "" : "s"}...`);
|
|
3959
3959
|
try {
|
|
3960
3960
|
const result = await find(
|
|
3961
3961
|
requests,
|
|
@@ -3968,12 +3968,12 @@ async function actionsFindCommand(pairs, options) {
|
|
|
3968
3968
|
json(result);
|
|
3969
3969
|
return;
|
|
3970
3970
|
}
|
|
3971
|
-
|
|
3971
|
+
spinner.stop("Found");
|
|
3972
3972
|
console.log();
|
|
3973
3973
|
console.log(renderFind(result));
|
|
3974
3974
|
console.log();
|
|
3975
3975
|
} catch (error2) {
|
|
3976
|
-
|
|
3976
|
+
spinner.stop("Find failed");
|
|
3977
3977
|
error(`Error: ${failure(error2)}`);
|
|
3978
3978
|
}
|
|
3979
3979
|
}
|
|
@@ -4002,20 +4002,20 @@ async function actionsLoadCommand(actionIds, options) {
|
|
|
4002
4002
|
const { apiKey, permissions, connectionKeys, actionIds: allowed, knowledgeAgent } = getConfig();
|
|
4003
4003
|
const api = new OneApi(apiKey, getApiBase());
|
|
4004
4004
|
const settings = { knowledgeAgent, permissions, actionIds: allowed, connectionKeys, apiBase: getApiBase() };
|
|
4005
|
-
const
|
|
4006
|
-
|
|
4005
|
+
const spinner = createSpinner();
|
|
4006
|
+
spinner.start(`Loading ${actionIds.length === 1 ? "the action" : `${actionIds.length} actions`}...`);
|
|
4007
4007
|
try {
|
|
4008
4008
|
const result = await load(actionIds, options, findDeps(api, connectionKeys, options.cache !== false), settings);
|
|
4009
4009
|
if (isAgentMode()) {
|
|
4010
4010
|
json(result);
|
|
4011
4011
|
return;
|
|
4012
4012
|
}
|
|
4013
|
-
|
|
4013
|
+
spinner.stop("Loaded");
|
|
4014
4014
|
console.log();
|
|
4015
4015
|
console.log(renderLoad(result));
|
|
4016
4016
|
console.log();
|
|
4017
4017
|
} catch (error2) {
|
|
4018
|
-
|
|
4018
|
+
spinner.stop("Load failed");
|
|
4019
4019
|
error(`Error: ${failure(error2)}`);
|
|
4020
4020
|
}
|
|
4021
4021
|
}
|
|
@@ -4034,17 +4034,17 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
|
|
|
4034
4034
|
error(`Connection key "${connectionKey}" is not allowed.`);
|
|
4035
4035
|
}
|
|
4036
4036
|
const api = new OneApi(apiKey, getApiBase());
|
|
4037
|
-
const
|
|
4038
|
-
|
|
4037
|
+
const spinner = createSpinner();
|
|
4038
|
+
spinner.start("Resolving action details...");
|
|
4039
4039
|
try {
|
|
4040
4040
|
const { details: actionDetails, cacheHit: preflightCacheHit } = await resolveActionDetails(api, actionId, { useCache: options.cache !== false });
|
|
4041
4041
|
if (!isMethodAllowed(actionDetails.method, permissions)) {
|
|
4042
|
-
|
|
4042
|
+
spinner.stop("Permission denied");
|
|
4043
4043
|
error(
|
|
4044
4044
|
`Method "${actionDetails.method}" is not allowed under "${permissions}" permission level.`
|
|
4045
4045
|
);
|
|
4046
4046
|
}
|
|
4047
|
-
|
|
4047
|
+
spinner.stop(
|
|
4048
4048
|
`Action: ${actionDetails.title} [${actionDetails.method}]` + (preflightCacheHit ? pc8.dim(" (cached)") : "")
|
|
4049
4049
|
);
|
|
4050
4050
|
const data = options.data ? parseJsonArg2(options.data, "--data") : void 0;
|
|
@@ -4054,7 +4054,7 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
|
|
|
4054
4054
|
if (!options.skipValidation) {
|
|
4055
4055
|
const validation = validateActionInput(actionDetails, { data, pathVariables, queryParams });
|
|
4056
4056
|
if (!validation.valid) {
|
|
4057
|
-
|
|
4057
|
+
spinner.stop("Validation failed");
|
|
4058
4058
|
if (isAgentMode()) {
|
|
4059
4059
|
json({
|
|
4060
4060
|
error: "Validation failed: missing required parameters",
|
|
@@ -4075,7 +4075,7 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
|
|
|
4075
4075
|
}
|
|
4076
4076
|
}
|
|
4077
4077
|
if (options.mock) {
|
|
4078
|
-
|
|
4078
|
+
spinner.stop("Mock \u2014 returning example response");
|
|
4079
4079
|
const mockResponse = actionDetails.ioSchema?.ioExample?.output ?? null;
|
|
4080
4080
|
if (isAgentMode()) {
|
|
4081
4081
|
json({
|
|
@@ -4159,7 +4159,7 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
|
|
|
4159
4159
|
}
|
|
4160
4160
|
}
|
|
4161
4161
|
} catch (error2) {
|
|
4162
|
-
|
|
4162
|
+
spinner.stop("Execution failed");
|
|
4163
4163
|
error(
|
|
4164
4164
|
`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`
|
|
4165
4165
|
);
|
|
@@ -4554,32 +4554,32 @@ function validateStepsArray(steps, pathPrefix, errors) {
|
|
|
4554
4554
|
const validTypes = FLOW_SCHEMA.stepTypes.map((st) => st.type);
|
|
4555
4555
|
for (let i = 0; i < steps.length; i++) {
|
|
4556
4556
|
const step = steps[i];
|
|
4557
|
-
const
|
|
4557
|
+
const path16 = `${pathPrefix}[${i}]`;
|
|
4558
4558
|
if (!step || typeof step !== "object" || Array.isArray(step)) {
|
|
4559
|
-
errors.push({ path:
|
|
4559
|
+
errors.push({ path: path16, message: "Step must be an object" });
|
|
4560
4560
|
continue;
|
|
4561
4561
|
}
|
|
4562
4562
|
const s = step;
|
|
4563
4563
|
if (!s.id || typeof s.id !== "string") {
|
|
4564
|
-
errors.push({ path: `${
|
|
4564
|
+
errors.push({ path: `${path16}.id`, message: 'Step must have a string "id"' });
|
|
4565
4565
|
}
|
|
4566
4566
|
if (!s.name || typeof s.name !== "string") {
|
|
4567
|
-
errors.push({ path: `${
|
|
4567
|
+
errors.push({ path: `${path16}.name`, message: 'Step must have a string "name"' });
|
|
4568
4568
|
}
|
|
4569
4569
|
if (!s.type || !validTypes.includes(s.type)) {
|
|
4570
|
-
errors.push({ path: `${
|
|
4570
|
+
errors.push({ path: `${path16}.type`, message: `Step type must be one of: ${validTypes.join(", ")}` });
|
|
4571
4571
|
continue;
|
|
4572
4572
|
}
|
|
4573
4573
|
if (s.requires !== void 0) {
|
|
4574
4574
|
if (!Array.isArray(s.requires)) {
|
|
4575
|
-
errors.push({ path: `${
|
|
4575
|
+
errors.push({ path: `${path16}.requires`, message: '"requires" must be an array of selector strings (e.g. ["$.steps.foo.output.bar"])' });
|
|
4576
4576
|
} else {
|
|
4577
4577
|
for (let r = 0; r < s.requires.length; r++) {
|
|
4578
4578
|
const sel = s.requires[r];
|
|
4579
4579
|
if (typeof sel !== "string") {
|
|
4580
|
-
errors.push({ path: `${
|
|
4580
|
+
errors.push({ path: `${path16}.requires[${r}]`, message: '"requires" entry must be a selector string' });
|
|
4581
4581
|
} else if (!sel.startsWith("$.")) {
|
|
4582
|
-
errors.push({ path: `${
|
|
4582
|
+
errors.push({ path: `${path16}.requires[${r}]`, message: `"requires" entry "${sel}" must be a selector starting with "$." (e.g. "$.steps.foo.output.bar")` });
|
|
4583
4583
|
}
|
|
4584
4584
|
}
|
|
4585
4585
|
}
|
|
@@ -4587,7 +4587,7 @@ function validateStepsArray(steps, pathPrefix, errors) {
|
|
|
4587
4587
|
if (s.onError && typeof s.onError === "object") {
|
|
4588
4588
|
const oe = s.onError;
|
|
4589
4589
|
if (!FLOW_SCHEMA.errorStrategies.includes(oe.strategy)) {
|
|
4590
|
-
errors.push({ path: `${
|
|
4590
|
+
errors.push({ path: `${path16}.onError.strategy`, message: `Error strategy must be one of: ${FLOW_SCHEMA.errorStrategies.join(", ")}` });
|
|
4591
4591
|
}
|
|
4592
4592
|
}
|
|
4593
4593
|
const descriptor = getStepTypeDescriptor(s.type);
|
|
@@ -4597,14 +4597,14 @@ function validateStepsArray(steps, pathPrefix, errors) {
|
|
|
4597
4597
|
if (!configObj || typeof configObj !== "object") {
|
|
4598
4598
|
const hint = detectFlatConfigHint(s, descriptor);
|
|
4599
4599
|
errors.push({
|
|
4600
|
-
path: `${
|
|
4600
|
+
path: `${path16}.${configKey}`,
|
|
4601
4601
|
message: `${capitalize(descriptor.type)} step must have a "${configKey}" config object${hint}`
|
|
4602
4602
|
});
|
|
4603
4603
|
continue;
|
|
4604
4604
|
}
|
|
4605
4605
|
const config2 = configObj;
|
|
4606
4606
|
for (const [fieldName, fd] of Object.entries(descriptor.fields)) {
|
|
4607
|
-
const fieldPath = `${
|
|
4607
|
+
const fieldPath = `${path16}.${configKey}.${fieldName}`;
|
|
4608
4608
|
const value = config2[fieldName];
|
|
4609
4609
|
if (fd.required && (value === void 0 || value === null || value === "")) {
|
|
4610
4610
|
errors.push({ path: fieldPath, message: `${capitalize(descriptor.type)} must have ${fd.type === "string" ? "a string" : fd.type === "array" ? "a" : "a"} "${fieldName}"` });
|
|
@@ -4637,30 +4637,30 @@ function validateStepsArray(steps, pathPrefix, errors) {
|
|
|
4637
4637
|
}
|
|
4638
4638
|
}
|
|
4639
4639
|
if (descriptor.type === "action") {
|
|
4640
|
-
validateConnectionForm(config2, `${
|
|
4640
|
+
validateConnectionForm(config2, `${path16}.${configKey}`, errors);
|
|
4641
4641
|
}
|
|
4642
4642
|
if (descriptor.type === "code") {
|
|
4643
4643
|
const hasSource = typeof config2.source === "string" && config2.source.length > 0;
|
|
4644
4644
|
const hasModule = typeof config2.module === "string" && config2.module.length > 0;
|
|
4645
4645
|
if (!hasSource && !hasModule) {
|
|
4646
|
-
errors.push({ path: `${
|
|
4646
|
+
errors.push({ path: `${path16}.${configKey}`, message: 'Code step must define either "source" (inline JS) or "module" (path to .mjs file)' });
|
|
4647
4647
|
} else if (hasSource && hasModule) {
|
|
4648
|
-
errors.push({ path: `${
|
|
4648
|
+
errors.push({ path: `${path16}.${configKey}`, message: 'Code step cannot define both "source" and "module" \u2014 pick one' });
|
|
4649
4649
|
}
|
|
4650
4650
|
if (hasModule) {
|
|
4651
4651
|
const m = config2.module;
|
|
4652
4652
|
if (m.startsWith("/") || /^[a-zA-Z]:[\\/]/.test(m)) {
|
|
4653
|
-
errors.push({ path: `${
|
|
4653
|
+
errors.push({ path: `${path16}.${configKey}.module`, message: "Code module path must be relative to the flow folder (no absolute paths)" });
|
|
4654
4654
|
} else if (m.split(/[\\/]/).includes("..")) {
|
|
4655
|
-
errors.push({ path: `${
|
|
4655
|
+
errors.push({ path: `${path16}.${configKey}.module`, message: 'Code module path must not escape the flow folder ("..")' });
|
|
4656
4656
|
} else if (!m.endsWith(".mjs")) {
|
|
4657
|
-
errors.push({ path: `${
|
|
4657
|
+
errors.push({ path: `${path16}.${configKey}.module`, message: "Code module must be a .mjs file" });
|
|
4658
4658
|
}
|
|
4659
4659
|
}
|
|
4660
4660
|
if (hasSource) {
|
|
4661
4661
|
const syntaxError = checkCodeSourceSyntax(config2.source);
|
|
4662
4662
|
if (syntaxError) {
|
|
4663
|
-
errors.push({ path: `${
|
|
4663
|
+
errors.push({ path: `${path16}.${configKey}.source`, message: `Syntax error in code step: ${syntaxError}` });
|
|
4664
4664
|
}
|
|
4665
4665
|
}
|
|
4666
4666
|
}
|
|
@@ -4732,16 +4732,16 @@ function validateStepIds(flow2) {
|
|
|
4732
4732
|
function collectIds(steps, pathPrefix) {
|
|
4733
4733
|
for (let i = 0; i < steps.length; i++) {
|
|
4734
4734
|
const step = steps[i];
|
|
4735
|
-
const
|
|
4735
|
+
const path16 = `${pathPrefix}[${i}]`;
|
|
4736
4736
|
if (seen.has(step.id)) {
|
|
4737
|
-
errors.push({ path: `${
|
|
4737
|
+
errors.push({ path: `${path16}.id`, message: `Duplicate step ID: "${step.id}"` });
|
|
4738
4738
|
} else {
|
|
4739
4739
|
seen.add(step.id);
|
|
4740
4740
|
}
|
|
4741
4741
|
for (const { configKey, fieldName } of nestedKeys) {
|
|
4742
4742
|
const config2 = step[configKey];
|
|
4743
4743
|
if (config2 && Array.isArray(config2[fieldName])) {
|
|
4744
|
-
collectIds(config2[fieldName], `${
|
|
4744
|
+
collectIds(config2[fieldName], `${path16}.${configKey}.${fieldName}`);
|
|
4745
4745
|
}
|
|
4746
4746
|
}
|
|
4747
4747
|
}
|
|
@@ -4789,7 +4789,7 @@ function validateSelectorReferences(flow2, rootDir) {
|
|
|
4789
4789
|
}
|
|
4790
4790
|
return selectors;
|
|
4791
4791
|
}
|
|
4792
|
-
function checkSelectors(selectors,
|
|
4792
|
+
function checkSelectors(selectors, path16, precedingStepIds) {
|
|
4793
4793
|
for (const selector of selectors) {
|
|
4794
4794
|
const parts = selector.split(".");
|
|
4795
4795
|
if (parts.length < 3) continue;
|
|
@@ -4797,15 +4797,15 @@ function validateSelectorReferences(flow2, rootDir) {
|
|
|
4797
4797
|
if (root === "input") {
|
|
4798
4798
|
const inputName = parts[2];
|
|
4799
4799
|
if (!inputNames.has(inputName)) {
|
|
4800
|
-
errors.push({ path:
|
|
4800
|
+
errors.push({ path: path16, message: `Selector "${selector}" references undefined input "${inputName}"` });
|
|
4801
4801
|
}
|
|
4802
4802
|
} else if (root === "steps") {
|
|
4803
4803
|
const stepId = parts[2].replace(/[\[\]]/g, "").split(/[\[\]]/)[0];
|
|
4804
4804
|
if (!allStepIds.has(stepId)) {
|
|
4805
|
-
errors.push({ path:
|
|
4805
|
+
errors.push({ path: path16, message: `Selector "${selector}" references undefined step "${stepId}"` });
|
|
4806
4806
|
} else if (precedingStepIds && !precedingStepIds.has(stepId)) {
|
|
4807
4807
|
errors.push({
|
|
4808
|
-
path:
|
|
4808
|
+
path: path16,
|
|
4809
4809
|
message: `Selector "${selector}" references step "${stepId}" which is declared after the current step. Steps execute in declaration order, so this will always resolve to undefined at runtime \u2014 move the dependency earlier in the steps array.`
|
|
4810
4810
|
});
|
|
4811
4811
|
}
|
|
@@ -4813,20 +4813,20 @@ function validateSelectorReferences(flow2, rootDir) {
|
|
|
4813
4813
|
}
|
|
4814
4814
|
}
|
|
4815
4815
|
const EXPRESSION_FIELDS = /* @__PURE__ */ new Set(["condition.expression", "while.condition"]);
|
|
4816
|
-
function checkOperatorsInSelectorField(value,
|
|
4816
|
+
function checkOperatorsInSelectorField(value, path16) {
|
|
4817
4817
|
if (typeof value === "string" && value.startsWith("$.")) {
|
|
4818
4818
|
if (value.includes("||")) {
|
|
4819
|
-
errors.push({ path:
|
|
4819
|
+
errors.push({ path: path16, message: `Selector "${value}" contains unsupported operator "||". Selectors in data fields use dot-path resolution, not JS evaluation. Use the "default" field on the input definition instead, or use a "code" step for complex expressions.` });
|
|
4820
4820
|
} else if (value.includes("&&")) {
|
|
4821
|
-
errors.push({ path:
|
|
4821
|
+
errors.push({ path: path16, message: `Selector "${value}" contains unsupported operator "&&". Selectors in data fields use dot-path resolution, not JS evaluation. Use a "condition" step or "code" step for complex expressions.` });
|
|
4822
4822
|
}
|
|
4823
4823
|
} else if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
4824
4824
|
for (const [k, v] of Object.entries(value)) {
|
|
4825
|
-
checkOperatorsInSelectorField(v, `${
|
|
4825
|
+
checkOperatorsInSelectorField(v, `${path16}.${k}`);
|
|
4826
4826
|
}
|
|
4827
4827
|
} else if (Array.isArray(value)) {
|
|
4828
4828
|
for (let i = 0; i < value.length; i++) {
|
|
4829
|
-
checkOperatorsInSelectorField(value[i], `${
|
|
4829
|
+
checkOperatorsInSelectorField(value[i], `${path16}[${i}]`);
|
|
4830
4830
|
}
|
|
4831
4831
|
}
|
|
4832
4832
|
}
|
|
@@ -4911,10 +4911,10 @@ var VALID_OUTPUT_SCHEMA_TYPES = /* @__PURE__ */ new Set(["string", "number", "bo
|
|
|
4911
4911
|
function isOutputSchemaObject(v) {
|
|
4912
4912
|
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
4913
4913
|
}
|
|
4914
|
-
function walkOutputSchema(schema,
|
|
4914
|
+
function walkOutputSchema(schema, path16) {
|
|
4915
4915
|
let current = schema;
|
|
4916
|
-
for (let i = 0; i <
|
|
4917
|
-
const seg =
|
|
4916
|
+
for (let i = 0; i < path16.length; i++) {
|
|
4917
|
+
const seg = path16[i];
|
|
4918
4918
|
if (typeof current === "string") {
|
|
4919
4919
|
return current === "unknown" || current === "object" || current === "array" ? "opaque" : "opaque";
|
|
4920
4920
|
}
|
|
@@ -5376,8 +5376,8 @@ async function flowExecuteCommand(keyOrPath, options) {
|
|
|
5376
5376
|
intro(pc9.bgCyan(pc9.black(" One Workflow ")));
|
|
5377
5377
|
const { apiKey, permissions, actionIds } = getConfig2();
|
|
5378
5378
|
const api = new OneApi(apiKey, getApiBase());
|
|
5379
|
-
const
|
|
5380
|
-
|
|
5379
|
+
const spinner = createSpinner();
|
|
5380
|
+
spinner.start(`Loading workflow "${keyOrPath}"...`);
|
|
5381
5381
|
let flow2;
|
|
5382
5382
|
let rootDir;
|
|
5383
5383
|
let flowFilePath;
|
|
@@ -5387,11 +5387,11 @@ async function flowExecuteCommand(keyOrPath, options) {
|
|
|
5387
5387
|
rootDir = loaded.rootDir;
|
|
5388
5388
|
flowFilePath = loaded.filePath;
|
|
5389
5389
|
} catch (err) {
|
|
5390
|
-
|
|
5390
|
+
spinner.stop("Workflow not found");
|
|
5391
5391
|
error(err instanceof Error ? err.message : String(err));
|
|
5392
5392
|
return;
|
|
5393
5393
|
}
|
|
5394
|
-
|
|
5394
|
+
spinner.stop(`Workflow: ${flow2.name} (${flow2.steps.length} steps)`);
|
|
5395
5395
|
const preflightErrors = validateFlow(flow2, rootDir);
|
|
5396
5396
|
if (preflightErrors.length > 0) {
|
|
5397
5397
|
if (isAgentMode()) {
|
|
@@ -5596,8 +5596,8 @@ async function flowListCommand() {
|
|
|
5596
5596
|
}
|
|
5597
5597
|
async function flowValidateCommand(keyOrPath) {
|
|
5598
5598
|
intro(pc9.bgCyan(pc9.black(" One Workflow ")));
|
|
5599
|
-
const
|
|
5600
|
-
|
|
5599
|
+
const spinner = createSpinner();
|
|
5600
|
+
spinner.start(`Validating "${keyOrPath}"...`);
|
|
5601
5601
|
let flowData;
|
|
5602
5602
|
let rootDir;
|
|
5603
5603
|
try {
|
|
@@ -5612,12 +5612,12 @@ async function flowValidateCommand(keyOrPath) {
|
|
|
5612
5612
|
rootDir = path7.dirname(flowPath);
|
|
5613
5613
|
}
|
|
5614
5614
|
} catch (err) {
|
|
5615
|
-
|
|
5615
|
+
spinner.stop("Validation failed");
|
|
5616
5616
|
error(`Could not read workflow: ${err instanceof Error ? err.message : String(err)}`);
|
|
5617
5617
|
}
|
|
5618
5618
|
const errors = validateFlow(flowData, rootDir);
|
|
5619
5619
|
if (errors.length > 0) {
|
|
5620
|
-
|
|
5620
|
+
spinner.stop("Validation failed");
|
|
5621
5621
|
if (isAgentMode()) {
|
|
5622
5622
|
json({ valid: false, errors });
|
|
5623
5623
|
process.exit(1);
|
|
@@ -5629,7 +5629,7 @@ async function flowValidateCommand(keyOrPath) {
|
|
|
5629
5629
|
console.log();
|
|
5630
5630
|
error(`${errors.length} validation error(s) found`);
|
|
5631
5631
|
}
|
|
5632
|
-
|
|
5632
|
+
spinner.stop("Workflow is valid");
|
|
5633
5633
|
if (isAgentMode()) {
|
|
5634
5634
|
json({ valid: true, key: flowData.key });
|
|
5635
5635
|
return;
|
|
@@ -5671,15 +5671,15 @@ async function flowResumeCommand(runId, options = {}) {
|
|
|
5671
5671
|
json(event);
|
|
5672
5672
|
}
|
|
5673
5673
|
};
|
|
5674
|
-
const
|
|
5675
|
-
|
|
5674
|
+
const spinner = createSpinner();
|
|
5675
|
+
spinner.start(`Resuming run ${runId} (${state.completedSteps.length} steps already completed)...`);
|
|
5676
5676
|
try {
|
|
5677
5677
|
const context = await runner.resume(flow2, api, permissions, actionIds, {
|
|
5678
5678
|
onEvent,
|
|
5679
5679
|
rootDir,
|
|
5680
5680
|
allowBash: options.allowBash
|
|
5681
5681
|
});
|
|
5682
|
-
|
|
5682
|
+
spinner.stop("Workflow completed");
|
|
5683
5683
|
if (isAgentMode()) {
|
|
5684
5684
|
json({
|
|
5685
5685
|
event: "workflow:result",
|
|
@@ -5693,7 +5693,7 @@ async function flowResumeCommand(runId, options = {}) {
|
|
|
5693
5693
|
console.log(` ${pc9.green("\u2713")} Resumed and completed successfully`);
|
|
5694
5694
|
console.log(` ${pc9.dim(`Log: ${runner.getLogPath()}`)}`);
|
|
5695
5695
|
} catch (error2) {
|
|
5696
|
-
|
|
5696
|
+
spinner.stop("Resume failed");
|
|
5697
5697
|
const errorMsg = error2 instanceof Error ? error2.message : String(error2);
|
|
5698
5698
|
if (isAgentMode()) {
|
|
5699
5699
|
json({ event: "workflow:result", runId, status: "failed", error: errorMsg });
|
|
@@ -6010,8 +6010,8 @@ async function relayCreateCommand(options) {
|
|
|
6010
6010
|
error(`Connection key "${options.connectionKey}" is not allowed.`);
|
|
6011
6011
|
}
|
|
6012
6012
|
const api = new OneApi(apiKey, getApiBase());
|
|
6013
|
-
const
|
|
6014
|
-
|
|
6013
|
+
const spinner = createSpinner();
|
|
6014
|
+
spinner.start("Creating relay endpoint...");
|
|
6015
6015
|
try {
|
|
6016
6016
|
const body = {
|
|
6017
6017
|
connectionKey: options.connectionKey
|
|
@@ -6026,7 +6026,7 @@ async function relayCreateCommand(options) {
|
|
|
6026
6026
|
json(result);
|
|
6027
6027
|
return;
|
|
6028
6028
|
}
|
|
6029
|
-
|
|
6029
|
+
spinner.stop("Relay endpoint created");
|
|
6030
6030
|
console.log();
|
|
6031
6031
|
console.log(` ${pc10.dim("ID:")} ${result.id}`);
|
|
6032
6032
|
console.log(` ${pc10.dim("URL:")} ${result.url}`);
|
|
@@ -6040,15 +6040,15 @@ async function relayCreateCommand(options) {
|
|
|
6040
6040
|
}
|
|
6041
6041
|
console.log();
|
|
6042
6042
|
} catch (error2) {
|
|
6043
|
-
|
|
6043
|
+
spinner.stop("Failed to create relay endpoint");
|
|
6044
6044
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
6045
6045
|
}
|
|
6046
6046
|
}
|
|
6047
6047
|
async function relayListCommand(options) {
|
|
6048
6048
|
const { apiKey } = getConfig3();
|
|
6049
6049
|
const api = new OneApi(apiKey, getApiBase());
|
|
6050
|
-
const
|
|
6051
|
-
|
|
6050
|
+
const spinner = createSpinner();
|
|
6051
|
+
spinner.start("Loading relay endpoints...");
|
|
6052
6052
|
try {
|
|
6053
6053
|
const query = {};
|
|
6054
6054
|
if (options.limit) query.limit = options.limit;
|
|
@@ -6071,7 +6071,7 @@ async function relayListCommand(options) {
|
|
|
6071
6071
|
});
|
|
6072
6072
|
return;
|
|
6073
6073
|
}
|
|
6074
|
-
|
|
6074
|
+
spinner.stop(`${endpoints.length} relay endpoint${endpoints.length === 1 ? "" : "s"} found`);
|
|
6075
6075
|
if (endpoints.length === 0) {
|
|
6076
6076
|
console.log("\n No relay endpoints yet.\n");
|
|
6077
6077
|
return;
|
|
@@ -6093,22 +6093,22 @@ async function relayListCommand(options) {
|
|
|
6093
6093
|
}))
|
|
6094
6094
|
);
|
|
6095
6095
|
} catch (error2) {
|
|
6096
|
-
|
|
6096
|
+
spinner.stop("Failed to list relay endpoints");
|
|
6097
6097
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
6098
6098
|
}
|
|
6099
6099
|
}
|
|
6100
6100
|
async function relayGetCommand(id) {
|
|
6101
6101
|
const { apiKey } = getConfig3();
|
|
6102
6102
|
const api = new OneApi(apiKey, getApiBase());
|
|
6103
|
-
const
|
|
6104
|
-
|
|
6103
|
+
const spinner = createSpinner();
|
|
6104
|
+
spinner.start("Loading relay endpoint...");
|
|
6105
6105
|
try {
|
|
6106
6106
|
const result = await api.getRelayEndpoint(id);
|
|
6107
6107
|
if (isAgentMode()) {
|
|
6108
6108
|
json(result);
|
|
6109
6109
|
return;
|
|
6110
6110
|
}
|
|
6111
|
-
|
|
6111
|
+
spinner.stop("Relay endpoint loaded");
|
|
6112
6112
|
console.log();
|
|
6113
6113
|
console.log(` ${pc10.dim("ID:")} ${result.id}`);
|
|
6114
6114
|
console.log(` ${pc10.dim("URL:")} ${result.url}`);
|
|
@@ -6124,15 +6124,15 @@ async function relayGetCommand(id) {
|
|
|
6124
6124
|
console.log(` ${pc10.dim("Created:")} ${result.createdAt}`);
|
|
6125
6125
|
console.log();
|
|
6126
6126
|
} catch (error2) {
|
|
6127
|
-
|
|
6127
|
+
spinner.stop("Failed to load relay endpoint");
|
|
6128
6128
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
6129
6129
|
}
|
|
6130
6130
|
}
|
|
6131
6131
|
async function relayUpdateCommand(id, options) {
|
|
6132
6132
|
const { apiKey } = getConfig3();
|
|
6133
6133
|
const api = new OneApi(apiKey, getApiBase());
|
|
6134
|
-
const
|
|
6135
|
-
|
|
6134
|
+
const spinner = createSpinner();
|
|
6135
|
+
spinner.start("Updating relay endpoint...");
|
|
6136
6136
|
try {
|
|
6137
6137
|
const body = {};
|
|
6138
6138
|
if (options.description !== void 0) body.description = options.description;
|
|
@@ -6145,40 +6145,40 @@ async function relayUpdateCommand(id, options) {
|
|
|
6145
6145
|
json(result);
|
|
6146
6146
|
return;
|
|
6147
6147
|
}
|
|
6148
|
-
|
|
6148
|
+
spinner.stop("Relay endpoint updated");
|
|
6149
6149
|
console.log(` ${pc10.dim("ID:")} ${result.id}`);
|
|
6150
6150
|
console.log(` ${pc10.dim("Active:")} ${result.active}`);
|
|
6151
6151
|
console.log(` ${pc10.dim("Actions:")} ${result.actions?.length || 0}`);
|
|
6152
6152
|
console.log();
|
|
6153
6153
|
} catch (error2) {
|
|
6154
|
-
|
|
6154
|
+
spinner.stop("Failed to update relay endpoint");
|
|
6155
6155
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
6156
6156
|
}
|
|
6157
6157
|
}
|
|
6158
6158
|
async function relayDeleteCommand(id) {
|
|
6159
6159
|
const { apiKey } = getConfig3();
|
|
6160
6160
|
const api = new OneApi(apiKey, getApiBase());
|
|
6161
|
-
const
|
|
6162
|
-
|
|
6161
|
+
const spinner = createSpinner();
|
|
6162
|
+
spinner.start("Deleting relay endpoint...");
|
|
6163
6163
|
try {
|
|
6164
6164
|
const result = await api.deleteRelayEndpoint(id);
|
|
6165
6165
|
if (isAgentMode()) {
|
|
6166
6166
|
json({ deleted: true, id: result.id });
|
|
6167
6167
|
return;
|
|
6168
6168
|
}
|
|
6169
|
-
|
|
6169
|
+
spinner.stop("Relay endpoint deleted");
|
|
6170
6170
|
console.log(` Deleted: ${result.id}`);
|
|
6171
6171
|
console.log();
|
|
6172
6172
|
} catch (error2) {
|
|
6173
|
-
|
|
6173
|
+
spinner.stop("Failed to delete relay endpoint");
|
|
6174
6174
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
6175
6175
|
}
|
|
6176
6176
|
}
|
|
6177
6177
|
async function relayActivateCommand(id, options) {
|
|
6178
6178
|
const { apiKey } = getConfig3();
|
|
6179
6179
|
const api = new OneApi(apiKey, getApiBase());
|
|
6180
|
-
const
|
|
6181
|
-
|
|
6180
|
+
const spinner = createSpinner();
|
|
6181
|
+
spinner.start("Activating relay endpoint...");
|
|
6182
6182
|
try {
|
|
6183
6183
|
const actions2 = parseJsonArg3(options.actions, "--actions");
|
|
6184
6184
|
const body = { actions: actions2 };
|
|
@@ -6188,21 +6188,21 @@ async function relayActivateCommand(id, options) {
|
|
|
6188
6188
|
json(result);
|
|
6189
6189
|
return;
|
|
6190
6190
|
}
|
|
6191
|
-
|
|
6191
|
+
spinner.stop("Relay endpoint activated");
|
|
6192
6192
|
console.log(` ${pc10.dim("ID:")} ${result.id}`);
|
|
6193
6193
|
console.log(` ${pc10.dim("Active:")} ${result.active}`);
|
|
6194
6194
|
console.log(` ${pc10.dim("Actions:")} ${result.actions?.length || 0}`);
|
|
6195
6195
|
console.log();
|
|
6196
6196
|
} catch (error2) {
|
|
6197
|
-
|
|
6197
|
+
spinner.stop("Failed to activate relay endpoint");
|
|
6198
6198
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
6199
6199
|
}
|
|
6200
6200
|
}
|
|
6201
6201
|
async function relayEventsCommand(options) {
|
|
6202
6202
|
const { apiKey } = getConfig3();
|
|
6203
6203
|
const api = new OneApi(apiKey, getApiBase());
|
|
6204
|
-
const
|
|
6205
|
-
|
|
6204
|
+
const spinner = createSpinner();
|
|
6205
|
+
spinner.start("Loading relay events...");
|
|
6206
6206
|
try {
|
|
6207
6207
|
const query = {};
|
|
6208
6208
|
if (options.limit) query.limit = options.limit;
|
|
@@ -6226,7 +6226,7 @@ async function relayEventsCommand(options) {
|
|
|
6226
6226
|
});
|
|
6227
6227
|
return;
|
|
6228
6228
|
}
|
|
6229
|
-
|
|
6229
|
+
spinner.stop(`${events.length} event${events.length === 1 ? "" : "s"} found`);
|
|
6230
6230
|
if (events.length === 0) {
|
|
6231
6231
|
console.log("\n No events found.\n");
|
|
6232
6232
|
return;
|
|
@@ -6246,22 +6246,22 @@ async function relayEventsCommand(options) {
|
|
|
6246
6246
|
}))
|
|
6247
6247
|
);
|
|
6248
6248
|
} catch (error2) {
|
|
6249
|
-
|
|
6249
|
+
spinner.stop("Failed to list relay events");
|
|
6250
6250
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
6251
6251
|
}
|
|
6252
6252
|
}
|
|
6253
6253
|
async function relayEventGetCommand(id) {
|
|
6254
6254
|
const { apiKey } = getConfig3();
|
|
6255
6255
|
const api = new OneApi(apiKey, getApiBase());
|
|
6256
|
-
const
|
|
6257
|
-
|
|
6256
|
+
const spinner = createSpinner();
|
|
6257
|
+
spinner.start("Loading relay event...");
|
|
6258
6258
|
try {
|
|
6259
6259
|
const result = await api.getRelayEvent(id);
|
|
6260
6260
|
if (isAgentMode()) {
|
|
6261
6261
|
json(result);
|
|
6262
6262
|
return;
|
|
6263
6263
|
}
|
|
6264
|
-
|
|
6264
|
+
spinner.stop("Relay event loaded");
|
|
6265
6265
|
console.log();
|
|
6266
6266
|
console.log(` ${pc10.dim("ID:")} ${result.id}`);
|
|
6267
6267
|
console.log(` ${pc10.dim("Platform:")} ${result.platform}`);
|
|
@@ -6271,7 +6271,7 @@ async function relayEventGetCommand(id) {
|
|
|
6271
6271
|
console.log(JSON.stringify(result.payload, null, 2));
|
|
6272
6272
|
console.log();
|
|
6273
6273
|
} catch (error2) {
|
|
6274
|
-
|
|
6274
|
+
spinner.stop("Failed to load relay event");
|
|
6275
6275
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
6276
6276
|
}
|
|
6277
6277
|
}
|
|
@@ -6281,8 +6281,8 @@ async function relayDeliveriesCommand(options) {
|
|
|
6281
6281
|
}
|
|
6282
6282
|
const { apiKey } = getConfig3();
|
|
6283
6283
|
const api = new OneApi(apiKey, getApiBase());
|
|
6284
|
-
const
|
|
6285
|
-
|
|
6284
|
+
const spinner = createSpinner();
|
|
6285
|
+
spinner.start("Loading deliveries...");
|
|
6286
6286
|
try {
|
|
6287
6287
|
const deliveries = options.endpointId ? await api.listRelayEndpointDeliveries(options.endpointId) : await api.listRelayEventDeliveries(options.eventId);
|
|
6288
6288
|
const items = Array.isArray(deliveries) ? deliveries : deliveries.rows || [];
|
|
@@ -6290,7 +6290,7 @@ async function relayDeliveriesCommand(options) {
|
|
|
6290
6290
|
json({ deliveries: items });
|
|
6291
6291
|
return;
|
|
6292
6292
|
}
|
|
6293
|
-
|
|
6293
|
+
spinner.stop(`${items.length} deliver${items.length === 1 ? "y" : "ies"} found`);
|
|
6294
6294
|
if (items.length === 0) {
|
|
6295
6295
|
console.log("\n No deliveries found.\n");
|
|
6296
6296
|
return;
|
|
@@ -6312,22 +6312,22 @@ async function relayDeliveriesCommand(options) {
|
|
|
6312
6312
|
}))
|
|
6313
6313
|
);
|
|
6314
6314
|
} catch (error2) {
|
|
6315
|
-
|
|
6315
|
+
spinner.stop("Failed to load deliveries");
|
|
6316
6316
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
6317
6317
|
}
|
|
6318
6318
|
}
|
|
6319
6319
|
async function relayPlatformsCommand() {
|
|
6320
6320
|
const { apiKey } = getConfig3();
|
|
6321
6321
|
const api = new OneApi(apiKey, getApiBase());
|
|
6322
|
-
const
|
|
6323
|
-
|
|
6322
|
+
const spinner = createSpinner();
|
|
6323
|
+
spinner.start("Loading relay-capable platforms...");
|
|
6324
6324
|
try {
|
|
6325
6325
|
const platforms = await api.listRelayPlatforms();
|
|
6326
6326
|
if (isAgentMode()) {
|
|
6327
6327
|
json({ platforms });
|
|
6328
6328
|
return;
|
|
6329
6329
|
}
|
|
6330
|
-
|
|
6330
|
+
spinner.stop(`${platforms.length} relay-capable platform${platforms.length === 1 ? "" : "s"} found`);
|
|
6331
6331
|
if (platforms.length === 0) {
|
|
6332
6332
|
console.log("\n No relay-capable platforms available.\n");
|
|
6333
6333
|
return;
|
|
@@ -6348,22 +6348,22 @@ async function relayPlatformsCommand() {
|
|
|
6348
6348
|
)
|
|
6349
6349
|
);
|
|
6350
6350
|
} catch (error2) {
|
|
6351
|
-
|
|
6351
|
+
spinner.stop("Failed to load relay platforms");
|
|
6352
6352
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
6353
6353
|
}
|
|
6354
6354
|
}
|
|
6355
6355
|
async function relayEventTypesCommand(platform) {
|
|
6356
6356
|
const { apiKey } = getConfig3();
|
|
6357
6357
|
const api = new OneApi(apiKey, getApiBase());
|
|
6358
|
-
const
|
|
6359
|
-
|
|
6358
|
+
const spinner = createSpinner();
|
|
6359
|
+
spinner.start(`Loading event types for ${pc10.cyan(platform)}...`);
|
|
6360
6360
|
try {
|
|
6361
6361
|
const eventTypes = await api.listRelayEventTypes(platform);
|
|
6362
6362
|
if (isAgentMode()) {
|
|
6363
6363
|
json({ platform, eventTypes });
|
|
6364
6364
|
return;
|
|
6365
6365
|
}
|
|
6366
|
-
|
|
6366
|
+
spinner.stop(`${eventTypes.length} event type${eventTypes.length === 1 ? "" : "s"} found`);
|
|
6367
6367
|
if (eventTypes.length === 0) {
|
|
6368
6368
|
console.log(`
|
|
6369
6369
|
No event types found for ${platform}.
|
|
@@ -6376,7 +6376,7 @@ async function relayEventTypesCommand(platform) {
|
|
|
6376
6376
|
}
|
|
6377
6377
|
console.log();
|
|
6378
6378
|
} catch (error2) {
|
|
6379
|
-
|
|
6379
|
+
spinner.stop("Failed to load event types");
|
|
6380
6380
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
6381
6381
|
}
|
|
6382
6382
|
}
|
|
@@ -6861,8 +6861,8 @@ function sleep(ms) {
|
|
|
6861
6861
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
6862
6862
|
}
|
|
6863
6863
|
function interpolate(template, record) {
|
|
6864
|
-
return template.replace(/\{?\{(\w+(?:\.\w+)*)\}\}?/g, (_,
|
|
6865
|
-
const parts =
|
|
6864
|
+
return template.replace(/\{?\{(\w+(?:\.\w+)*)\}\}?/g, (_, path16) => {
|
|
6865
|
+
const parts = path16.split(".");
|
|
6866
6866
|
let value = record;
|
|
6867
6867
|
for (const part2 of parts) {
|
|
6868
6868
|
if (typeof value !== "object" || value === null) return "";
|
|
@@ -6890,8 +6890,8 @@ function deepMerge(target, source) {
|
|
|
6890
6890
|
}
|
|
6891
6891
|
return result;
|
|
6892
6892
|
}
|
|
6893
|
-
function getByDotPath2(obj,
|
|
6894
|
-
const parts =
|
|
6893
|
+
function getByDotPath2(obj, path16) {
|
|
6894
|
+
const parts = path16.split(".");
|
|
6895
6895
|
let current = obj;
|
|
6896
6896
|
for (const part2 of parts) {
|
|
6897
6897
|
if (current === null || current === void 0 || typeof current !== "object") return void 0;
|
|
@@ -6900,8 +6900,8 @@ function getByDotPath2(obj, path14) {
|
|
|
6900
6900
|
return current;
|
|
6901
6901
|
}
|
|
6902
6902
|
function stripExcludedFields(obj, paths) {
|
|
6903
|
-
for (const
|
|
6904
|
-
stripOnePath(obj,
|
|
6903
|
+
for (const path16 of paths) {
|
|
6904
|
+
stripOnePath(obj, path16.replace(/\[\]/g, ".*").split("."));
|
|
6905
6905
|
}
|
|
6906
6906
|
}
|
|
6907
6907
|
function stripOnePath(obj, parts) {
|
|
@@ -7322,8 +7322,8 @@ function sleep2(ms) {
|
|
|
7322
7322
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
7323
7323
|
}
|
|
7324
7324
|
function stripFields(record, paths) {
|
|
7325
|
-
for (const
|
|
7326
|
-
stripOnePath2(record,
|
|
7325
|
+
for (const path16 of paths) {
|
|
7326
|
+
stripOnePath2(record, path16.split("."));
|
|
7327
7327
|
}
|
|
7328
7328
|
}
|
|
7329
7329
|
function stripOnePath2(obj, parts) {
|
|
@@ -7657,7 +7657,7 @@ async function syncModel(api, profile, options) {
|
|
|
7657
7657
|
records,
|
|
7658
7658
|
tableCreated
|
|
7659
7659
|
) : void 0;
|
|
7660
|
-
const
|
|
7660
|
+
const report2 = await writePageToMemory(
|
|
7661
7661
|
profile,
|
|
7662
7662
|
records,
|
|
7663
7663
|
{
|
|
@@ -7669,12 +7669,12 @@ async function syncModel(api, profile, options) {
|
|
|
7669
7669
|
alreadyEnrichedIds
|
|
7670
7670
|
}
|
|
7671
7671
|
);
|
|
7672
|
-
pageReport =
|
|
7673
|
-
memPreserved +=
|
|
7674
|
-
for (const key of
|
|
7672
|
+
pageReport = report2;
|
|
7673
|
+
memPreserved += report2.preserved;
|
|
7674
|
+
for (const key of report2.sourceKeysSeen) seenSourceKeys.add(key);
|
|
7675
7675
|
if (hasHooks && !db) {
|
|
7676
|
-
inserts =
|
|
7677
|
-
updates =
|
|
7676
|
+
inserts = report2.inserts;
|
|
7677
|
+
updates = report2.updates;
|
|
7678
7678
|
}
|
|
7679
7679
|
} catch (err) {
|
|
7680
7680
|
const msg = err instanceof Error ? err.message : String(err);
|
|
@@ -7993,7 +7993,7 @@ function detectColumnType2(value) {
|
|
|
7993
7993
|
}
|
|
7994
7994
|
async function testSyncProfile(api, profile) {
|
|
7995
7995
|
const checks = [];
|
|
7996
|
-
const
|
|
7996
|
+
const report2 = {
|
|
7997
7997
|
platform: profile.platform,
|
|
7998
7998
|
model: profile.model,
|
|
7999
7999
|
ok: false,
|
|
@@ -8025,7 +8025,7 @@ async function testSyncProfile(api, profile) {
|
|
|
8025
8025
|
ok: false,
|
|
8026
8026
|
detail: err instanceof Error ? err.message : String(err)
|
|
8027
8027
|
});
|
|
8028
|
-
return
|
|
8028
|
+
return report2;
|
|
8029
8029
|
}
|
|
8030
8030
|
let actionDetails;
|
|
8031
8031
|
try {
|
|
@@ -8037,7 +8037,7 @@ async function testSyncProfile(api, profile) {
|
|
|
8037
8037
|
ok: false,
|
|
8038
8038
|
detail: err instanceof Error ? err.message : String(err)
|
|
8039
8039
|
});
|
|
8040
|
-
return
|
|
8040
|
+
return report2;
|
|
8041
8041
|
}
|
|
8042
8042
|
if (actionDetails.tags?.includes("custom")) {
|
|
8043
8043
|
checks.push({
|
|
@@ -8045,7 +8045,7 @@ async function testSyncProfile(api, profile) {
|
|
|
8045
8045
|
ok: false,
|
|
8046
8046
|
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.`
|
|
8047
8047
|
});
|
|
8048
|
-
return
|
|
8048
|
+
return report2;
|
|
8049
8049
|
}
|
|
8050
8050
|
let responseData;
|
|
8051
8051
|
try {
|
|
@@ -8062,7 +8062,7 @@ async function testSyncProfile(api, profile) {
|
|
|
8062
8062
|
} catch (err) {
|
|
8063
8063
|
const detail = err instanceof ApiError ? `HTTP ${err.status}: ${err.message}` : err instanceof Error ? err.message : String(err);
|
|
8064
8064
|
checks.push({ name: "single-page fetch", ok: false, detail });
|
|
8065
|
-
return
|
|
8065
|
+
return report2;
|
|
8066
8066
|
}
|
|
8067
8067
|
let resolvedResultsPath = profile.resultsPath;
|
|
8068
8068
|
const rawCandidate = isRootPath(resolvedResultsPath) ? responseData : getByDotPath(responseData, resolvedResultsPath);
|
|
@@ -8071,8 +8071,8 @@ async function testSyncProfile(api, profile) {
|
|
|
8071
8071
|
if (Array.isArray(responseData)) {
|
|
8072
8072
|
resolvedResultsPath = "";
|
|
8073
8073
|
records = responseData;
|
|
8074
|
-
|
|
8075
|
-
|
|
8074
|
+
report2.autoFixed = report2.autoFixed ?? {};
|
|
8075
|
+
report2.autoFixed.resultsPath = "";
|
|
8076
8076
|
checks.push({
|
|
8077
8077
|
name: `resultsPath auto-discovered \u2192 <root>`,
|
|
8078
8078
|
ok: true,
|
|
@@ -8084,8 +8084,8 @@ async function testSyncProfile(api, profile) {
|
|
|
8084
8084
|
if (arrayKey) {
|
|
8085
8085
|
resolvedResultsPath = arrayKey;
|
|
8086
8086
|
records = topObj[arrayKey];
|
|
8087
|
-
|
|
8088
|
-
|
|
8087
|
+
report2.autoFixed = report2.autoFixed ?? {};
|
|
8088
|
+
report2.autoFixed.resultsPath = arrayKey;
|
|
8089
8089
|
checks.push({
|
|
8090
8090
|
name: `resultsPath auto-discovered \u2192 "${arrayKey}"`,
|
|
8091
8091
|
ok: true,
|
|
@@ -8101,7 +8101,7 @@ async function testSyncProfile(api, profile) {
|
|
|
8101
8101
|
ok: false,
|
|
8102
8102
|
detail: `Not an array. Response keys: [${topKeys.join(", ")}]`
|
|
8103
8103
|
});
|
|
8104
|
-
return
|
|
8104
|
+
return report2;
|
|
8105
8105
|
}
|
|
8106
8106
|
let wrappedPrimitives = false;
|
|
8107
8107
|
if (records.length > 0 && typeof records[0] !== "object") {
|
|
@@ -8122,8 +8122,8 @@ async function testSyncProfile(api, profile) {
|
|
|
8122
8122
|
});
|
|
8123
8123
|
if (records.length === 0) {
|
|
8124
8124
|
checks.push({ name: "sample record available", ok: false, detail: "empty result set" });
|
|
8125
|
-
|
|
8126
|
-
return
|
|
8125
|
+
report2.ok = checks.every((c) => c.ok === true || c.name === "sample record available");
|
|
8126
|
+
return report2;
|
|
8127
8127
|
}
|
|
8128
8128
|
const first = records[0];
|
|
8129
8129
|
let resolvedIdField = profile.idField;
|
|
@@ -8137,8 +8137,8 @@ async function testSyncProfile(api, profile) {
|
|
|
8137
8137
|
if (found) {
|
|
8138
8138
|
resolvedIdField = found;
|
|
8139
8139
|
idValue = getByDotPath(first, found);
|
|
8140
|
-
|
|
8141
|
-
|
|
8140
|
+
report2.autoFixed = report2.autoFixed ?? {};
|
|
8141
|
+
report2.autoFixed.idField = found;
|
|
8142
8142
|
checks.push({
|
|
8143
8143
|
name: `idField auto-discovered \u2192 "${found}"`,
|
|
8144
8144
|
ok: true,
|
|
@@ -8175,7 +8175,7 @@ async function testSyncProfile(api, profile) {
|
|
|
8175
8175
|
ok: true,
|
|
8176
8176
|
detail: JSON.stringify(nextParams).slice(0, 120)
|
|
8177
8177
|
});
|
|
8178
|
-
|
|
8178
|
+
report2.paginationPreview = nextParams;
|
|
8179
8179
|
} else {
|
|
8180
8180
|
checks.push({
|
|
8181
8181
|
name: `pagination "${profile.pagination.type}"`,
|
|
@@ -8183,22 +8183,22 @@ async function testSyncProfile(api, profile) {
|
|
|
8183
8183
|
detail: "no next page (single-page result or end-of-data)"
|
|
8184
8184
|
});
|
|
8185
8185
|
}
|
|
8186
|
-
|
|
8186
|
+
report2.detectedColumns = Object.entries(first).map(([name, value]) => ({
|
|
8187
8187
|
name,
|
|
8188
8188
|
type: detectColumnType2(value)
|
|
8189
8189
|
}));
|
|
8190
|
-
|
|
8191
|
-
|
|
8192
|
-
if (profile.enrich && (profile.identityKeys?.length ?? 0) > 0 &&
|
|
8193
|
-
const merged = await enrichOneForPreview(api, profile,
|
|
8190
|
+
report2.sample = first;
|
|
8191
|
+
report2.samples = records.slice(0, SEARCHABLE_SAMPLE_SIZE);
|
|
8192
|
+
if (profile.enrich && (profile.identityKeys?.length ?? 0) > 0 && report2.samples.length > 0) {
|
|
8193
|
+
const merged = await enrichOneForPreview(api, profile, report2.samples[0], connectionKey);
|
|
8194
8194
|
if (merged) {
|
|
8195
8195
|
const preview = buildIdentityKeysPreview([merged], profile);
|
|
8196
|
-
if (preview)
|
|
8196
|
+
if (preview) report2.identityKeysPreview = { ...preview, previewedAfterEnrich: true };
|
|
8197
8197
|
}
|
|
8198
8198
|
}
|
|
8199
|
-
|
|
8200
|
-
|
|
8201
|
-
return
|
|
8199
|
+
report2.identityKeysPreview ??= buildIdentityKeysPreview(report2.samples, profile);
|
|
8200
|
+
report2.ok = checks.every((c) => c.ok);
|
|
8201
|
+
return report2;
|
|
8202
8202
|
}
|
|
8203
8203
|
|
|
8204
8204
|
// src/lib/memory/sync/infer.ts
|
|
@@ -8974,11 +8974,11 @@ function isNoise(s) {
|
|
|
8974
8974
|
if (/^-?\d+(\.\d+)?([eE][-+]?\d+)?$/.test(s)) return true;
|
|
8975
8975
|
return false;
|
|
8976
8976
|
}
|
|
8977
|
-
function recordSample(stats,
|
|
8978
|
-
let s = stats.get(
|
|
8977
|
+
function recordSample(stats, path16, value, jsType, recordIndex, totalSamples) {
|
|
8978
|
+
let s = stats.get(path16);
|
|
8979
8979
|
if (!s) {
|
|
8980
8980
|
s = {
|
|
8981
|
-
path:
|
|
8981
|
+
path: path16,
|
|
8982
8982
|
total: totalSamples,
|
|
8983
8983
|
recordIndices: /* @__PURE__ */ new Set(),
|
|
8984
8984
|
lenSum: 0,
|
|
@@ -8987,7 +8987,7 @@ function recordSample(stats, path14, value, jsType, recordIndex, totalSamples) {
|
|
|
8987
8987
|
primaryType: jsType,
|
|
8988
8988
|
examples: []
|
|
8989
8989
|
};
|
|
8990
|
-
stats.set(
|
|
8990
|
+
stats.set(path16, s);
|
|
8991
8991
|
}
|
|
8992
8992
|
s.recordIndices.add(recordIndex);
|
|
8993
8993
|
s.lenSum += value.length;
|
|
@@ -8996,28 +8996,28 @@ function recordSample(stats, path14, value, jsType, recordIndex, totalSamples) {
|
|
|
8996
8996
|
if (s.primaryType !== jsType) s.primaryType = "mixed";
|
|
8997
8997
|
if (s.examples.length < 3 && value.length < 200) s.examples.push(value);
|
|
8998
8998
|
}
|
|
8999
|
-
function walkRecord(record,
|
|
8999
|
+
function walkRecord(record, path16, stats, recordIndex, totalSamples) {
|
|
9000
9000
|
if (record === null || record === void 0) return;
|
|
9001
9001
|
if (typeof record === "string") {
|
|
9002
9002
|
const trimmed = record.trim();
|
|
9003
|
-
if (trimmed) recordSample(stats,
|
|
9003
|
+
if (trimmed) recordSample(stats, path16, trimmed, "string", recordIndex, totalSamples);
|
|
9004
9004
|
return;
|
|
9005
9005
|
}
|
|
9006
9006
|
if (typeof record === "number" || typeof record === "boolean") {
|
|
9007
9007
|
const str = String(record);
|
|
9008
9008
|
const kind = typeof record === "number" ? "number" : "boolean";
|
|
9009
|
-
if (str) recordSample(stats,
|
|
9009
|
+
if (str) recordSample(stats, path16, str, kind, recordIndex, totalSamples);
|
|
9010
9010
|
return;
|
|
9011
9011
|
}
|
|
9012
9012
|
if (Array.isArray(record)) {
|
|
9013
|
-
const childPath =
|
|
9013
|
+
const childPath = path16 ? `${path16}[]` : "[]";
|
|
9014
9014
|
for (const item of record) walkRecord(item, childPath, stats, recordIndex, totalSamples);
|
|
9015
9015
|
return;
|
|
9016
9016
|
}
|
|
9017
9017
|
if (typeof record === "object") {
|
|
9018
9018
|
for (const [key, value] of Object.entries(record)) {
|
|
9019
9019
|
if (key.startsWith("_")) continue;
|
|
9020
|
-
const childPath =
|
|
9020
|
+
const childPath = path16 ? `${path16}.${key}` : key;
|
|
9021
9021
|
walkRecord(value, childPath, stats, recordIndex, totalSamples);
|
|
9022
9022
|
}
|
|
9023
9023
|
}
|
|
@@ -9179,11 +9179,11 @@ ${profiles.length} built-in profile(s). Run ${pc11.bold("one sync init <platform
|
|
|
9179
9179
|
}
|
|
9180
9180
|
async function syncModelsCommand(platform) {
|
|
9181
9181
|
const api = getApi();
|
|
9182
|
-
const
|
|
9183
|
-
|
|
9182
|
+
const spinner = createSpinner();
|
|
9183
|
+
spinner.start(`Discovering models for ${platform}...`);
|
|
9184
9184
|
try {
|
|
9185
9185
|
const models = await discoverModels(api, platform);
|
|
9186
|
-
|
|
9186
|
+
spinner.stop(`Found ${models.length} models`);
|
|
9187
9187
|
if (isAgentMode()) {
|
|
9188
9188
|
json({ platform, models, total: models.length });
|
|
9189
9189
|
return;
|
|
@@ -9197,15 +9197,15 @@ async function syncModelsCommand(platform) {
|
|
|
9197
9197
|
);
|
|
9198
9198
|
note(lines.join("\n"), `${platform} \u2014 ${models.length} models`);
|
|
9199
9199
|
} catch (err) {
|
|
9200
|
-
|
|
9200
|
+
spinner.stop("Failed");
|
|
9201
9201
|
error(`Error discovering models: ${err instanceof Error ? err.message : String(err)}`);
|
|
9202
9202
|
}
|
|
9203
9203
|
}
|
|
9204
9204
|
async function syncInitCommand(platform, model, options) {
|
|
9205
9205
|
if (!options.config) {
|
|
9206
9206
|
const api = getApi();
|
|
9207
|
-
const
|
|
9208
|
-
|
|
9207
|
+
const spinner = createSpinner();
|
|
9208
|
+
spinner.start(`Looking up ${platform}/${model}...`);
|
|
9209
9209
|
try {
|
|
9210
9210
|
const models = await discoverModels(api, platform);
|
|
9211
9211
|
const match = models.find((m) => m.name === model || m.name.toLowerCase() === model.toLowerCase());
|
|
@@ -9215,9 +9215,9 @@ async function syncInitCommand(platform, model, options) {
|
|
|
9215
9215
|
if (actionId && !actionId.startsWith("conn_mod_def::")) {
|
|
9216
9216
|
actionId = void 0;
|
|
9217
9217
|
}
|
|
9218
|
-
|
|
9218
|
+
spinner.stop(actionId ? "Found model + action ID" : "Found model (action ID not resolved)");
|
|
9219
9219
|
} else {
|
|
9220
|
-
|
|
9220
|
+
spinner.stop("Model not found in available actions");
|
|
9221
9221
|
}
|
|
9222
9222
|
const builtin = loadBuiltinProfile(platform, model);
|
|
9223
9223
|
let template;
|
|
@@ -9317,7 +9317,7 @@ Run with --config to save:
|
|
|
9317
9317
|
}
|
|
9318
9318
|
}
|
|
9319
9319
|
} catch (err) {
|
|
9320
|
-
|
|
9320
|
+
spinner.stop("Failed");
|
|
9321
9321
|
error(`Error: ${err instanceof Error ? err.message : String(err)}`);
|
|
9322
9322
|
}
|
|
9323
9323
|
return;
|
|
@@ -9371,38 +9371,38 @@ async function syncTestCommand(platformModel, options = {}) {
|
|
|
9371
9371
|
);
|
|
9372
9372
|
}
|
|
9373
9373
|
const api = getApi();
|
|
9374
|
-
const
|
|
9375
|
-
if (
|
|
9374
|
+
const report2 = await testSyncProfile(api, profile);
|
|
9375
|
+
if (report2.autoFixed && Object.keys(report2.autoFixed).length > 0) {
|
|
9376
9376
|
try {
|
|
9377
9377
|
const existing = readProfile(platform, model);
|
|
9378
9378
|
if (existing) {
|
|
9379
|
-
const patched = { ...existing, ...
|
|
9379
|
+
const patched = { ...existing, ...report2.autoFixed };
|
|
9380
9380
|
writeProfile(patched);
|
|
9381
9381
|
}
|
|
9382
9382
|
} catch {
|
|
9383
9383
|
}
|
|
9384
9384
|
}
|
|
9385
|
-
const searchablePreview = options.showSearchable ? buildSearchablePreview(profile,
|
|
9385
|
+
const searchablePreview = options.showSearchable ? buildSearchablePreview(profile, report2.samples) : null;
|
|
9386
9386
|
if (isAgentMode()) {
|
|
9387
|
-
json({ ...
|
|
9387
|
+
json({ ...report2, ...searchablePreview ? { searchable: searchablePreview } : {} });
|
|
9388
9388
|
return;
|
|
9389
9389
|
}
|
|
9390
|
-
for (const c of
|
|
9390
|
+
for (const c of report2.checks) {
|
|
9391
9391
|
const mark = c.ok ? pc11.green("\u2713") : pc11.red("\u2717");
|
|
9392
9392
|
console.log(` ${mark} ${c.name}${c.detail ? pc11.dim(` \u2014 ${c.detail}`) : ""}`);
|
|
9393
9393
|
}
|
|
9394
|
-
if (
|
|
9394
|
+
if (report2.detectedColumns && report2.detectedColumns.length > 0) {
|
|
9395
9395
|
console.log(`
|
|
9396
9396
|
${pc11.bold("Detected columns:")}`);
|
|
9397
|
-
for (const col of
|
|
9397
|
+
for (const col of report2.detectedColumns.slice(0, 20)) {
|
|
9398
9398
|
console.log(` ${col.name.padEnd(30)} ${pc11.dim(col.type)}`);
|
|
9399
9399
|
}
|
|
9400
|
-
if (
|
|
9401
|
-
console.log(pc11.dim(` ... and ${
|
|
9400
|
+
if (report2.detectedColumns.length > 20) {
|
|
9401
|
+
console.log(pc11.dim(` ... and ${report2.detectedColumns.length - 20} more`));
|
|
9402
9402
|
}
|
|
9403
9403
|
}
|
|
9404
|
-
if (
|
|
9405
|
-
const { perRecord, sampleKeys, entityFanOut, resolvesAfterEnrich } =
|
|
9404
|
+
if (report2.identityKeysPreview) {
|
|
9405
|
+
const { perRecord, sampleKeys, entityFanOut, resolvesAfterEnrich } = report2.identityKeysPreview;
|
|
9406
9406
|
const total = perRecord.reduce((a, b) => a + b, 0);
|
|
9407
9407
|
const min = perRecord.length ? Math.min(...perRecord) : 0;
|
|
9408
9408
|
const max = perRecord.length ? Math.max(...perRecord) : 0;
|
|
@@ -9444,7 +9444,7 @@ async function syncTestCommand(platformModel, options = {}) {
|
|
|
9444
9444
|
}
|
|
9445
9445
|
console.log(
|
|
9446
9446
|
`
|
|
9447
|
-
${
|
|
9447
|
+
${report2.ok ? pc11.green("Profile looks good.") : pc11.red("Profile has issues.")} ` + (report2.ok ? `Run: ${pc11.bold(`one sync run ${platform} --models ${model}`)}` : "Fix the issues above and test again.")
|
|
9448
9448
|
);
|
|
9449
9449
|
}
|
|
9450
9450
|
function buildSearchablePreview(profile, samples) {
|
|
@@ -9452,7 +9452,7 @@ function buildSearchablePreview(profile, samples) {
|
|
|
9452
9452
|
const first = samples[0];
|
|
9453
9453
|
const paths = getSearchablePaths(profile);
|
|
9454
9454
|
if (paths) {
|
|
9455
|
-
const perPathAgg = paths.map((
|
|
9455
|
+
const perPathAgg = paths.map((path16) => ({ path: path16, hits: 0, total: samples.length, sample: "" }));
|
|
9456
9456
|
for (const record of samples) {
|
|
9457
9457
|
const { paths: perPath } = extractSearchableFromPaths(record, paths);
|
|
9458
9458
|
perPath.forEach((p9, i) => {
|
|
@@ -9602,7 +9602,7 @@ ${result.total} results`);
|
|
|
9602
9602
|
}
|
|
9603
9603
|
}
|
|
9604
9604
|
async function syncSqlCommand(platformModel, sql) {
|
|
9605
|
-
const { syncSqlCommand: runSyncSql } = await import("./sql-
|
|
9605
|
+
const { syncSqlCommand: runSyncSql } = await import("./sql-AKQSXRV2.js");
|
|
9606
9606
|
await runSyncSql(platformModel, sql);
|
|
9607
9607
|
}
|
|
9608
9608
|
async function syncDeleteCommand(platformModel, options) {
|
|
@@ -9696,7 +9696,7 @@ async function maybeAutoMigrateLegacy(platform, models) {
|
|
|
9696
9696
|
` detected legacy .one/sync/data/${platform}.db (${dbSize}) \u2014 auto-migrating into memory before sync.
|
|
9697
9697
|
`
|
|
9698
9698
|
);
|
|
9699
|
-
const { memMigrateCommand: memMigrateCommand3 } = await import("./migrate-
|
|
9699
|
+
const { memMigrateCommand: memMigrateCommand3 } = await import("./migrate-3LSEIPRF.js");
|
|
9700
9700
|
await memMigrateCommand3({ platform, yes: true });
|
|
9701
9701
|
return;
|
|
9702
9702
|
}
|
|
@@ -9705,7 +9705,7 @@ async function maybeAutoMigrateLegacy(platform, models) {
|
|
|
9705
9705
|
initialValue: true
|
|
9706
9706
|
});
|
|
9707
9707
|
if (p6.isCancel(shouldMigrate) || !shouldMigrate) return;
|
|
9708
|
-
const { memMigrateCommand: memMigrateCommand2 } = await import("./migrate-
|
|
9708
|
+
const { memMigrateCommand: memMigrateCommand2 } = await import("./migrate-3LSEIPRF.js");
|
|
9709
9709
|
await memMigrateCommand2({ platform, yes: true });
|
|
9710
9710
|
}
|
|
9711
9711
|
async function syncSuggestSearchableCommand(platformModel, options = {}) {
|
|
@@ -9720,8 +9720,8 @@ async function syncSuggestSearchableCommand(platformModel, options = {}) {
|
|
|
9720
9720
|
);
|
|
9721
9721
|
}
|
|
9722
9722
|
const api = getApi();
|
|
9723
|
-
const
|
|
9724
|
-
const samples =
|
|
9723
|
+
const report2 = await testSyncProfile(api, profile);
|
|
9724
|
+
const samples = report2.samples ?? [];
|
|
9725
9725
|
if (samples.length === 0) {
|
|
9726
9726
|
error(
|
|
9727
9727
|
"No sample records available to rank against. Fix the failures in `sync test` first, then re-run suggest-searchable."
|
|
@@ -10042,7 +10042,7 @@ function registerSyncSubcommands(sync) {
|
|
|
10042
10042
|
await syncSqlCommand(platformModel, sql);
|
|
10043
10043
|
});
|
|
10044
10044
|
sync.command("schema <platform/model>").description("Inspect the JSON structure of synced records (field paths, types, examples) \u2014 useful before writing `sync sql` queries").action(async (platformModel) => {
|
|
10045
|
-
const { syncSchemaCommand } = await import("./schema-
|
|
10045
|
+
const { syncSchemaCommand } = await import("./schema-FICQRMZ7.js");
|
|
10046
10046
|
await syncSchemaCommand(platformModel);
|
|
10047
10047
|
});
|
|
10048
10048
|
sync.command("delete <platform/model>").description('Delete records from local sync data (e.g. one sync delete notion/pages --id "abc-123")').option("--id <value>", "Delete record by ID").option("--where <conditions>", 'Delete records matching conditions (e.g. "status=archived")').option("--where-sql <predicate>", `Delete using a raw SQL WHERE clause (e.g. "json_extract(data, '$.type') = 'promotion'")`).option("--yes", "Skip confirmation prompt").action(async (platformModel, options) => {
|
|
@@ -10409,16 +10409,16 @@ function projectEmbeddingApiKey(cfg) {
|
|
|
10409
10409
|
}
|
|
10410
10410
|
function redactSecrets(cfg) {
|
|
10411
10411
|
const copy = JSON.parse(JSON.stringify(cfg));
|
|
10412
|
-
for (const
|
|
10413
|
-
const val = getPath(copy,
|
|
10412
|
+
for (const path16 of SECRET_PATHS) {
|
|
10413
|
+
const val = getPath(copy, path16);
|
|
10414
10414
|
if (typeof val === "string" && val.length > 0) {
|
|
10415
|
-
setPath(copy,
|
|
10415
|
+
setPath(copy, path16, `${val.slice(0, 6)}\u2026(redacted, use --show-secrets)`);
|
|
10416
10416
|
}
|
|
10417
10417
|
}
|
|
10418
10418
|
return copy;
|
|
10419
10419
|
}
|
|
10420
|
-
function getPath(obj,
|
|
10421
|
-
const parts =
|
|
10420
|
+
function getPath(obj, path16) {
|
|
10421
|
+
const parts = path16.split(".");
|
|
10422
10422
|
let cur = obj;
|
|
10423
10423
|
for (const part2 of parts) {
|
|
10424
10424
|
if (cur == null || typeof cur !== "object") return void 0;
|
|
@@ -10426,8 +10426,8 @@ function getPath(obj, path14) {
|
|
|
10426
10426
|
}
|
|
10427
10427
|
return cur;
|
|
10428
10428
|
}
|
|
10429
|
-
function setPath(obj,
|
|
10430
|
-
const parts =
|
|
10429
|
+
function setPath(obj, path16, value) {
|
|
10430
|
+
const parts = path16.split(".");
|
|
10431
10431
|
let cur = obj;
|
|
10432
10432
|
for (let i = 0; i < parts.length - 1; i++) {
|
|
10433
10433
|
const part2 = parts[i];
|
|
@@ -10437,8 +10437,8 @@ function setPath(obj, path14, value) {
|
|
|
10437
10437
|
cur[parts[parts.length - 1]] = value;
|
|
10438
10438
|
return obj;
|
|
10439
10439
|
}
|
|
10440
|
-
function unsetPath(obj,
|
|
10441
|
-
const parts =
|
|
10440
|
+
function unsetPath(obj, path16) {
|
|
10441
|
+
const parts = path16.split(".");
|
|
10442
10442
|
let cur = obj;
|
|
10443
10443
|
for (let i = 0; i < parts.length - 1; i++) {
|
|
10444
10444
|
const part2 = parts[i];
|
|
@@ -11243,8 +11243,8 @@ async function cacheUpdateAllCommand() {
|
|
|
11243
11243
|
console.log("No cached entries to update");
|
|
11244
11244
|
return;
|
|
11245
11245
|
}
|
|
11246
|
-
const
|
|
11247
|
-
|
|
11246
|
+
const spinner = createSpinner();
|
|
11247
|
+
spinner.start(`Updating ${entries.length} cached ${entries.length === 1 ? "entry" : "entries"}...`);
|
|
11248
11248
|
let updated = 0;
|
|
11249
11249
|
let failed = 0;
|
|
11250
11250
|
const errors = [];
|
|
@@ -11261,7 +11261,7 @@ async function cacheUpdateAllCommand() {
|
|
|
11261
11261
|
});
|
|
11262
11262
|
}
|
|
11263
11263
|
}
|
|
11264
|
-
|
|
11264
|
+
spinner.stop(`Updated ${updated} ${updated === 1 ? "entry" : "entries"}${failed > 0 ? `, ${failed} failed` : ""}`);
|
|
11265
11265
|
if (isAgentMode()) {
|
|
11266
11266
|
json({ updated, failed, errors: errors.length > 0 ? errors : void 0 });
|
|
11267
11267
|
return;
|
|
@@ -11413,6 +11413,7 @@ Request specific sections:
|
|
|
11413
11413
|
- Connection keys come from \`one connection list\` \u2014 don't hardcode them
|
|
11414
11414
|
- \`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
|
|
11415
11415
|
- Skills stay in lockstep with the CLI version automatically \u2014 every command checks a \`.one-cli-version\` marker in the canonical skill dir and refreshes the files if the CLI has been upgraded. Check manually with \`one config skills status\`; force a resync with \`one config skills sync\`
|
|
11416
|
+
- Building an app whose users connect their own tools? \`one skills add connect\` (run inside the app) installs the One Connect skill from the \`@withone/connect\` version the app uses, into \`.agents/skills/one-connect\` and \`.claude/skills/one-connect\`. \`one --agent skills list\` shows what is installed; any \`one\` command in the project refreshes it after an SDK upgrade
|
|
11416
11417
|
`;
|
|
11417
11418
|
var GUIDE_ACTIONS = `# One Actions \u2014 Reference
|
|
11418
11419
|
|
|
@@ -12806,22 +12807,22 @@ function buildWorkflowIdeas(connections) {
|
|
|
12806
12807
|
// src/commands/logout.ts
|
|
12807
12808
|
import fs13 from "fs";
|
|
12808
12809
|
import * as p8 from "@clack/prompts";
|
|
12809
|
-
function formatWhoami(config2, apiKey,
|
|
12810
|
+
function formatWhoami(config2, apiKey, pc17) {
|
|
12810
12811
|
const whoami = config2.whoami;
|
|
12811
12812
|
const env = getEnvFromApiKey(apiKey);
|
|
12812
|
-
const envLabel = env === "test" ?
|
|
12813
|
+
const envLabel = env === "test" ? pc17.yellow("test") : pc17.green("live");
|
|
12813
12814
|
const lines = [];
|
|
12814
12815
|
if (whoami) {
|
|
12815
12816
|
const contextParts = [];
|
|
12816
12817
|
if (whoami.organization) contextParts.push(whoami.organization.name);
|
|
12817
12818
|
if (whoami.project) contextParts.push(whoami.project.name);
|
|
12818
12819
|
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
12819
|
-
lines.push(`${
|
|
12820
|
-
lines.push(`${whoami.user.name} ${
|
|
12821
|
-
if (config2.apiKeyName) lines.push(`${
|
|
12820
|
+
lines.push(`${pc17.bold(scopeDisplay)} ${pc17.dim("\xB7")} ${envLabel}`);
|
|
12821
|
+
lines.push(`${whoami.user.name} ${pc17.dim(`(${whoami.user.email})`)}`);
|
|
12822
|
+
if (config2.apiKeyName) lines.push(`${pc17.dim("Key:")} ${config2.apiKeyName}`);
|
|
12822
12823
|
} else {
|
|
12823
12824
|
const keyLabel = config2.apiKeyName ?? `${apiKey.slice(0, 8)}...`;
|
|
12824
|
-
lines.push(`${
|
|
12825
|
+
lines.push(`${pc17.dim("Key:")} ${keyLabel} ${pc17.dim("\xB7")} ${envLabel}`);
|
|
12825
12826
|
}
|
|
12826
12827
|
return lines;
|
|
12827
12828
|
}
|
|
@@ -12850,7 +12851,7 @@ async function logoutCommand() {
|
|
|
12850
12851
|
json({ status: cleared ? "logged_out" : "not_logged_in", message: cleared ? "Credentials cleared." : "No config found." });
|
|
12851
12852
|
return;
|
|
12852
12853
|
}
|
|
12853
|
-
const
|
|
12854
|
+
const pc17 = (await import("picocolors")).default;
|
|
12854
12855
|
const globalConfig = readGlobalConfig();
|
|
12855
12856
|
const projectConfig = readProjectConfig();
|
|
12856
12857
|
const hasGlobal = globalConfig?.apiKey != null;
|
|
@@ -12859,13 +12860,13 @@ async function logoutCommand() {
|
|
|
12859
12860
|
if (hasGlobal && hasProject) {
|
|
12860
12861
|
const infoLines = ["You are logged in with multiple configs.", ""];
|
|
12861
12862
|
if (projectConfig) {
|
|
12862
|
-
infoLines.push(`${
|
|
12863
|
-
infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey,
|
|
12863
|
+
infoLines.push(`${pc17.cyan("Local config:")}`);
|
|
12864
|
+
infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey, pc17));
|
|
12864
12865
|
infoLines.push("");
|
|
12865
12866
|
}
|
|
12866
12867
|
if (globalConfig) {
|
|
12867
|
-
infoLines.push(`${
|
|
12868
|
-
infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey,
|
|
12868
|
+
infoLines.push(`${pc17.magenta("Global config:")}`);
|
|
12869
|
+
infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey, pc17));
|
|
12869
12870
|
}
|
|
12870
12871
|
p8.note(infoLines.join("\n"));
|
|
12871
12872
|
const choice = await p8.select({
|
|
@@ -12883,14 +12884,14 @@ async function logoutCommand() {
|
|
|
12883
12884
|
targetScope = choice;
|
|
12884
12885
|
} else if (hasProject) {
|
|
12885
12886
|
const infoLines = ["You are logged in.", ""];
|
|
12886
|
-
infoLines.push(`${
|
|
12887
|
-
infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey,
|
|
12887
|
+
infoLines.push(`${pc17.dim("Stored in")} ${pc17.cyan("local config")}`);
|
|
12888
|
+
infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey, pc17));
|
|
12888
12889
|
p8.note(infoLines.join("\n"));
|
|
12889
12890
|
targetScope = "project";
|
|
12890
12891
|
} else if (hasGlobal) {
|
|
12891
12892
|
const infoLines = ["You are logged in.", ""];
|
|
12892
|
-
infoLines.push(`${
|
|
12893
|
-
infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey,
|
|
12893
|
+
infoLines.push(`${pc17.dim("Stored in")} ${pc17.magenta("global config")}`);
|
|
12894
|
+
infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey, pc17));
|
|
12894
12895
|
p8.note(infoLines.join("\n"));
|
|
12895
12896
|
targetScope = "global";
|
|
12896
12897
|
} else {
|
|
@@ -12924,6 +12925,538 @@ async function logoutCommand() {
|
|
|
12924
12925
|
p8.outro("Logged out.");
|
|
12925
12926
|
}
|
|
12926
12927
|
|
|
12928
|
+
// src/lib/project-skills.ts
|
|
12929
|
+
import crypto2 from "crypto";
|
|
12930
|
+
import fs14 from "fs";
|
|
12931
|
+
import os3 from "os";
|
|
12932
|
+
import path13 from "path";
|
|
12933
|
+
import zlib from "zlib";
|
|
12934
|
+
var OPTIONAL_SKILLS = [
|
|
12935
|
+
{
|
|
12936
|
+
name: "connect",
|
|
12937
|
+
dirName: "one-connect",
|
|
12938
|
+
title: "One Connect",
|
|
12939
|
+
description: "Add One Connect to an app: your users grant it scoped, revocable access to their own tools.",
|
|
12940
|
+
packageName: "@withone/connect",
|
|
12941
|
+
packagePath: "skills/one-connect"
|
|
12942
|
+
}
|
|
12943
|
+
];
|
|
12944
|
+
function findOptionalSkill(name) {
|
|
12945
|
+
const wanted = name.trim().toLowerCase();
|
|
12946
|
+
return OPTIONAL_SKILLS.find((s) => s.name === wanted || s.dirName === wanted);
|
|
12947
|
+
}
|
|
12948
|
+
var UNIVERSAL_PROJECT_DIR = ".agents/skills";
|
|
12949
|
+
var SKILL_AGENT_TARGETS = [
|
|
12950
|
+
{ id: "claude-code", name: "Claude Code", projectDir: ".claude/skills", projectMarker: null, homeDir: ".claude/skills" },
|
|
12951
|
+
{ id: "codex", name: "Codex", projectDir: UNIVERSAL_PROJECT_DIR, projectMarker: null, homeDir: ".codex/skills" },
|
|
12952
|
+
{ id: "cursor", name: "Cursor", projectDir: UNIVERSAL_PROJECT_DIR, projectMarker: null, homeDir: ".cursor/skills" },
|
|
12953
|
+
{ id: "amp", name: "Amp", projectDir: UNIVERSAL_PROJECT_DIR, projectMarker: null, homeDir: ".amp/skills" },
|
|
12954
|
+
{ id: "opencode", name: "OpenCode", projectDir: UNIVERSAL_PROJECT_DIR, projectMarker: null, homeDir: ".opencode/skills" },
|
|
12955
|
+
{ id: "windsurf", name: "Windsurf", projectDir: ".windsurf/skills", projectMarker: ".windsurf", homeDir: ".codeium/windsurf/skills" },
|
|
12956
|
+
{ id: "kiro", name: "Kiro", projectDir: ".kiro/skills", projectMarker: ".kiro", homeDir: ".kiro/skills" },
|
|
12957
|
+
{ id: "goose", name: "Goose", projectDir: ".goose/skills", projectMarker: ".goose", homeDir: ".config/goose/skills" },
|
|
12958
|
+
{ id: "roo", name: "Roo", projectDir: ".roo/skills", projectMarker: ".roo", homeDir: ".roo/skills" }
|
|
12959
|
+
];
|
|
12960
|
+
function findAgentTarget(id) {
|
|
12961
|
+
return SKILL_AGENT_TARGETS.find((a) => a.id === id.trim().toLowerCase());
|
|
12962
|
+
}
|
|
12963
|
+
function findProjectRoot(start) {
|
|
12964
|
+
let dir = path13.resolve(start);
|
|
12965
|
+
for (; ; ) {
|
|
12966
|
+
if (fs14.existsSync(path13.join(dir, "package.json")) || fs14.existsSync(path13.join(dir, ".git"))) return dir;
|
|
12967
|
+
const parent = path13.dirname(dir);
|
|
12968
|
+
if (parent === dir) return null;
|
|
12969
|
+
dir = parent;
|
|
12970
|
+
}
|
|
12971
|
+
}
|
|
12972
|
+
function findInstalledPackage(start, packageName) {
|
|
12973
|
+
let dir = path13.resolve(start);
|
|
12974
|
+
for (; ; ) {
|
|
12975
|
+
const pkgDir = path13.join(dir, "node_modules", ...packageName.split("/"));
|
|
12976
|
+
const manifest = path13.join(pkgDir, "package.json");
|
|
12977
|
+
if (fs14.existsSync(manifest)) {
|
|
12978
|
+
try {
|
|
12979
|
+
const { version: version2 } = JSON.parse(fs14.readFileSync(manifest, "utf-8"));
|
|
12980
|
+
if (version2) return { dir: pkgDir, version: version2 };
|
|
12981
|
+
} catch {
|
|
12982
|
+
}
|
|
12983
|
+
}
|
|
12984
|
+
const parent = path13.dirname(dir);
|
|
12985
|
+
if (parent === dir) return null;
|
|
12986
|
+
dir = parent;
|
|
12987
|
+
}
|
|
12988
|
+
}
|
|
12989
|
+
var SkillSourceError = class extends Error {
|
|
12990
|
+
constructor(message, code) {
|
|
12991
|
+
super(message);
|
|
12992
|
+
this.code = code;
|
|
12993
|
+
}
|
|
12994
|
+
};
|
|
12995
|
+
function projectSkillSource(skill, projectDir) {
|
|
12996
|
+
const installed = findInstalledPackage(projectDir, skill.packageName);
|
|
12997
|
+
if (!installed) return null;
|
|
12998
|
+
const dir = path13.join(installed.dir, ...skill.packagePath.split("/"));
|
|
12999
|
+
if (!fs14.existsSync(path13.join(dir, "SKILL.md"))) {
|
|
13000
|
+
throw new SkillSourceError(
|
|
13001
|
+
`${skill.packageName} ${installed.version} does not include the ${skill.title} skill. Upgrade it: npm install ${skill.packageName}@latest`,
|
|
13002
|
+
"skill-missing"
|
|
13003
|
+
);
|
|
13004
|
+
}
|
|
13005
|
+
return { kind: "project", version: installed.version, dir, origin: installed.dir, cleanup: () => {
|
|
13006
|
+
} };
|
|
13007
|
+
}
|
|
13008
|
+
function registryBase() {
|
|
13009
|
+
return (process.env.ONE_SKILLS_REGISTRY || "https://registry.npmjs.org").replace(/\/+$/, "");
|
|
13010
|
+
}
|
|
13011
|
+
async function registrySkillSource(skill, fetchImpl = fetch) {
|
|
13012
|
+
const metaUrl = `${registryBase()}/${skill.packageName.replace("/", "%2f")}/latest`;
|
|
13013
|
+
let meta;
|
|
13014
|
+
try {
|
|
13015
|
+
const res = await fetchImpl(metaUrl, { headers: { accept: "application/json" } });
|
|
13016
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
13017
|
+
meta = await res.json();
|
|
13018
|
+
} catch (err) {
|
|
13019
|
+
throw new SkillSourceError(`Could not reach the npm registry for ${skill.packageName} (${err.message}).`, "registry-failed");
|
|
13020
|
+
}
|
|
13021
|
+
const version2 = meta.version;
|
|
13022
|
+
const tarball = meta.dist?.tarball;
|
|
13023
|
+
const integrity = meta.dist?.integrity;
|
|
13024
|
+
if (!version2 || !tarball || !integrity) {
|
|
13025
|
+
throw new SkillSourceError(`The npm registry returned no tarball for ${skill.packageName}.`, "registry-failed");
|
|
13026
|
+
}
|
|
13027
|
+
let bytes;
|
|
13028
|
+
try {
|
|
13029
|
+
const res = await fetchImpl(tarball);
|
|
13030
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
13031
|
+
bytes = Buffer.from(await res.arrayBuffer());
|
|
13032
|
+
} catch (err) {
|
|
13033
|
+
throw new SkillSourceError(`Could not download ${skill.packageName}@${version2} (${err.message}).`, "registry-failed");
|
|
13034
|
+
}
|
|
13035
|
+
if (!matchesIntegrity(bytes, integrity)) {
|
|
13036
|
+
throw new SkillSourceError(`${skill.packageName}@${version2} failed its integrity check; nothing was installed.`, "integrity");
|
|
13037
|
+
}
|
|
13038
|
+
const files = readTarEntries(zlib.gunzipSync(bytes), `package/${skill.packagePath}/`);
|
|
13039
|
+
if (!files.some((f) => f.path === "SKILL.md")) {
|
|
13040
|
+
throw new SkillSourceError(`${skill.packageName}@${version2} does not include the ${skill.title} skill.`, "not-in-package");
|
|
13041
|
+
}
|
|
13042
|
+
const tmp = fs14.mkdtempSync(path13.join(os3.tmpdir(), "one-skill-"));
|
|
13043
|
+
for (const file of files) {
|
|
13044
|
+
const dest = path13.join(tmp, ...file.path.split("/"));
|
|
13045
|
+
fs14.mkdirSync(path13.dirname(dest), { recursive: true });
|
|
13046
|
+
fs14.writeFileSync(dest, file.data);
|
|
13047
|
+
}
|
|
13048
|
+
return {
|
|
13049
|
+
kind: "registry",
|
|
13050
|
+
version: version2,
|
|
13051
|
+
dir: tmp,
|
|
13052
|
+
origin: tarball,
|
|
13053
|
+
cleanup: () => {
|
|
13054
|
+
try {
|
|
13055
|
+
fs14.rmSync(tmp, { recursive: true, force: true });
|
|
13056
|
+
} catch {
|
|
13057
|
+
}
|
|
13058
|
+
}
|
|
13059
|
+
};
|
|
13060
|
+
}
|
|
13061
|
+
function matchesIntegrity(bytes, integrity) {
|
|
13062
|
+
return integrity.split(/\s+/).some((entry) => {
|
|
13063
|
+
const dash = entry.indexOf("-");
|
|
13064
|
+
if (dash < 0) return false;
|
|
13065
|
+
const algorithm = entry.slice(0, dash);
|
|
13066
|
+
if (!["sha512", "sha384", "sha256"].includes(algorithm)) return false;
|
|
13067
|
+
return crypto2.createHash(algorithm).update(bytes).digest("base64") === entry.slice(dash + 1);
|
|
13068
|
+
});
|
|
13069
|
+
}
|
|
13070
|
+
function readTarEntries(tar, prefix) {
|
|
13071
|
+
const out = [];
|
|
13072
|
+
let offset = 0;
|
|
13073
|
+
let paxPath = null;
|
|
13074
|
+
const text5 = (start, length) => {
|
|
13075
|
+
const raw = tar.subarray(start, start + length);
|
|
13076
|
+
const end = raw.indexOf(0);
|
|
13077
|
+
return raw.subarray(0, end < 0 ? raw.length : end).toString("utf-8");
|
|
13078
|
+
};
|
|
13079
|
+
while (offset + 512 <= tar.length) {
|
|
13080
|
+
const header = tar.subarray(offset, offset + 512);
|
|
13081
|
+
if (header.every((b) => b === 0)) break;
|
|
13082
|
+
const size = parseInt(text5(offset + 124, 12).trim() || "0", 8);
|
|
13083
|
+
const type = String.fromCharCode(header[156] || 48);
|
|
13084
|
+
let name = text5(offset, 100);
|
|
13085
|
+
if (text5(offset + 257, 5) === "ustar") {
|
|
13086
|
+
const pre = text5(offset + 345, 155);
|
|
13087
|
+
if (pre) name = `${pre}/${name}`;
|
|
13088
|
+
}
|
|
13089
|
+
const body = tar.subarray(offset + 512, offset + 512 + size);
|
|
13090
|
+
if (type === "x") {
|
|
13091
|
+
const match = /\d+ path=([^\n]*)\n/.exec(body.toString("utf-8"));
|
|
13092
|
+
paxPath = match ? match[1] : null;
|
|
13093
|
+
} else {
|
|
13094
|
+
const full = paxPath ?? name;
|
|
13095
|
+
paxPath = null;
|
|
13096
|
+
if ((type === "0" || type === "\0") && full.startsWith(prefix)) {
|
|
13097
|
+
const rel = full.slice(prefix.length);
|
|
13098
|
+
const parts = rel.split("/");
|
|
13099
|
+
if (rel && !path13.isAbsolute(rel) && !parts.includes("..") && !parts.includes("")) {
|
|
13100
|
+
out.push({ path: rel, data: Buffer.from(body) });
|
|
13101
|
+
}
|
|
13102
|
+
}
|
|
13103
|
+
}
|
|
13104
|
+
offset += 512 + Math.ceil(size / 512) * 512;
|
|
13105
|
+
}
|
|
13106
|
+
return out;
|
|
13107
|
+
}
|
|
13108
|
+
var SKILL_STAMP = ".one-skill.json";
|
|
13109
|
+
function canonicalSkillDir(skill, plan) {
|
|
13110
|
+
return path13.join(plan.root, ...UNIVERSAL_PROJECT_DIR.split("/"), skill.dirName);
|
|
13111
|
+
}
|
|
13112
|
+
function readStamp(dir) {
|
|
13113
|
+
try {
|
|
13114
|
+
return JSON.parse(fs14.readFileSync(path13.join(dir, SKILL_STAMP), "utf-8"));
|
|
13115
|
+
} catch {
|
|
13116
|
+
return null;
|
|
13117
|
+
}
|
|
13118
|
+
}
|
|
13119
|
+
function resolveAgentFolders(plan) {
|
|
13120
|
+
const explicit = plan.agents.length > 0;
|
|
13121
|
+
const chosen = SKILL_AGENT_TARGETS.filter((agent) => {
|
|
13122
|
+
if (explicit) return plan.agents.includes(agent.id);
|
|
13123
|
+
if (plan.scope === "global") {
|
|
13124
|
+
return fs14.existsSync(path13.join(plan.root, path13.dirname(agent.homeDir)));
|
|
13125
|
+
}
|
|
13126
|
+
return agent.projectMarker === null || fs14.existsSync(path13.join(plan.root, agent.projectMarker));
|
|
13127
|
+
});
|
|
13128
|
+
const readers = [];
|
|
13129
|
+
const byDir = /* @__PURE__ */ new Map();
|
|
13130
|
+
for (const agent of chosen) {
|
|
13131
|
+
const dir = plan.scope === "project" ? agent.projectDir : agent.homeDir;
|
|
13132
|
+
if (dir === UNIVERSAL_PROJECT_DIR) {
|
|
13133
|
+
readers.push(agent.name);
|
|
13134
|
+
continue;
|
|
13135
|
+
}
|
|
13136
|
+
byDir.set(dir, [...byDir.get(dir) ?? [], agent.name]);
|
|
13137
|
+
}
|
|
13138
|
+
return { readers, folders: [...byDir].map(([dir, agents]) => ({ dir, agents })) };
|
|
13139
|
+
}
|
|
13140
|
+
function copyDir(src, dest) {
|
|
13141
|
+
fs14.mkdirSync(dest, { recursive: true });
|
|
13142
|
+
for (const entry of fs14.readdirSync(src, { withFileTypes: true })) {
|
|
13143
|
+
if (entry.name === SKILL_STAMP) continue;
|
|
13144
|
+
const from = path13.join(src, entry.name);
|
|
13145
|
+
const to = path13.join(dest, entry.name);
|
|
13146
|
+
if (entry.isDirectory()) copyDir(from, to);
|
|
13147
|
+
else fs14.copyFileSync(from, to);
|
|
13148
|
+
}
|
|
13149
|
+
}
|
|
13150
|
+
function removePath(target) {
|
|
13151
|
+
try {
|
|
13152
|
+
const stat = fs14.lstatSync(target);
|
|
13153
|
+
if (stat.isSymbolicLink()) fs14.unlinkSync(target);
|
|
13154
|
+
else fs14.rmSync(target, { recursive: true, force: true });
|
|
13155
|
+
} catch {
|
|
13156
|
+
}
|
|
13157
|
+
}
|
|
13158
|
+
function linkDir(target, linkPath) {
|
|
13159
|
+
removePath(linkPath);
|
|
13160
|
+
fs14.mkdirSync(path13.dirname(linkPath), { recursive: true });
|
|
13161
|
+
try {
|
|
13162
|
+
fs14.symlinkSync(path13.relative(path13.dirname(linkPath), target), linkPath, "dir");
|
|
13163
|
+
return "symlink";
|
|
13164
|
+
} catch {
|
|
13165
|
+
}
|
|
13166
|
+
try {
|
|
13167
|
+
fs14.symlinkSync(target, linkPath, "junction");
|
|
13168
|
+
return "junction";
|
|
13169
|
+
} catch {
|
|
13170
|
+
}
|
|
13171
|
+
copyDir(target, linkPath);
|
|
13172
|
+
return "copy";
|
|
13173
|
+
}
|
|
13174
|
+
function installSkill(skill, source, plan, cliVersion2) {
|
|
13175
|
+
const canonical = canonicalSkillDir(skill, plan);
|
|
13176
|
+
const previous = readStamp(canonical);
|
|
13177
|
+
const { readers, folders } = resolveAgentFolders(plan);
|
|
13178
|
+
const nextPaths = new Set(folders.map((f) => `${f.dir}/${skill.dirName}`));
|
|
13179
|
+
for (const link of previous?.links ?? []) {
|
|
13180
|
+
if (!nextPaths.has(toPosix(link.path))) removePath(fromStamp(plan.root, link.path));
|
|
13181
|
+
}
|
|
13182
|
+
removePath(canonical);
|
|
13183
|
+
copyDir(source.dir, canonical);
|
|
13184
|
+
const links = folders.map((folder) => {
|
|
13185
|
+
const rel = `${folder.dir}/${skill.dirName}`;
|
|
13186
|
+
return { path: rel, kind: linkDir(canonical, fromStamp(plan.root, rel)), agents: folder.agents };
|
|
13187
|
+
});
|
|
13188
|
+
const stamp = {
|
|
13189
|
+
skill: skill.name,
|
|
13190
|
+
package: skill.packageName,
|
|
13191
|
+
version: source.version,
|
|
13192
|
+
source: source.kind,
|
|
13193
|
+
scope: plan.scope,
|
|
13194
|
+
links,
|
|
13195
|
+
installedBy: `@withone/cli@${cliVersion2}`,
|
|
13196
|
+
installedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
13197
|
+
};
|
|
13198
|
+
fs14.writeFileSync(path13.join(canonical, SKILL_STAMP), JSON.stringify(stamp, null, 2) + "\n");
|
|
13199
|
+
return { skill, version: source.version, source: source.kind, origin: source.origin, scope: plan.scope, root: plan.root, canonical, readers, links };
|
|
13200
|
+
}
|
|
13201
|
+
function removeSkill(skill, plan) {
|
|
13202
|
+
const canonical = canonicalSkillDir(skill, plan);
|
|
13203
|
+
const stamp = readStamp(canonical);
|
|
13204
|
+
if (!stamp && !fs14.existsSync(path13.join(canonical, "SKILL.md"))) return { removed: false, paths: [] };
|
|
13205
|
+
const paths = [];
|
|
13206
|
+
for (const link of stamp?.links ?? []) {
|
|
13207
|
+
const full = fromStamp(plan.root, link.path);
|
|
13208
|
+
if (fs14.existsSync(full) || isDanglingLink(full)) {
|
|
13209
|
+
removePath(full);
|
|
13210
|
+
paths.push(full);
|
|
13211
|
+
}
|
|
13212
|
+
}
|
|
13213
|
+
removePath(canonical);
|
|
13214
|
+
paths.push(canonical);
|
|
13215
|
+
return { removed: true, paths };
|
|
13216
|
+
}
|
|
13217
|
+
function toPosix(p9) {
|
|
13218
|
+
return p9.split("\\").join("/");
|
|
13219
|
+
}
|
|
13220
|
+
function fromStamp(root, rel) {
|
|
13221
|
+
return path13.join(root, ...toPosix(rel).split("/"));
|
|
13222
|
+
}
|
|
13223
|
+
function isDanglingLink(p9) {
|
|
13224
|
+
try {
|
|
13225
|
+
return fs14.lstatSync(p9).isSymbolicLink();
|
|
13226
|
+
} catch {
|
|
13227
|
+
return false;
|
|
13228
|
+
}
|
|
13229
|
+
}
|
|
13230
|
+
function installedSkill(skill, plan) {
|
|
13231
|
+
const canonical = canonicalSkillDir(skill, plan);
|
|
13232
|
+
if (!fs14.existsSync(path13.join(canonical, "SKILL.md"))) return null;
|
|
13233
|
+
const stamp = readStamp(canonical);
|
|
13234
|
+
return { scope: plan.scope, root: plan.root, canonical, version: stamp?.version ?? null, source: stamp?.source ?? null, links: stamp?.links ?? [] };
|
|
13235
|
+
}
|
|
13236
|
+
function globalRoot() {
|
|
13237
|
+
return homeDir();
|
|
13238
|
+
}
|
|
13239
|
+
function refreshProjectSkills(cwd, cliVersion2) {
|
|
13240
|
+
const root = findProjectRoot(cwd);
|
|
13241
|
+
if (!root || path13.resolve(root) === path13.resolve(homeDir())) return [];
|
|
13242
|
+
const results = [];
|
|
13243
|
+
for (const skill of OPTIONAL_SKILLS) {
|
|
13244
|
+
const canonical = canonicalSkillDir(skill, { scope: "project", root });
|
|
13245
|
+
const stamp = readStamp(canonical);
|
|
13246
|
+
if (!stamp || stamp.scope !== "project" || stamp.source !== "project") continue;
|
|
13247
|
+
const installed = findInstalledPackage(root, skill.packageName);
|
|
13248
|
+
if (!installed || installed.version === stamp.version) continue;
|
|
13249
|
+
let source;
|
|
13250
|
+
try {
|
|
13251
|
+
source = projectSkillSource(skill, root);
|
|
13252
|
+
} catch {
|
|
13253
|
+
continue;
|
|
13254
|
+
}
|
|
13255
|
+
if (!source) continue;
|
|
13256
|
+
const agents = SKILL_AGENT_TARGETS.filter((a) => stamp.links.some((l) => l.agents.includes(a.name)) || a.projectDir === UNIVERSAL_PROJECT_DIR).map((a) => a.id);
|
|
13257
|
+
installSkill(skill, source, { scope: "project", root, agents }, cliVersion2);
|
|
13258
|
+
results.push({ skill: skill.name, from: stamp.version, to: source.version, root });
|
|
13259
|
+
}
|
|
13260
|
+
return results;
|
|
13261
|
+
}
|
|
13262
|
+
|
|
13263
|
+
// src/commands/skills.ts
|
|
13264
|
+
import path14 from "path";
|
|
13265
|
+
import pc16 from "picocolors";
|
|
13266
|
+
function requireSkill(name) {
|
|
13267
|
+
const skill = findOptionalSkill(name);
|
|
13268
|
+
if (!skill) {
|
|
13269
|
+
const known = OPTIONAL_SKILLS.map((s) => s.name).join(", ");
|
|
13270
|
+
error(`Unknown skill "${name}". Available: ${known}. The One skill itself is installed by \`one init\`.`);
|
|
13271
|
+
}
|
|
13272
|
+
return skill;
|
|
13273
|
+
}
|
|
13274
|
+
function parseAgents(raw) {
|
|
13275
|
+
if (!raw) return [];
|
|
13276
|
+
const ids = raw.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean);
|
|
13277
|
+
for (const id of ids) {
|
|
13278
|
+
if (!findAgentTarget(id)) {
|
|
13279
|
+
error(`Unknown agent "${id}". Use: ${SKILL_AGENT_TARGETS.map((a) => a.id).join(", ")}.`);
|
|
13280
|
+
}
|
|
13281
|
+
}
|
|
13282
|
+
return ids;
|
|
13283
|
+
}
|
|
13284
|
+
function resolvePlan(options) {
|
|
13285
|
+
const agents = parseAgents(options.agents);
|
|
13286
|
+
if (options.global) return { scope: "global", root: globalRoot(), agents };
|
|
13287
|
+
const root = findProjectRoot(process.cwd());
|
|
13288
|
+
if (!root || path14.resolve(root) === path14.resolve(homeDir())) {
|
|
13289
|
+
error("No project here: run this inside your app (a folder with package.json or .git), or pass --global.");
|
|
13290
|
+
}
|
|
13291
|
+
return { scope: "project", root, agents };
|
|
13292
|
+
}
|
|
13293
|
+
async function resolveSource(skill, plan) {
|
|
13294
|
+
try {
|
|
13295
|
+
const local = projectSkillSource(skill, plan.scope === "project" ? plan.root : process.cwd());
|
|
13296
|
+
if (local) return local;
|
|
13297
|
+
return await registrySkillSource(skill);
|
|
13298
|
+
} catch (err) {
|
|
13299
|
+
if (err instanceof SkillSourceError) error(err.message);
|
|
13300
|
+
throw err;
|
|
13301
|
+
}
|
|
13302
|
+
}
|
|
13303
|
+
function display(p9, root) {
|
|
13304
|
+
const rel = path14.relative(root, p9);
|
|
13305
|
+
return rel && !rel.startsWith("..") ? rel : p9;
|
|
13306
|
+
}
|
|
13307
|
+
function report(command, result, packageInProject) {
|
|
13308
|
+
const where = (p9) => display(p9, result.root);
|
|
13309
|
+
if (isAgentMode()) {
|
|
13310
|
+
json({
|
|
13311
|
+
command,
|
|
13312
|
+
skill: result.skill.name,
|
|
13313
|
+
name: result.skill.dirName,
|
|
13314
|
+
version: result.version,
|
|
13315
|
+
source: { kind: result.source, from: result.origin },
|
|
13316
|
+
scope: result.scope,
|
|
13317
|
+
root: result.root,
|
|
13318
|
+
installedTo: [
|
|
13319
|
+
{ path: result.canonical, kind: "folder", agents: result.readers },
|
|
13320
|
+
...result.links.map((l) => ({ path: path14.join(result.root, ...l.path.split("/")), kind: l.kind, agents: l.agents }))
|
|
13321
|
+
],
|
|
13322
|
+
next: nextSteps(result, packageInProject)
|
|
13323
|
+
});
|
|
13324
|
+
return;
|
|
13325
|
+
}
|
|
13326
|
+
const scopeLabel2 = result.scope === "project" ? "this project" : "every project on this machine";
|
|
13327
|
+
console.log();
|
|
13328
|
+
console.log(` ${pc16.green("\u2713")} ${pc16.bold(`${result.skill.title} skill ${result.version}`)} installed for ${scopeLabel2}`);
|
|
13329
|
+
console.log();
|
|
13330
|
+
const from = result.source === "project" ? `${where(result.origin)} ${pc16.dim("(the version your code uses)")}` : `npm ${pc16.dim(result.scope === "project" ? `(latest ${result.skill.packageName}; not installed in this project yet)` : `(latest ${result.skill.packageName})`)}`;
|
|
13331
|
+
console.log(` ${pc16.dim("From")} ${from}`);
|
|
13332
|
+
const rows = [
|
|
13333
|
+
{ path: where(result.canonical), agents: result.readers },
|
|
13334
|
+
...result.links.map((l) => ({ path: `${l.path}${l.kind === "copy" ? pc16.dim(" (copy)") : ""}`, agents: l.agents }))
|
|
13335
|
+
];
|
|
13336
|
+
rows.forEach((row, i) => {
|
|
13337
|
+
const agents = row.agents.length ? pc16.dim(row.agents.join(", ")) : pc16.dim("shared copy the links point to");
|
|
13338
|
+
console.log(` ${pc16.dim(i === 0 ? "To " : " ")} ${row.path} ${agents}`);
|
|
13339
|
+
});
|
|
13340
|
+
console.log();
|
|
13341
|
+
console.log(` ${pc16.bold("Next")}`);
|
|
13342
|
+
nextSteps(result, packageInProject).forEach((step, i) => console.log(` ${i + 1}. ${step}`));
|
|
13343
|
+
console.log();
|
|
13344
|
+
}
|
|
13345
|
+
function nextSteps(result, packageInProject) {
|
|
13346
|
+
const steps = [];
|
|
13347
|
+
if (result.scope === "project" && !packageInProject) steps.push(`Install the SDK: npm install ${result.skill.packageName}`);
|
|
13348
|
+
steps.push(`Ask your agent: "Add ${result.skill.title} to this app." The skill tells it every step.`);
|
|
13349
|
+
steps.push("Set the secrets it names in your server environment yourself; never paste them into a chat.");
|
|
13350
|
+
if (result.scope === "project") {
|
|
13351
|
+
const folders = [`${UNIVERSAL_DIR}/${result.skill.dirName}`, ...result.links.map((l) => l.path)];
|
|
13352
|
+
steps.push(`Commit ${folders.join(" and ")} so your team's agents share it. Any \`one\` command here refreshes it when ${result.skill.packageName} is upgraded.`);
|
|
13353
|
+
} else {
|
|
13354
|
+
steps.push(`Refresh it after a new ${result.skill.packageName} release: one skills update ${result.skill.name} --global`);
|
|
13355
|
+
}
|
|
13356
|
+
return steps;
|
|
13357
|
+
}
|
|
13358
|
+
var UNIVERSAL_DIR = ".agents/skills";
|
|
13359
|
+
async function skillsAddCommand(name, options) {
|
|
13360
|
+
const skill = requireSkill(name);
|
|
13361
|
+
const plan = resolvePlan(options);
|
|
13362
|
+
const source = await resolveSource(skill, plan);
|
|
13363
|
+
try {
|
|
13364
|
+
const result = installSkill(skill, source, plan, getCurrentVersion());
|
|
13365
|
+
const packageInProject = plan.scope === "project" && findInstalledPackage(plan.root, skill.packageName) !== null;
|
|
13366
|
+
report("skills add", result, packageInProject);
|
|
13367
|
+
} finally {
|
|
13368
|
+
source.cleanup();
|
|
13369
|
+
}
|
|
13370
|
+
}
|
|
13371
|
+
async function skillsUpdateCommand(name, options) {
|
|
13372
|
+
const skills2 = name ? [requireSkill(name)] : OPTIONAL_SKILLS;
|
|
13373
|
+
const plan = resolvePlan(options);
|
|
13374
|
+
const updated = [];
|
|
13375
|
+
const skipped = [];
|
|
13376
|
+
for (const skill of skills2) {
|
|
13377
|
+
const current = installedSkill(skill, plan);
|
|
13378
|
+
if (!current) {
|
|
13379
|
+
skipped.push(skill.name);
|
|
13380
|
+
continue;
|
|
13381
|
+
}
|
|
13382
|
+
const agents = plan.agents.length ? plan.agents : SKILL_AGENT_TARGETS.filter((a) => current.links.some((l) => l.agents.includes(a.name)) || plan.scope === "project" && a.projectDir === UNIVERSAL_DIR).map((a) => a.id);
|
|
13383
|
+
const source = await resolveSource(skill, plan);
|
|
13384
|
+
try {
|
|
13385
|
+
updated.push(installSkill(skill, source, { ...plan, agents }, getCurrentVersion()));
|
|
13386
|
+
} finally {
|
|
13387
|
+
source.cleanup();
|
|
13388
|
+
}
|
|
13389
|
+
}
|
|
13390
|
+
if (name && updated.length === 0) error(`${skills2[0].title} skill is not installed here. Add it: one skills add ${skills2[0].name}${plan.scope === "global" ? " --global" : ""}`);
|
|
13391
|
+
if (isAgentMode()) {
|
|
13392
|
+
json({
|
|
13393
|
+
command: "skills update",
|
|
13394
|
+
scope: plan.scope,
|
|
13395
|
+
updated: updated.map((r) => ({ skill: r.skill.name, version: r.version, source: r.source, path: r.canonical })),
|
|
13396
|
+
notInstalled: skipped
|
|
13397
|
+
});
|
|
13398
|
+
return;
|
|
13399
|
+
}
|
|
13400
|
+
if (updated.length === 0) {
|
|
13401
|
+
console.log("No optional skills are installed here. See: one skills list");
|
|
13402
|
+
return;
|
|
13403
|
+
}
|
|
13404
|
+
for (const r of updated) console.log(` ${pc16.green("\u2713")} ${r.skill.title} skill ${r.version} ${pc16.dim(display(r.canonical, r.root))}`);
|
|
13405
|
+
}
|
|
13406
|
+
async function skillsRemoveCommand(name, options) {
|
|
13407
|
+
const skill = requireSkill(name);
|
|
13408
|
+
const plan = resolvePlan(options);
|
|
13409
|
+
const result = removeSkill(skill, plan);
|
|
13410
|
+
if (isAgentMode()) {
|
|
13411
|
+
json({ command: "skills remove", skill: skill.name, scope: plan.scope, removed: result.removed, paths: result.paths });
|
|
13412
|
+
return;
|
|
13413
|
+
}
|
|
13414
|
+
if (!result.removed) {
|
|
13415
|
+
console.log(`${skill.title} skill is not installed ${plan.scope === "global" ? "globally" : "in this project"}.`);
|
|
13416
|
+
return;
|
|
13417
|
+
}
|
|
13418
|
+
console.log(` ${pc16.green("\u2713")} Removed the ${skill.title} skill`);
|
|
13419
|
+
for (const p9 of result.paths) console.log(` ${pc16.dim(display(p9, plan.root))}`);
|
|
13420
|
+
}
|
|
13421
|
+
async function skillsListCommand() {
|
|
13422
|
+
const projectRoot = findProjectRoot(process.cwd());
|
|
13423
|
+
const inProject = projectRoot && path14.resolve(projectRoot) !== path14.resolve(homeDir()) ? projectRoot : null;
|
|
13424
|
+
const optional = OPTIONAL_SKILLS.map((skill) => {
|
|
13425
|
+
const project = inProject ? installedSkill(skill, { scope: "project", root: inProject }) : null;
|
|
13426
|
+
const global = installedSkill(skill, { scope: "global", root: globalRoot() });
|
|
13427
|
+
const pkg = inProject ? findInstalledPackage(inProject, skill.packageName) : null;
|
|
13428
|
+
return {
|
|
13429
|
+
skill: skill.name,
|
|
13430
|
+
name: skill.dirName,
|
|
13431
|
+
title: skill.title,
|
|
13432
|
+
description: skill.description,
|
|
13433
|
+
package: skill.packageName,
|
|
13434
|
+
packageInProject: pkg?.version ?? null,
|
|
13435
|
+
project: project ? { version: project.version, path: project.canonical, upToDate: !pkg || project.version === pkg.version } : null,
|
|
13436
|
+
global: global ? { version: global.version, path: global.canonical } : null
|
|
13437
|
+
};
|
|
13438
|
+
});
|
|
13439
|
+
const oneSkill = {
|
|
13440
|
+
skill: "one",
|
|
13441
|
+
title: "One CLI",
|
|
13442
|
+
managedBy: "one init",
|
|
13443
|
+
installed: isSkillInstalled(),
|
|
13444
|
+
version: readInstalledSkillVersion()
|
|
13445
|
+
};
|
|
13446
|
+
if (isAgentMode()) {
|
|
13447
|
+
json({ command: "skills list", project: inProject, skills: [oneSkill, ...optional] });
|
|
13448
|
+
return;
|
|
13449
|
+
}
|
|
13450
|
+
console.log();
|
|
13451
|
+
console.log(` ${pc16.bold("one")} ${oneSkill.installed ? pc16.green(`installed ${oneSkill.version ?? ""}`.trim()) : pc16.yellow("not installed")} ${pc16.dim("managed by one init")}`);
|
|
13452
|
+
for (const s of optional) {
|
|
13453
|
+
const state = s.project ? pc16.green(`project ${s.project.version ?? ""}`.trim()) + (s.project.upToDate ? "" : pc16.yellow(` (package is ${s.packageInProject}: run one skills update ${s.skill})`)) : s.global ? pc16.green(`global ${s.global.version ?? ""}`.trim()) : pc16.dim(`not installed \u2014 one skills add ${s.skill}`);
|
|
13454
|
+
console.log(` ${pc16.bold(s.skill.padEnd(8))} ${state}`);
|
|
13455
|
+
console.log(` ${" ".repeat(8)} ${pc16.dim(s.description)}`);
|
|
13456
|
+
}
|
|
13457
|
+
console.log();
|
|
13458
|
+
}
|
|
13459
|
+
|
|
12927
13460
|
// src/cli.ts
|
|
12928
13461
|
silenceWarningsInAgentMode();
|
|
12929
13462
|
var require4 = createRequire3(import.meta.url);
|
|
@@ -12946,6 +13479,12 @@ program.name("one").option("--agent", "Machine-readable JSON output (no colors,
|
|
|
12946
13479
|
3. one actions execute <p> <id> <key> Execute the action
|
|
12947
13480
|
one actions load <id> --section <s> More of an action's docs: a section a digest left out, --full, or --toc
|
|
12948
13481
|
|
|
13482
|
+
Skills for your coding agent:
|
|
13483
|
+
one skills list The One skill and the optional ones (installed or not)
|
|
13484
|
+
one skills add connect Add the One Connect skill to this project (--global for every project)
|
|
13485
|
+
one skills update [connect] Re-copy from the installed @withone/connect after an upgrade
|
|
13486
|
+
one skills remove connect Remove it
|
|
13487
|
+
|
|
12949
13488
|
Guide:
|
|
12950
13489
|
one guide [topic] Full CLI guide (topics: overview, actions, workflows, memory, sync, all)
|
|
12951
13490
|
|
|
@@ -13019,6 +13558,12 @@ program.hook("preAction", (thisCommand, actionCommand) => {
|
|
|
13019
13558
|
} catch {
|
|
13020
13559
|
}
|
|
13021
13560
|
}
|
|
13561
|
+
if (commandName !== "skills") {
|
|
13562
|
+
try {
|
|
13563
|
+
refreshProjectSkills(process.cwd(), getCurrentVersion());
|
|
13564
|
+
} catch {
|
|
13565
|
+
}
|
|
13566
|
+
}
|
|
13022
13567
|
});
|
|
13023
13568
|
program.hook("postAction", async () => {
|
|
13024
13569
|
await closeBackendIfCached();
|
|
@@ -13041,6 +13586,19 @@ program.command("login").description("Authenticate with One via browser").action
|
|
|
13041
13586
|
program.command("logout").description("Clear local credentials").action(async () => {
|
|
13042
13587
|
await logoutCommand();
|
|
13043
13588
|
});
|
|
13589
|
+
var skills = program.command("skills").description("Optional skills for your coding agent, such as One Connect (the One skill itself comes from one init)");
|
|
13590
|
+
skills.command("list").description("Show the One skill and each optional skill, with where it is installed").action(async () => {
|
|
13591
|
+
await skillsListCommand();
|
|
13592
|
+
});
|
|
13593
|
+
skills.command("add <name>").description("Install an optional skill (connect) into this project, from the SDK version it uses").option("-g, --global", "Install for every project on this machine instead").option("--agents <ids>", "Comma-separated agents to link: claude-code, codex, cursor, amp, opencode, windsurf, kiro, goose, roo").action(async (name, options) => {
|
|
13594
|
+
await skillsAddCommand(name, options);
|
|
13595
|
+
});
|
|
13596
|
+
skills.command("update [name]").description("Re-copy installed optional skills from their source (all when no name is given)").option("-g, --global", "Update the global install").option("--agents <ids>", "Change which agents are linked").action(async (name, options) => {
|
|
13597
|
+
await skillsUpdateCommand(name, options);
|
|
13598
|
+
});
|
|
13599
|
+
skills.command("remove <name>").alias("rm").description("Remove an optional skill and the agent folders that point at it").option("-g, --global", "Remove the global install").action(async (name, options) => {
|
|
13600
|
+
await skillsRemoveCommand(name, options);
|
|
13601
|
+
});
|
|
13044
13602
|
var config = program.command("config").description("Configure the CLI (access control, skills, ...)").action(async () => {
|
|
13045
13603
|
await configCommand();
|
|
13046
13604
|
});
|
|
@@ -13140,8 +13698,8 @@ config.command("reset").description("Remove the project config for the current d
|
|
|
13140
13698
|
return;
|
|
13141
13699
|
}
|
|
13142
13700
|
}
|
|
13143
|
-
const
|
|
13144
|
-
|
|
13701
|
+
const fs16 = await import("fs");
|
|
13702
|
+
fs16.unlinkSync(globalPath);
|
|
13145
13703
|
if (isAgentMode()) {
|
|
13146
13704
|
json({ deleted: true, scope: "global" });
|
|
13147
13705
|
} else {
|
|
@@ -13158,15 +13716,15 @@ config.command("reset").description("Remove the project config for the current d
|
|
|
13158
13716
|
}
|
|
13159
13717
|
return;
|
|
13160
13718
|
}
|
|
13161
|
-
const
|
|
13162
|
-
const configContent =
|
|
13163
|
-
|
|
13719
|
+
const fs15 = await import("fs");
|
|
13720
|
+
const configContent = fs15.readFileSync(resolved.path, "utf-8");
|
|
13721
|
+
fs15.unlinkSync(resolved.path);
|
|
13164
13722
|
const next = resolveConfig();
|
|
13165
|
-
|
|
13166
|
-
|
|
13723
|
+
fs15.mkdirSync(path15.dirname(resolved.path), { recursive: true });
|
|
13724
|
+
fs15.writeFileSync(resolved.path, configContent);
|
|
13167
13725
|
let fallbackLabel;
|
|
13168
13726
|
if (next.scope === "project") {
|
|
13169
|
-
fallbackLabel = `parent project config (${
|
|
13727
|
+
fallbackLabel = `parent project config (${path15.basename(next.projectRoot)})`;
|
|
13170
13728
|
} else if (next.scope === "global") {
|
|
13171
13729
|
fallbackLabel = "global config";
|
|
13172
13730
|
} else {
|
|
@@ -13175,7 +13733,7 @@ config.command("reset").description("Remove the project config for the current d
|
|
|
13175
13733
|
if (!isAgentMode()) {
|
|
13176
13734
|
const p9 = await import("@clack/prompts");
|
|
13177
13735
|
const confirmed = await p9.confirm({
|
|
13178
|
-
message: `Delete project config for ${
|
|
13736
|
+
message: `Delete project config for ${path15.basename(resolved.projectRoot)}? Will fall back to ${fallbackLabel}.`,
|
|
13179
13737
|
initialValue: false
|
|
13180
13738
|
});
|
|
13181
13739
|
if (p9.isCancel(confirmed) || !confirmed) {
|
|
@@ -13183,9 +13741,9 @@ config.command("reset").description("Remove the project config for the current d
|
|
|
13183
13741
|
return;
|
|
13184
13742
|
}
|
|
13185
13743
|
}
|
|
13186
|
-
|
|
13744
|
+
fs15.unlinkSync(resolved.path);
|
|
13187
13745
|
try {
|
|
13188
|
-
|
|
13746
|
+
fs15.rmdirSync(path15.dirname(resolved.path));
|
|
13189
13747
|
} catch {
|
|
13190
13748
|
}
|
|
13191
13749
|
if (isAgentMode()) {
|
|
@@ -13348,22 +13906,22 @@ program.command("whoami").description("Show the user, organization, and project
|
|
|
13348
13906
|
});
|
|
13349
13907
|
return;
|
|
13350
13908
|
}
|
|
13351
|
-
const
|
|
13909
|
+
const pc17 = (await import("picocolors")).default;
|
|
13352
13910
|
const contextParts = [];
|
|
13353
13911
|
if (whoami.organization) contextParts.push(whoami.organization.name);
|
|
13354
13912
|
if (whoami.project) contextParts.push(whoami.project.name);
|
|
13355
13913
|
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
13356
|
-
const envLabel = env === "test" ?
|
|
13357
|
-
const configLabel = configScope === "project" ?
|
|
13914
|
+
const envLabel = env === "test" ? pc17.yellow("test") : pc17.green("live");
|
|
13915
|
+
const configLabel = configScope === "project" ? pc17.cyan("project config") : pc17.magenta("global config");
|
|
13358
13916
|
console.log();
|
|
13359
|
-
console.log(` ${
|
|
13360
|
-
console.log(` ${whoami.user.name} ${
|
|
13361
|
-
if (keyName) console.log(` ${
|
|
13362
|
-
if (whoami.organization) console.log(` ${
|
|
13363
|
-
if (whoami.project) console.log(` ${
|
|
13917
|
+
console.log(` ${pc17.bold(scopeDisplay)} ${pc17.dim("\xB7")} ${envLabel}`);
|
|
13918
|
+
console.log(` ${whoami.user.name} ${pc17.dim(`(${whoami.user.email})`)}`);
|
|
13919
|
+
if (keyName) console.log(` ${pc17.dim("Key:")} ${keyName}`);
|
|
13920
|
+
if (whoami.organization) console.log(` ${pc17.dim("Org:")} ${whoami.organization.name} ${pc17.dim(`(${whoami.organization.id})`)}`);
|
|
13921
|
+
if (whoami.project) console.log(` ${pc17.dim("Project:")} ${whoami.project.name} ${pc17.dim(`(${whoami.project.id})`)}`);
|
|
13364
13922
|
console.log();
|
|
13365
|
-
console.log(` ${
|
|
13366
|
-
console.log(` ${
|
|
13923
|
+
console.log(` ${pc17.dim("Using")} ${configLabel}`);
|
|
13924
|
+
console.log(` ${pc17.dim("API:")} ${apiBase}`);
|
|
13367
13925
|
console.log();
|
|
13368
13926
|
});
|
|
13369
13927
|
program.command("add [platform]").description("Shortcut for: connection add").option("--tag <name>", "Tag the new connection (disambiguates multiple connections per platform in sync/flow profiles)").action(async (platform, options) => {
|