@withone/cli 1.55.2 → 1.55.4
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 +4 -0
- package/dist/index.js +606 -416
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -155,7 +155,7 @@ import { Command } from "commander";
|
|
|
155
155
|
|
|
156
156
|
// src/commands/init.ts
|
|
157
157
|
import * as p3 from "@clack/prompts";
|
|
158
|
-
import
|
|
158
|
+
import pc3 from "picocolors";
|
|
159
159
|
import fs3 from "fs";
|
|
160
160
|
import path4 from "path";
|
|
161
161
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
@@ -654,8 +654,9 @@ import { fileURLToPath as fileURLToPath2 } from "url";
|
|
|
654
654
|
|
|
655
655
|
// src/commands/update.ts
|
|
656
656
|
import { spawn } from "child_process";
|
|
657
|
-
import { readFileSync, writeFileSync, mkdirSync, rmSync } from "fs";
|
|
658
|
-
import { join } from "path";
|
|
657
|
+
import { existsSync as existsSync2, readFileSync, writeFileSync, mkdirSync, rmSync, openSync, closeSync } from "fs";
|
|
658
|
+
import { delimiter, dirname, join } from "path";
|
|
659
|
+
import pc2 from "picocolors";
|
|
659
660
|
|
|
660
661
|
// src/lib/version.ts
|
|
661
662
|
import { createRequire } from "module";
|
|
@@ -688,9 +689,13 @@ var currentVersion = cliVersion();
|
|
|
688
689
|
var ONE_DIR = () => join(homeDir(), ".one");
|
|
689
690
|
var CACHE_PATH = () => join(ONE_DIR(), "update-check.json");
|
|
690
691
|
var LOCK_PATH = () => join(ONE_DIR(), "auto-update.lock");
|
|
692
|
+
var STATE_PATH = () => join(ONE_DIR(), "auto-update-state.json");
|
|
693
|
+
var LOG_PATH = () => join(ONE_DIR(), "auto-update.log");
|
|
691
694
|
var CHECK_INTERVAL_MS = 4 * 60 * 60 * 1e3;
|
|
692
695
|
var AGE_GATE_MS = 30 * 60 * 1e3;
|
|
693
696
|
var LOCK_TTL_MS = 10 * 60 * 1e3;
|
|
697
|
+
var FAILED_UPDATE_NOTICE_THRESHOLD = 3;
|
|
698
|
+
var FAILED_UPDATE_NOTICE_INTERVAL_MS = 24 * 60 * 60 * 1e3;
|
|
694
699
|
async function fetchLatestVersionInfo() {
|
|
695
700
|
try {
|
|
696
701
|
const res = await fetch("https://registry.npmjs.org/@withone/cli");
|
|
@@ -734,6 +739,22 @@ async function checkLatestVersionCached() {
|
|
|
734
739
|
function getCurrentVersion() {
|
|
735
740
|
return currentVersion;
|
|
736
741
|
}
|
|
742
|
+
function resolveNpmBin(nodeExecPath = process.execPath) {
|
|
743
|
+
const name = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
744
|
+
try {
|
|
745
|
+
const sibling = join(dirname(nodeExecPath), name);
|
|
746
|
+
if (existsSync2(sibling)) return sibling;
|
|
747
|
+
} catch {
|
|
748
|
+
}
|
|
749
|
+
return name;
|
|
750
|
+
}
|
|
751
|
+
function updateChildEnv(env = process.env, nodeExecPath = process.execPath) {
|
|
752
|
+
const nodeDir = dirname(nodeExecPath);
|
|
753
|
+
const key = Object.keys(env).find((k) => k.toUpperCase() === "PATH") ?? "PATH";
|
|
754
|
+
const parts = (env[key] ?? "").split(delimiter).filter(Boolean);
|
|
755
|
+
if (!parts.includes(nodeDir)) parts.unshift(nodeDir);
|
|
756
|
+
return { ...env, [key]: parts.join(delimiter) };
|
|
757
|
+
}
|
|
737
758
|
async function updateCommand() {
|
|
738
759
|
const s = createSpinner();
|
|
739
760
|
s.start("Checking for updates...");
|
|
@@ -753,23 +774,26 @@ async function updateCommand() {
|
|
|
753
774
|
}
|
|
754
775
|
s.stop(`Update available: v${currentVersion} \u2192 v${latestVersion}`);
|
|
755
776
|
console.log(`Updating @withone/cli: v${currentVersion} \u2192 v${latestVersion}...`);
|
|
777
|
+
const npmBin = resolveNpmBin();
|
|
778
|
+
const env = updateChildEnv();
|
|
779
|
+
const useShell = process.platform === "win32";
|
|
780
|
+
const command = useShell ? `"${npmBin}"` : npmBin;
|
|
756
781
|
await new Promise((resolve) => {
|
|
757
|
-
const child = spawn(
|
|
758
|
-
stdio: "ignore",
|
|
759
|
-
shell: true
|
|
760
|
-
});
|
|
782
|
+
const child = spawn(command, ["cache", "clean", "--force"], { stdio: "ignore", shell: useShell, env });
|
|
761
783
|
child.on("close", () => resolve());
|
|
762
784
|
child.on("error", () => resolve());
|
|
763
785
|
});
|
|
764
786
|
const code = await new Promise((resolve) => {
|
|
765
|
-
const child = spawn(
|
|
787
|
+
const child = spawn(command, ["install", "-g", `@withone/cli@${latestVersion}`, "--force"], {
|
|
766
788
|
stdio: isAgentMode() ? "pipe" : "inherit",
|
|
767
|
-
shell:
|
|
789
|
+
shell: useShell,
|
|
790
|
+
env
|
|
768
791
|
});
|
|
769
792
|
child.on("close", resolve);
|
|
770
793
|
child.on("error", () => resolve(1));
|
|
771
794
|
});
|
|
772
795
|
if (code === 0) {
|
|
796
|
+
clearAutoUpdateState();
|
|
773
797
|
if (isAgentMode()) {
|
|
774
798
|
json({ current: currentVersion, latest: latestVersion, updated: true, message: "Updated successfully" });
|
|
775
799
|
} else {
|
|
@@ -791,15 +815,74 @@ function isAutoUpdateDisabled() {
|
|
|
791
815
|
const v = process.env.ONE_NO_AUTO_UPDATE ?? process.env.ONE_DISABLE_AUTO_UPDATE;
|
|
792
816
|
return v === "1" || v === "true";
|
|
793
817
|
}
|
|
818
|
+
function readAutoUpdateState() {
|
|
819
|
+
try {
|
|
820
|
+
const parsed = JSON.parse(readFileSync(STATE_PATH(), "utf8"));
|
|
821
|
+
return { ...parsed, failures: typeof parsed.failures === "number" ? parsed.failures : 0 };
|
|
822
|
+
} catch {
|
|
823
|
+
return { failures: 0 };
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
function writeAutoUpdateState(state) {
|
|
827
|
+
try {
|
|
828
|
+
mkdirSync(ONE_DIR(), { recursive: true });
|
|
829
|
+
writeFileSync(STATE_PATH(), JSON.stringify(state), { mode: 384 });
|
|
830
|
+
} catch {
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
function clearAutoUpdateState() {
|
|
834
|
+
try {
|
|
835
|
+
rmSync(STATE_PATH(), { force: true });
|
|
836
|
+
} catch {
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
function reconcileAbandonedAttempt(lock) {
|
|
840
|
+
const target = lock.targetVersion;
|
|
841
|
+
if (!target) return;
|
|
842
|
+
if (!isNewerVersion(target, currentVersion)) {
|
|
843
|
+
clearAutoUpdateState();
|
|
844
|
+
return;
|
|
845
|
+
}
|
|
846
|
+
const state = readAutoUpdateState();
|
|
847
|
+
writeAutoUpdateState({
|
|
848
|
+
...state,
|
|
849
|
+
failures: state.failures + 1,
|
|
850
|
+
lastError: `install of v${target} never completed (npm may not be on this environment's PATH)`
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
function shouldWarnAboutFailedUpdates(state, now = Date.now()) {
|
|
854
|
+
if (state.failures < FAILED_UPDATE_NOTICE_THRESHOLD) return false;
|
|
855
|
+
if (state.lastNoticeAt && now - state.lastNoticeAt < FAILED_UPDATE_NOTICE_INTERVAL_MS) return false;
|
|
856
|
+
return true;
|
|
857
|
+
}
|
|
858
|
+
function maybeWarnAboutFailedUpdates(targetVersion) {
|
|
859
|
+
const state = readAutoUpdateState();
|
|
860
|
+
if (!shouldWarnAboutFailedUpdates(state)) return;
|
|
861
|
+
writeAutoUpdateState({ ...state, lastNoticeAt: Date.now() });
|
|
862
|
+
process.stderr.write(
|
|
863
|
+
pc2.yellow(
|
|
864
|
+
`One CLI could not auto-update (v${currentVersion} \u2192 v${targetVersion}) after ${state.failures} attempts.
|
|
865
|
+
`
|
|
866
|
+
) + pc2.dim(
|
|
867
|
+
`Update manually with: npm install -g @withone/cli@latest
|
|
868
|
+
Details: ${LOG_PATH()}. Silence this with ONE_NO_AUTO_UPDATE=1.
|
|
869
|
+
`
|
|
870
|
+
)
|
|
871
|
+
);
|
|
872
|
+
}
|
|
794
873
|
function acquireUpdateLock(targetVersion) {
|
|
795
874
|
try {
|
|
796
875
|
mkdirSync(ONE_DIR(), { recursive: true });
|
|
797
876
|
} catch {
|
|
798
877
|
}
|
|
878
|
+
let abandoned = null;
|
|
799
879
|
try {
|
|
800
880
|
const lock = JSON.parse(readFileSync(LOCK_PATH(), "utf8"));
|
|
801
881
|
const startedAt = typeof lock.startedAt === "number" ? lock.startedAt : 0;
|
|
802
|
-
if (Date.now() - startedAt < LOCK_TTL_MS)
|
|
882
|
+
if (Date.now() - startedAt < LOCK_TTL_MS) {
|
|
883
|
+
return { acquired: false, abandoned: null };
|
|
884
|
+
}
|
|
885
|
+
abandoned = { targetVersion: lock.targetVersion };
|
|
803
886
|
rmSync(LOCK_PATH(), { force: true });
|
|
804
887
|
} catch {
|
|
805
888
|
}
|
|
@@ -810,9 +893,23 @@ function acquireUpdateLock(targetVersion) {
|
|
|
810
893
|
{ flag: "wx" }
|
|
811
894
|
// fail if another invocation created it first
|
|
812
895
|
);
|
|
813
|
-
return true;
|
|
896
|
+
return { acquired: true, abandoned };
|
|
814
897
|
} catch {
|
|
815
|
-
return false;
|
|
898
|
+
return { acquired: false, abandoned };
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
function releaseUpdateLock() {
|
|
902
|
+
try {
|
|
903
|
+
rmSync(LOCK_PATH(), { force: true });
|
|
904
|
+
} catch {
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
function installLogTarget() {
|
|
908
|
+
try {
|
|
909
|
+
mkdirSync(ONE_DIR(), { recursive: true });
|
|
910
|
+
return openSync(LOG_PATH(), "a", 384);
|
|
911
|
+
} catch {
|
|
912
|
+
return "ignore";
|
|
816
913
|
}
|
|
817
914
|
}
|
|
818
915
|
function autoUpdate(targetVersion, publishedAt) {
|
|
@@ -821,17 +918,40 @@ function autoUpdate(targetVersion, publishedAt) {
|
|
|
821
918
|
const age = Date.now() - new Date(publishedAt).getTime();
|
|
822
919
|
if (age < AGE_GATE_MS) return;
|
|
823
920
|
}
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
921
|
+
const claim = acquireUpdateLock(targetVersion);
|
|
922
|
+
if (claim.abandoned) {
|
|
923
|
+
reconcileAbandonedAttempt(claim.abandoned);
|
|
924
|
+
maybeWarnAboutFailedUpdates(targetVersion);
|
|
925
|
+
}
|
|
926
|
+
if (!claim.acquired) return;
|
|
927
|
+
const npmBin = resolveNpmBin();
|
|
928
|
+
const useShell = process.platform === "win32";
|
|
929
|
+
const log5 = installLogTarget();
|
|
930
|
+
const child = spawn(
|
|
931
|
+
useShell ? `"${npmBin}"` : npmBin,
|
|
932
|
+
["install", "-g", `@withone/cli@${targetVersion}`],
|
|
933
|
+
{
|
|
934
|
+
detached: true,
|
|
935
|
+
// Keep npm's own diagnostics: when an install does fail, the reason is on
|
|
936
|
+
// disk instead of nowhere.
|
|
937
|
+
stdio: log5 === "ignore" ? "ignore" : ["ignore", log5, log5],
|
|
938
|
+
shell: useShell,
|
|
939
|
+
env: updateChildEnv()
|
|
940
|
+
}
|
|
941
|
+
);
|
|
942
|
+
if (log5 !== "ignore") {
|
|
831
943
|
try {
|
|
832
|
-
|
|
944
|
+
closeSync(log5);
|
|
833
945
|
} catch {
|
|
834
946
|
}
|
|
947
|
+
}
|
|
948
|
+
child.on("error", (err) => {
|
|
949
|
+
writeAutoUpdateState({ ...readAutoUpdateState(), lastError: err.message });
|
|
950
|
+
releaseUpdateLock();
|
|
951
|
+
});
|
|
952
|
+
child.on("exit", (code) => {
|
|
953
|
+
if (code === 0) clearAutoUpdateState();
|
|
954
|
+
releaseUpdateLock();
|
|
835
955
|
});
|
|
836
956
|
child.unref();
|
|
837
957
|
}
|
|
@@ -1063,25 +1183,25 @@ async function loginCommand() {
|
|
|
1063
1183
|
let targetScope = "global";
|
|
1064
1184
|
const existingKey = getApiKey();
|
|
1065
1185
|
if (existingKey) {
|
|
1066
|
-
const
|
|
1186
|
+
const pc17 = (await import("picocolors")).default;
|
|
1067
1187
|
const resolved2 = resolveConfig();
|
|
1068
1188
|
const whoami2 = resolved2.config?.whoami;
|
|
1069
1189
|
const env2 = getEnvFromApiKey(existingKey);
|
|
1070
|
-
const envLabel2 = env2 === "test" ?
|
|
1071
|
-
const currentScope = resolved2.scope === "project" ?
|
|
1190
|
+
const envLabel2 = env2 === "test" ? pc17.yellow("test") : pc17.green("live");
|
|
1191
|
+
const currentScope = resolved2.scope === "project" ? pc17.cyan("local config") : pc17.magenta("global config");
|
|
1072
1192
|
const lines = ["You are already logged in.", ""];
|
|
1073
1193
|
if (whoami2) {
|
|
1074
1194
|
const contextParts2 = [];
|
|
1075
1195
|
if (whoami2.organization) contextParts2.push(whoami2.organization.name);
|
|
1076
1196
|
if (whoami2.project) contextParts2.push(whoami2.project.name);
|
|
1077
1197
|
const scopeDisplay2 = contextParts2.length > 0 ? contextParts2.join(" / ") : "Personal";
|
|
1078
|
-
lines.push(`${
|
|
1079
|
-
lines.push(`${whoami2.user.name} ${
|
|
1080
|
-
if (whoami2.organization) lines.push(`${
|
|
1081
|
-
if (whoami2.project) lines.push(`${
|
|
1198
|
+
lines.push(`${pc17.bold(scopeDisplay2)} ${pc17.dim("\xB7")} ${envLabel2}`);
|
|
1199
|
+
lines.push(`${whoami2.user.name} ${pc17.dim(`(${whoami2.user.email})`)}`);
|
|
1200
|
+
if (whoami2.organization) lines.push(`${pc17.dim("Org:")} ${whoami2.organization.name}`);
|
|
1201
|
+
if (whoami2.project) lines.push(`${pc17.dim("Project:")} ${whoami2.project.name}`);
|
|
1082
1202
|
}
|
|
1083
1203
|
lines.push("");
|
|
1084
|
-
lines.push(`${
|
|
1204
|
+
lines.push(`${pc17.dim("Stored in")} ${currentScope}`);
|
|
1085
1205
|
p2.note(lines.join("\n"));
|
|
1086
1206
|
const scopeChoice = await p2.select({
|
|
1087
1207
|
message: "Where would you like to log in?",
|
|
@@ -1104,40 +1224,40 @@ async function loginCommand() {
|
|
|
1104
1224
|
if (resolved.config) {
|
|
1105
1225
|
writeConfig({ ...resolved.config, whoami }, targetScope);
|
|
1106
1226
|
}
|
|
1107
|
-
const
|
|
1227
|
+
const pc16 = (await import("picocolors")).default;
|
|
1108
1228
|
const env = getEnvFromApiKey(apiKey);
|
|
1109
1229
|
const contextParts = [];
|
|
1110
1230
|
if (whoami.organization) contextParts.push(whoami.organization.name);
|
|
1111
1231
|
if (whoami.project) contextParts.push(whoami.project.name);
|
|
1112
1232
|
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
1113
|
-
const envLabel = env === "test" ?
|
|
1114
|
-
const configLabel = targetScope === "project" ?
|
|
1233
|
+
const envLabel = env === "test" ? pc16.yellow("test") : pc16.green("live");
|
|
1234
|
+
const configLabel = targetScope === "project" ? pc16.cyan("local config") : pc16.magenta("global config");
|
|
1115
1235
|
const infoLines = [
|
|
1116
|
-
`${
|
|
1117
|
-
`${whoami.user.name} ${
|
|
1236
|
+
`${pc16.bold(scopeDisplay)} ${pc16.dim("\xB7")} ${envLabel}`,
|
|
1237
|
+
`${whoami.user.name} ${pc16.dim(`(${whoami.user.email})`)}`
|
|
1118
1238
|
];
|
|
1119
|
-
if (whoami.organization) infoLines.push(`${
|
|
1120
|
-
if (whoami.project) infoLines.push(`${
|
|
1239
|
+
if (whoami.organization) infoLines.push(`${pc16.dim("Org:")} ${whoami.organization.name}`);
|
|
1240
|
+
if (whoami.project) infoLines.push(`${pc16.dim("Project:")} ${whoami.project.name}`);
|
|
1121
1241
|
infoLines.push("");
|
|
1122
|
-
infoLines.push(`${
|
|
1242
|
+
infoLines.push(`${pc16.dim("Stored in")} ${configLabel}`);
|
|
1123
1243
|
p2.note(infoLines.join("\n"), "Logged in");
|
|
1124
1244
|
console.log();
|
|
1125
|
-
console.log(` ${
|
|
1126
|
-
console.log(` ${
|
|
1245
|
+
console.log(` ${pc16.dim("Next steps:")}`);
|
|
1246
|
+
console.log(` ${pc16.cyan("one add <platform>")} ${pc16.dim("\u2014")} Connect a platform (e.g. gmail, slack, stripe)`);
|
|
1127
1247
|
console.log();
|
|
1128
|
-
console.log(
|
|
1248
|
+
console.log(pc16.bold(" Copy-paste this to your AI agent:"));
|
|
1129
1249
|
console.log();
|
|
1130
|
-
console.log(
|
|
1131
|
-
console.log(
|
|
1132
|
-
console.log(
|
|
1133
|
-
console.log(
|
|
1134
|
-
console.log(
|
|
1135
|
-
console.log(
|
|
1136
|
-
console.log(
|
|
1137
|
-
console.log(
|
|
1138
|
-
console.log(
|
|
1139
|
-
console.log(
|
|
1140
|
-
console.log(
|
|
1250
|
+
console.log(pc16.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"));
|
|
1251
|
+
console.log(pc16.cyan(" \u2502"));
|
|
1252
|
+
console.log(pc16.cyan(" \u2502 The One CLI (`one`) is now installed on this machine. It"));
|
|
1253
|
+
console.log(pc16.cyan(" \u2502 lets you interact with 600+ third-party platforms (Gmail,"));
|
|
1254
|
+
console.log(pc16.cyan(" \u2502 Slack, Shopify, HubSpot, Stripe, GitHub, etc.) through"));
|
|
1255
|
+
console.log(pc16.cyan(" \u2502 their APIs. Whenever you need to interact with any"));
|
|
1256
|
+
console.log(pc16.cyan(" \u2502 third-party platform or external service, use the `one`"));
|
|
1257
|
+
console.log(pc16.cyan(" \u2502 skill. Please save this to your project instructions or"));
|
|
1258
|
+
console.log(pc16.cyan(" \u2502 memory so you remember it in future conversations."));
|
|
1259
|
+
console.log(pc16.cyan(" \u2502"));
|
|
1260
|
+
console.log(pc16.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"));
|
|
1141
1261
|
console.log();
|
|
1142
1262
|
p2.outro("Happy building!");
|
|
1143
1263
|
}
|
|
@@ -1245,18 +1365,18 @@ async function nonInteractiveInit(options) {
|
|
|
1245
1365
|
if (whoami.organization) contextParts.push(whoami.organization.name);
|
|
1246
1366
|
if (whoami.project) contextParts.push(whoami.project.name);
|
|
1247
1367
|
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
1248
|
-
const envLabel = env === "test" ?
|
|
1368
|
+
const envLabel = env === "test" ? pc3.yellow("test") : pc3.green("live");
|
|
1249
1369
|
console.log();
|
|
1250
|
-
console.log(` ${
|
|
1251
|
-
console.log(` ${
|
|
1252
|
-
console.log(` ${
|
|
1253
|
-
console.log(` ${
|
|
1254
|
-
console.log(` ${
|
|
1370
|
+
console.log(` ${pc3.bold("Setup complete")} ${scopeLabel(scope)}`);
|
|
1371
|
+
console.log(` ${pc3.dim("\u2500".repeat(42))}`);
|
|
1372
|
+
console.log(` ${pc3.dim("Account:")} ${scopeDisplay} ${pc3.dim("\xB7")} ${envLabel}`);
|
|
1373
|
+
console.log(` ${pc3.dim("User:")} ${whoami.user.name} ${pc3.dim(`(${whoami.user.email})`)}`);
|
|
1374
|
+
console.log(` ${pc3.dim("Config:")} ${tildify(configPath)}`);
|
|
1255
1375
|
if (installed.length > 0) {
|
|
1256
|
-
console.log(` ${
|
|
1376
|
+
console.log(` ${pc3.dim("Skill:")} ${pc3.green("installed")} ${pc3.dim("\xB7 " + installed.join(", "))}`);
|
|
1257
1377
|
}
|
|
1258
1378
|
console.log();
|
|
1259
|
-
console.log(` ${
|
|
1379
|
+
console.log(` ${pc3.dim("Connect a platform later with")} ${pc3.cyan("one add <platform>")}`);
|
|
1260
1380
|
printOnboardingPrompt();
|
|
1261
1381
|
}
|
|
1262
1382
|
async function chooseConfigScope(options) {
|
|
@@ -1271,8 +1391,8 @@ async function chooseConfigScope(options) {
|
|
|
1271
1391
|
const homeProject = tildify(getProjectConfigPath(projectRoot));
|
|
1272
1392
|
if (hasProject) {
|
|
1273
1393
|
console.log();
|
|
1274
|
-
console.log(` ${
|
|
1275
|
-
console.log(` ${
|
|
1394
|
+
console.log(` ${pc3.dim("Project:")} ${projectName} ${pc3.dim(projectRoot)}`);
|
|
1395
|
+
console.log(` ${pc3.bold("Active config:")} ${pc3.cyan("project")} ${pc3.dim("\xB7 " + homeProject)}`);
|
|
1276
1396
|
console.log();
|
|
1277
1397
|
if (hasGlobal) {
|
|
1278
1398
|
const which2 = await p3.select({
|
|
@@ -1289,11 +1409,11 @@ async function chooseConfigScope(options) {
|
|
|
1289
1409
|
return "project";
|
|
1290
1410
|
}
|
|
1291
1411
|
console.log();
|
|
1292
|
-
console.log(` ${
|
|
1293
|
-
console.log(` ${
|
|
1294
|
-
console.log(` ${
|
|
1295
|
-
console.log(` ${
|
|
1296
|
-
console.log(` ${
|
|
1412
|
+
console.log(` ${pc3.bold("Initializing One")}`);
|
|
1413
|
+
console.log(` ${pc3.dim("\u2500".repeat(42))}`);
|
|
1414
|
+
console.log(` ${pc3.dim("Project:")} ${projectName} ${pc3.dim(projectRoot)}`);
|
|
1415
|
+
console.log(` ${pc3.dim("Global:")} ${hasGlobal ? pc3.green("\u2713 configured") : pc3.yellow("\u2014 not set up")} ${pc3.dim(homeGlobal)}`);
|
|
1416
|
+
console.log(` ${pc3.dim("Project:")} ${pc3.yellow("\u2014 not set up")} ${pc3.dim(homeProject)}`);
|
|
1297
1417
|
console.log();
|
|
1298
1418
|
const defaultScope = hasGlobal ? "project" : "global";
|
|
1299
1419
|
const hint = hasGlobal ? "Your global config stays as-is. This folder gets its own setup." : "No global config yet \u2014 this becomes your default for every folder.";
|
|
@@ -1322,7 +1442,7 @@ function tildify(filePath) {
|
|
|
1322
1442
|
return filePath.startsWith(home) ? "~" + filePath.slice(home.length) : filePath;
|
|
1323
1443
|
}
|
|
1324
1444
|
function scopeLabel(scope) {
|
|
1325
|
-
return scope === "project" ?
|
|
1445
|
+
return scope === "project" ? pc3.cyan("[project]") : pc3.magenta("[global]");
|
|
1326
1446
|
}
|
|
1327
1447
|
function scopedMessage(scope, message) {
|
|
1328
1448
|
return `${scopeLabel(scope)} ${message}`;
|
|
@@ -1333,20 +1453,20 @@ async function handleExistingConfig(apiKey, scope, options) {
|
|
|
1333
1453
|
const skillInstalled = isSkillInstalled2();
|
|
1334
1454
|
const activeConfigPath = scope === "project" ? getProjectConfigPath() : getGlobalConfigPath();
|
|
1335
1455
|
console.log();
|
|
1336
|
-
console.log(` ${
|
|
1337
|
-
console.log(` ${
|
|
1338
|
-
console.log(` ${
|
|
1339
|
-
console.log(` ${
|
|
1340
|
-
console.log(` ${
|
|
1456
|
+
console.log(` ${pc3.bold("Current Setup")} ${scopeLabel(scope)}`);
|
|
1457
|
+
console.log(` ${pc3.dim("\u2500".repeat(42))}`);
|
|
1458
|
+
console.log(` ${pc3.dim("API Key:")} ${masked}`);
|
|
1459
|
+
console.log(` ${pc3.dim("Skill:")} ${skillInstalled ? pc3.green("installed") : pc3.yellow("not installed")}`);
|
|
1460
|
+
console.log(` ${pc3.dim("Config:")} ${tildify(activeConfigPath)}`);
|
|
1341
1461
|
const ac = getAccessControl();
|
|
1342
1462
|
if (Object.keys(ac).length > 0) {
|
|
1343
1463
|
console.log();
|
|
1344
|
-
console.log(` ${
|
|
1345
|
-
console.log(` ${
|
|
1346
|
-
if (ac.permissions) console.log(` ${
|
|
1347
|
-
if (ac.connectionKeys) console.log(` ${
|
|
1348
|
-
if (ac.actionIds) console.log(` ${
|
|
1349
|
-
if (ac.knowledgeAgent) console.log(` ${
|
|
1464
|
+
console.log(` ${pc3.bold("Access Control")}`);
|
|
1465
|
+
console.log(` ${pc3.dim("\u2500".repeat(42))}`);
|
|
1466
|
+
if (ac.permissions) console.log(` ${pc3.dim("Permissions:")} ${ac.permissions}`);
|
|
1467
|
+
if (ac.connectionKeys) console.log(` ${pc3.dim("Connections:")} ${ac.connectionKeys.join(", ")}`);
|
|
1468
|
+
if (ac.actionIds) console.log(` ${pc3.dim("Action IDs:")} ${ac.actionIds.join(", ")}`);
|
|
1469
|
+
if (ac.knowledgeAgent) console.log(` ${pc3.dim("Knowledge only:")} yes`);
|
|
1350
1470
|
}
|
|
1351
1471
|
console.log();
|
|
1352
1472
|
const actionOptions = [];
|
|
@@ -1456,7 +1576,7 @@ async function handleUpdateKey(statuses, scope) {
|
|
|
1456
1576
|
whoamiResult = result.whoami;
|
|
1457
1577
|
} else {
|
|
1458
1578
|
p3.note(`Get your API key at:
|
|
1459
|
-
${
|
|
1579
|
+
${pc3.cyan(getApiKeyUrl())}`, `API Key ${scopeLabel(scope)}`);
|
|
1460
1580
|
const openBrowser = await p3.confirm({
|
|
1461
1581
|
message: scopedMessage(scope, "Open browser to get API key?"),
|
|
1462
1582
|
initialValue: true
|
|
@@ -1501,10 +1621,10 @@ ${pc2.cyan(getApiKeyUrl())}`, `API Key ${scopeLabel(scope)}`);
|
|
|
1501
1621
|
if (whoamiResult.organization) contextParts.push(whoamiResult.organization.name);
|
|
1502
1622
|
if (whoamiResult.project) contextParts.push(whoamiResult.project.name);
|
|
1503
1623
|
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
1504
|
-
const envLabel = env === "test" ?
|
|
1624
|
+
const envLabel = env === "test" ? pc3.yellow("test") : pc3.green("live");
|
|
1505
1625
|
p3.note(
|
|
1506
|
-
`${scopeDisplay} ${
|
|
1507
|
-
${whoamiResult.user.name} ${
|
|
1626
|
+
`${scopeDisplay} ${pc3.dim("\xB7")} ${envLabel}
|
|
1627
|
+
${whoamiResult.user.name} ${pc3.dim(`(${whoamiResult.user.email})`)}`,
|
|
1508
1628
|
"Account"
|
|
1509
1629
|
);
|
|
1510
1630
|
const ac = getAccessControl();
|
|
@@ -1628,7 +1748,7 @@ async function promptOpenAiKey(scope) {
|
|
|
1628
1748
|
const entered = await p3.password({
|
|
1629
1749
|
message: scopedMessage(
|
|
1630
1750
|
scope,
|
|
1631
|
-
`OpenAI API key ${
|
|
1751
|
+
`OpenAI API key ${pc3.dim("(optional \u2014 enables semantic search in `one mem`)")}`
|
|
1632
1752
|
),
|
|
1633
1753
|
mask: "\u2022",
|
|
1634
1754
|
// Validator accepts empty → treated as "skip".
|
|
@@ -1683,7 +1803,7 @@ async function promptSkillInstall() {
|
|
|
1683
1803
|
...primaryAgents.map((a) => ({
|
|
1684
1804
|
value: a.id,
|
|
1685
1805
|
label: a.name,
|
|
1686
|
-
hint: isSkillInstalledForAgent(a) ?
|
|
1806
|
+
hint: isSkillInstalledForAgent(a) ? pc3.green("installed") : void 0
|
|
1687
1807
|
})),
|
|
1688
1808
|
{
|
|
1689
1809
|
value: "_other",
|
|
@@ -1707,7 +1827,7 @@ async function promptSkillInstall() {
|
|
|
1707
1827
|
options: otherAgents.map((a) => ({
|
|
1708
1828
|
value: a.id,
|
|
1709
1829
|
label: a.name,
|
|
1710
|
-
hint: isSkillInstalledForAgent(a) ?
|
|
1830
|
+
hint: isSkillInstalledForAgent(a) ? pc3.green("installed") : void 0
|
|
1711
1831
|
}))
|
|
1712
1832
|
});
|
|
1713
1833
|
if (!p3.isCancel(otherChoice)) {
|
|
@@ -1723,7 +1843,7 @@ async function promptSkillInstall() {
|
|
|
1723
1843
|
const { installed, failed } = installSkillForAgents(selectedIds);
|
|
1724
1844
|
spinner5.stop(installed.length > 0 ? "Skill installed" : "Installation failed");
|
|
1725
1845
|
for (const name of installed) {
|
|
1726
|
-
p3.log.success(`${name}: ${
|
|
1846
|
+
p3.log.success(`${name}: ${pc3.green("\u2713")} skill installed`);
|
|
1727
1847
|
}
|
|
1728
1848
|
for (const name of failed) {
|
|
1729
1849
|
p3.log.warn(`${name}: failed to install`);
|
|
@@ -1732,19 +1852,19 @@ async function promptSkillInstall() {
|
|
|
1732
1852
|
}
|
|
1733
1853
|
function printOnboardingPrompt() {
|
|
1734
1854
|
console.log();
|
|
1735
|
-
console.log(
|
|
1855
|
+
console.log(pc3.bold(" Copy-paste this to your AI agent:"));
|
|
1736
1856
|
console.log();
|
|
1737
|
-
console.log(
|
|
1738
|
-
console.log(
|
|
1739
|
-
console.log(
|
|
1740
|
-
console.log(
|
|
1741
|
-
console.log(
|
|
1742
|
-
console.log(
|
|
1743
|
-
console.log(
|
|
1744
|
-
console.log(
|
|
1745
|
-
console.log(
|
|
1746
|
-
console.log(
|
|
1747
|
-
console.log(
|
|
1857
|
+
console.log(pc3.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"));
|
|
1858
|
+
console.log(pc3.cyan(" \u2502"));
|
|
1859
|
+
console.log(pc3.cyan(" \u2502 The One CLI (`one`) is now installed on this machine. It"));
|
|
1860
|
+
console.log(pc3.cyan(" \u2502 lets you interact with 600+ third-party platforms (Gmail,"));
|
|
1861
|
+
console.log(pc3.cyan(" \u2502 Slack, Shopify, HubSpot, Stripe, GitHub, etc.) through"));
|
|
1862
|
+
console.log(pc3.cyan(" \u2502 their APIs. Whenever you need to interact with any"));
|
|
1863
|
+
console.log(pc3.cyan(" \u2502 third-party platform or external service, use the `one`"));
|
|
1864
|
+
console.log(pc3.cyan(" \u2502 skill. Please save this to your project instructions or"));
|
|
1865
|
+
console.log(pc3.cyan(" \u2502 memory so you remember it in future conversations."));
|
|
1866
|
+
console.log(pc3.cyan(" \u2502"));
|
|
1867
|
+
console.log(pc3.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"));
|
|
1748
1868
|
console.log();
|
|
1749
1869
|
}
|
|
1750
1870
|
async function freshSetup(scope, options) {
|
|
@@ -1772,10 +1892,10 @@ async function freshSetup(scope, options) {
|
|
|
1772
1892
|
if (result.whoami.organization) contextParts.push(result.whoami.organization.name);
|
|
1773
1893
|
if (result.whoami.project) contextParts.push(result.whoami.project.name);
|
|
1774
1894
|
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
1775
|
-
const envLabel = env2 === "test" ?
|
|
1895
|
+
const envLabel = env2 === "test" ? pc3.yellow("test") : pc3.green("live");
|
|
1776
1896
|
p3.note(
|
|
1777
|
-
`${scopeDisplay} ${
|
|
1778
|
-
${result.whoami.user.name} ${
|
|
1897
|
+
`${scopeDisplay} ${pc3.dim("\xB7")} ${envLabel}
|
|
1898
|
+
${result.whoami.user.name} ${pc3.dim(`(${result.whoami.user.email})`)}`,
|
|
1779
1899
|
"Account"
|
|
1780
1900
|
);
|
|
1781
1901
|
writeConfig(
|
|
@@ -1789,7 +1909,7 @@ ${result.whoami.user.name} ${pc2.dim(`(${result.whoami.user.email})`)}`,
|
|
|
1789
1909
|
);
|
|
1790
1910
|
} else {
|
|
1791
1911
|
p3.note(`Get your API key at:
|
|
1792
|
-
${
|
|
1912
|
+
${pc3.cyan(getApiKeyUrl())}`, `API Key ${scopeLabel(scope)}`);
|
|
1793
1913
|
const openBrowser = await p3.confirm({
|
|
1794
1914
|
message: scopedMessage(scope, "Open browser to get API key?"),
|
|
1795
1915
|
initialValue: true
|
|
@@ -1832,10 +1952,10 @@ ${pc2.cyan(getApiKeyUrl())}`, `API Key ${scopeLabel(scope)}`);
|
|
|
1832
1952
|
if (whoami.organization) contextParts.push(whoami.organization.name);
|
|
1833
1953
|
if (whoami.project) contextParts.push(whoami.project.name);
|
|
1834
1954
|
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
1835
|
-
const envLabel = env2 === "test" ?
|
|
1955
|
+
const envLabel = env2 === "test" ? pc3.yellow("test") : pc3.green("live");
|
|
1836
1956
|
p3.note(
|
|
1837
|
-
`${scopeDisplay} ${
|
|
1838
|
-
${whoami.user.name} ${
|
|
1957
|
+
`${scopeDisplay} ${pc3.dim("\xB7")} ${envLabel}
|
|
1958
|
+
${whoami.user.name} ${pc3.dim(`(${whoami.user.email})`)}`,
|
|
1839
1959
|
"Account"
|
|
1840
1960
|
);
|
|
1841
1961
|
writeConfig(
|
|
@@ -1859,11 +1979,11 @@ ${whoami.user.name} ${pc2.dim(`(${whoami.user.email})`)}`,
|
|
|
1859
1979
|
};
|
|
1860
1980
|
await promptConnectIntegrations(apiKey, connParams);
|
|
1861
1981
|
const savedPath = scope === "project" ? getProjectConfigPath() : getGlobalConfigPath();
|
|
1862
|
-
const resolutionHint = scope === "project" ? `When you run ${
|
|
1982
|
+
const resolutionHint = scope === "project" ? `When you run ${pc3.cyan("one")} from ${pc3.bold(path4.basename(getProjectRoot()))}, it uses this project config.
|
|
1863
1983
|
From anywhere else, it falls back to your global config.` : `This config applies to every folder unless a project config is set.`;
|
|
1864
1984
|
p3.note(
|
|
1865
1985
|
`${scopeLabel(scope)} Config saved to:
|
|
1866
|
-
${
|
|
1986
|
+
${pc3.dim(tildify(savedPath))}
|
|
1867
1987
|
|
|
1868
1988
|
${resolutionHint}`,
|
|
1869
1989
|
"Setup Complete"
|
|
@@ -1873,18 +1993,18 @@ ${resolutionHint}`,
|
|
|
1873
1993
|
}
|
|
1874
1994
|
function printBanner() {
|
|
1875
1995
|
console.log();
|
|
1876
|
-
console.log(
|
|
1877
|
-
console.log(
|
|
1878
|
-
console.log(
|
|
1879
|
-
console.log(
|
|
1880
|
-
console.log(
|
|
1881
|
-
console.log(
|
|
1882
|
-
console.log(
|
|
1883
|
-
console.log(
|
|
1884
|
-
console.log(
|
|
1885
|
-
console.log(
|
|
1996
|
+
console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
|
|
1997
|
+
console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
|
|
1998
|
+
console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
|
|
1999
|
+
console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
|
|
2000
|
+
console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 "));
|
|
2001
|
+
console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 "));
|
|
2002
|
+
console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
|
|
2003
|
+
console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 "));
|
|
2004
|
+
console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
|
|
2005
|
+
console.log(pc3.yellow(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588"));
|
|
1886
2006
|
console.log();
|
|
1887
|
-
console.log(
|
|
2007
|
+
console.log(pc3.dim(" I N F R A S T R U C T U R E F O R A G E N T S"));
|
|
1888
2008
|
console.log();
|
|
1889
2009
|
}
|
|
1890
2010
|
var TOP_INTEGRATIONS = [
|
|
@@ -1929,13 +2049,13 @@ async function promptConnectIntegrations(apiKey, connParams) {
|
|
|
1929
2049
|
} catch {
|
|
1930
2050
|
p3.note("https://app.withone.ai/connections", "Open in browser");
|
|
1931
2051
|
}
|
|
1932
|
-
p3.log.info(`Connect from the dashboard, or use ${
|
|
2052
|
+
p3.log.info(`Connect from the dashboard, or use ${pc3.cyan("one add <platform>")}`);
|
|
1933
2053
|
break;
|
|
1934
2054
|
}
|
|
1935
2055
|
const platform = choice;
|
|
1936
2056
|
const integration = TOP_INTEGRATIONS.find((i) => i.value === platform);
|
|
1937
2057
|
const label = integration?.label ?? platform;
|
|
1938
|
-
p3.log.info(`Opening browser to connect ${
|
|
2058
|
+
p3.log.info(`Opening browser to connect ${pc3.cyan(label)}...`);
|
|
1939
2059
|
try {
|
|
1940
2060
|
await openConnectionPage(platform, connParams);
|
|
1941
2061
|
} catch {
|
|
@@ -1948,13 +2068,13 @@ async function promptConnectIntegrations(apiKey, connParams) {
|
|
|
1948
2068
|
try {
|
|
1949
2069
|
await api.waitForConnection(platform, 5 * 60 * 1e3, 5e3);
|
|
1950
2070
|
spinner5.stop(`${label} connected!`);
|
|
1951
|
-
p3.log.success(`${
|
|
2071
|
+
p3.log.success(`${pc3.green("\u2713")} ${label} is now available to your AI agents`);
|
|
1952
2072
|
connected.push(platform);
|
|
1953
2073
|
first = false;
|
|
1954
2074
|
} catch (error2) {
|
|
1955
2075
|
spinner5.stop("Connection timed out");
|
|
1956
2076
|
if (error2 instanceof TimeoutError) {
|
|
1957
|
-
p3.log.warn(`No worries. Connect later with: ${
|
|
2077
|
+
p3.log.warn(`No worries. Connect later with: ${pc3.cyan(`one add ${platform}`)}`);
|
|
1958
2078
|
}
|
|
1959
2079
|
first = false;
|
|
1960
2080
|
}
|
|
@@ -1971,7 +2091,7 @@ function maskApiKey(key) {
|
|
|
1971
2091
|
|
|
1972
2092
|
// src/commands/connection.ts
|
|
1973
2093
|
import * as p4 from "@clack/prompts";
|
|
1974
|
-
import
|
|
2094
|
+
import pc5 from "picocolors";
|
|
1975
2095
|
|
|
1976
2096
|
// src/lib/access.ts
|
|
1977
2097
|
async function resolveAllowedActions(api, actionIds) {
|
|
@@ -2057,7 +2177,7 @@ function countMatchingChars(a, b) {
|
|
|
2057
2177
|
}
|
|
2058
2178
|
|
|
2059
2179
|
// src/lib/table.ts
|
|
2060
|
-
import
|
|
2180
|
+
import pc4 from "picocolors";
|
|
2061
2181
|
function printTable(columns, rows) {
|
|
2062
2182
|
if (rows.length === 0) return;
|
|
2063
2183
|
const gap = " ";
|
|
@@ -2069,10 +2189,10 @@ function printTable(columns, rows) {
|
|
|
2069
2189
|
});
|
|
2070
2190
|
const header = columns.map((col, i) => {
|
|
2071
2191
|
const padded = col.align === "right" ? col.label.padStart(widths[i]) : col.label.padEnd(widths[i]);
|
|
2072
|
-
return
|
|
2192
|
+
return pc4.dim(padded);
|
|
2073
2193
|
}).join(gap);
|
|
2074
2194
|
console.log(`${indent}${header}`);
|
|
2075
|
-
const separator = columns.map((_, i) =>
|
|
2195
|
+
const separator = columns.map((_, i) => pc4.dim("\u2500".repeat(widths[i]))).join(gap);
|
|
2076
2196
|
console.log(`${indent}${separator}`);
|
|
2077
2197
|
for (const row of rows) {
|
|
2078
2198
|
const line = columns.map((col, i) => {
|
|
@@ -2097,7 +2217,7 @@ async function connectionAddCommand(platformArg, options) {
|
|
|
2097
2217
|
if (isAgentMode()) {
|
|
2098
2218
|
error("This command requires interactive input. Run without --agent.");
|
|
2099
2219
|
}
|
|
2100
|
-
p4.intro(
|
|
2220
|
+
p4.intro(pc5.bgCyan(pc5.black(" One ")));
|
|
2101
2221
|
const apiKey = getApiKey();
|
|
2102
2222
|
if (!apiKey) {
|
|
2103
2223
|
p4.cancel("Not configured. Run `one init` first.");
|
|
@@ -2132,7 +2252,7 @@ async function connectionAddCommand(platformArg, options) {
|
|
|
2132
2252
|
]
|
|
2133
2253
|
});
|
|
2134
2254
|
if (p4.isCancel(suggestion) || suggestion === "__other__") {
|
|
2135
|
-
p4.note(`Run ${
|
|
2255
|
+
p4.note(`Run ${pc5.cyan("one platforms")} to see all available platforms.`);
|
|
2136
2256
|
p4.cancel("Connection cancelled.");
|
|
2137
2257
|
process.exit(0);
|
|
2138
2258
|
}
|
|
@@ -2140,7 +2260,7 @@ async function connectionAddCommand(platformArg, options) {
|
|
|
2140
2260
|
} else {
|
|
2141
2261
|
p4.cancel(`Unknown platform: ${platformArg}
|
|
2142
2262
|
|
|
2143
|
-
Run ${
|
|
2263
|
+
Run ${pc5.cyan("one platforms")} to see available platforms.`);
|
|
2144
2264
|
process.exit(1);
|
|
2145
2265
|
}
|
|
2146
2266
|
}
|
|
@@ -2163,7 +2283,7 @@ Run ${pc4.cyan("one platforms")} to see available platforms.`);
|
|
|
2163
2283
|
} else {
|
|
2164
2284
|
p4.cancel(`Unknown platform: ${platformInput}
|
|
2165
2285
|
|
|
2166
|
-
Run ${
|
|
2286
|
+
Run ${pc5.cyan("one platforms")} to see available platforms.`);
|
|
2167
2287
|
process.exit(1);
|
|
2168
2288
|
}
|
|
2169
2289
|
}
|
|
@@ -2174,8 +2294,8 @@ Run ${pc4.cyan("one platforms")} to see available platforms.`);
|
|
|
2174
2294
|
...whoami?.project && { projectId: whoami.project.id }
|
|
2175
2295
|
};
|
|
2176
2296
|
const url = getConnectionUrl(platform, connParams);
|
|
2177
|
-
p4.log.info(`Opening browser to connect ${
|
|
2178
|
-
p4.note(
|
|
2297
|
+
p4.log.info(`Opening browser to connect ${pc5.cyan(platform)}...`);
|
|
2298
|
+
p4.note(pc5.dim(url), "URL");
|
|
2179
2299
|
try {
|
|
2180
2300
|
await openConnectionPage(platform, connParams);
|
|
2181
2301
|
} catch {
|
|
@@ -2203,7 +2323,7 @@ The connection is usable; set the tag later in the dashboard or retry.`
|
|
|
2203
2323
|
);
|
|
2204
2324
|
}
|
|
2205
2325
|
}
|
|
2206
|
-
p4.log.success(`${
|
|
2326
|
+
p4.log.success(`${pc5.green("\u2713")} ${connection2.platform} is now available to your AI agents.${tag ? ` (tag: ${tag})` : ""}`);
|
|
2207
2327
|
p4.outro("Connection complete!");
|
|
2208
2328
|
} catch (error2) {
|
|
2209
2329
|
pollSpinner.stop("Connection timed out");
|
|
@@ -2214,7 +2334,7 @@ The connection is usable; set the tag later in the dashboard or retry.`
|
|
|
2214
2334
|
- Browser popup was blocked
|
|
2215
2335
|
- Wrong account selected
|
|
2216
2336
|
|
|
2217
|
-
Try again with: ${
|
|
2337
|
+
Try again with: ${pc5.cyan(`one connection add ${platform}`)}`,
|
|
2218
2338
|
"Timed Out"
|
|
2219
2339
|
);
|
|
2220
2340
|
} else {
|
|
@@ -2278,14 +2398,14 @@ async function connectionListCommand(options) {
|
|
|
2278
2398
|
p4.note(
|
|
2279
2399
|
`No connections matching "${searchQuery}".
|
|
2280
2400
|
|
|
2281
|
-
Try: ${
|
|
2401
|
+
Try: ${pc5.cyan("one connection list")} to see all connections.`,
|
|
2282
2402
|
"No Results"
|
|
2283
2403
|
);
|
|
2284
2404
|
} else {
|
|
2285
2405
|
p4.note(
|
|
2286
2406
|
`No connections yet.
|
|
2287
2407
|
|
|
2288
|
-
Add one with: ${
|
|
2408
|
+
Add one with: ${pc5.cyan("one connection add gmail")}`,
|
|
2289
2409
|
"No Connections"
|
|
2290
2410
|
);
|
|
2291
2411
|
}
|
|
@@ -2307,9 +2427,9 @@ Add one with: ${pc4.cyan("one connection add gmail")}`,
|
|
|
2307
2427
|
{ key: "status", label: "" },
|
|
2308
2428
|
{ key: "platform", label: "Platform" },
|
|
2309
2429
|
{ key: "state", label: "Status" },
|
|
2310
|
-
{ key: "key", label: "Connection Key", color:
|
|
2311
|
-
...hasTags ? [{ key: "tags", label: "Tags", color:
|
|
2312
|
-
...hasScopedAccess ? [{ key: "access", label: "Access", color:
|
|
2430
|
+
{ key: "key", label: "Connection Key", color: pc5.dim },
|
|
2431
|
+
...hasTags ? [{ key: "tags", label: "Tags", color: pc5.dim }] : [],
|
|
2432
|
+
...hasScopedAccess ? [{ key: "access", label: "Access", color: pc5.yellow }] : []
|
|
2313
2433
|
],
|
|
2314
2434
|
rows
|
|
2315
2435
|
);
|
|
@@ -2323,7 +2443,7 @@ Add one with: ${pc4.cyan("one connection add gmail")}`,
|
|
|
2323
2443
|
}
|
|
2324
2444
|
p4.note(`${wrapText(lines.join("\n"))}
|
|
2325
2445
|
|
|
2326
|
-
Change it with: ${
|
|
2446
|
+
Change it with: ${pc5.cyan("one config")}`, "Access");
|
|
2327
2447
|
}
|
|
2328
2448
|
if (displayed.length < filtered.length) {
|
|
2329
2449
|
p4.note(
|
|
@@ -2331,7 +2451,7 @@ Change it with: ${pc4.cyan("one config")}`, "Access");
|
|
|
2331
2451
|
"Limited"
|
|
2332
2452
|
);
|
|
2333
2453
|
} else {
|
|
2334
|
-
p4.note(`Add more with: ${
|
|
2454
|
+
p4.note(`Add more with: ${pc5.cyan("one connection add <platform>")}`, "Tip");
|
|
2335
2455
|
}
|
|
2336
2456
|
} catch (error2) {
|
|
2337
2457
|
spinner5.stop("Failed to load connections");
|
|
@@ -2367,7 +2487,7 @@ async function connectionDeleteCommand(connectionKey, options) {
|
|
|
2367
2487
|
spinner5.stop(`Found ${connection2.platform} (${connection2.state})`);
|
|
2368
2488
|
if (!isAgentMode() && !options?.force) {
|
|
2369
2489
|
console.log();
|
|
2370
|
-
console.log(` ${getStatusIndicator(connection2.state)} ${connection2.platform} ${
|
|
2490
|
+
console.log(` ${getStatusIndicator(connection2.state)} ${connection2.platform} ${pc5.dim(connection2.key)}`);
|
|
2371
2491
|
console.log();
|
|
2372
2492
|
const confirmed = await p4.confirm({
|
|
2373
2493
|
message: "Are you sure you want to delete this connection?",
|
|
@@ -2391,7 +2511,7 @@ async function connectionDeleteCommand(connectionKey, options) {
|
|
|
2391
2511
|
});
|
|
2392
2512
|
return;
|
|
2393
2513
|
}
|
|
2394
|
-
p4.log.success(`${
|
|
2514
|
+
p4.log.success(`${pc5.green("\u2713")} ${connection2.platform} connection removed.`);
|
|
2395
2515
|
} catch (error2) {
|
|
2396
2516
|
deleteSpinner.stop("Failed to delete connection");
|
|
2397
2517
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
@@ -2431,19 +2551,19 @@ function wrapText(text5, width = 72) {
|
|
|
2431
2551
|
function getStatusIndicator(state) {
|
|
2432
2552
|
switch (state) {
|
|
2433
2553
|
case "operational":
|
|
2434
|
-
return
|
|
2554
|
+
return pc5.green("\u25CF");
|
|
2435
2555
|
case "degraded":
|
|
2436
|
-
return
|
|
2556
|
+
return pc5.yellow("\u25CF");
|
|
2437
2557
|
case "failed":
|
|
2438
|
-
return
|
|
2558
|
+
return pc5.red("\u25CF");
|
|
2439
2559
|
default:
|
|
2440
|
-
return
|
|
2560
|
+
return pc5.dim("\u25CB");
|
|
2441
2561
|
}
|
|
2442
2562
|
}
|
|
2443
2563
|
|
|
2444
2564
|
// src/commands/platforms.ts
|
|
2445
2565
|
import * as p5 from "@clack/prompts";
|
|
2446
|
-
import
|
|
2566
|
+
import pc6 from "picocolors";
|
|
2447
2567
|
async function platformsCommand(options) {
|
|
2448
2568
|
const apiKey = getApiKey();
|
|
2449
2569
|
if (!apiKey) {
|
|
@@ -2509,7 +2629,7 @@ async function platformsCommand(options) {
|
|
|
2509
2629
|
);
|
|
2510
2630
|
}
|
|
2511
2631
|
console.log();
|
|
2512
|
-
p5.note(`Connect with: ${
|
|
2632
|
+
p5.note(`Connect with: ${pc6.cyan("one connection add <platform>")}`, "Tip");
|
|
2513
2633
|
} catch (error2) {
|
|
2514
2634
|
spinner5.stop("Failed to load platforms");
|
|
2515
2635
|
error(`Error: ${error2 instanceof Error ? error2.message : "Unknown error"}`);
|
|
@@ -2518,7 +2638,7 @@ async function platformsCommand(options) {
|
|
|
2518
2638
|
|
|
2519
2639
|
// src/commands/actions.ts
|
|
2520
2640
|
import * as p6 from "@clack/prompts";
|
|
2521
|
-
import
|
|
2641
|
+
import pc7 from "picocolors";
|
|
2522
2642
|
function getConfig() {
|
|
2523
2643
|
const apiKey = getApiKey();
|
|
2524
2644
|
if (!apiKey) {
|
|
@@ -2539,11 +2659,11 @@ function parseJsonArg2(value, argName) {
|
|
|
2539
2659
|
}
|
|
2540
2660
|
}
|
|
2541
2661
|
async function actionsSearchCommand(platform, query, options) {
|
|
2542
|
-
intro(
|
|
2662
|
+
intro(pc7.bgCyan(pc7.black(" One ")));
|
|
2543
2663
|
const { apiKey, permissions, actionIds, knowledgeAgent } = getConfig();
|
|
2544
2664
|
const api = new OneApi(apiKey, getApiBase());
|
|
2545
2665
|
const spinner5 = createSpinner();
|
|
2546
|
-
spinner5.start(`Searching actions on ${
|
|
2666
|
+
spinner5.start(`Searching actions on ${pc7.cyan(platform)} for "${query}"...`);
|
|
2547
2667
|
try {
|
|
2548
2668
|
const agentType = knowledgeAgent ? "knowledge" : options.type || "execute";
|
|
2549
2669
|
const useCache = options.cache !== false;
|
|
@@ -2616,7 +2736,7 @@ async function actionsSearchCommand(platform, query, options) {
|
|
|
2616
2736
|
Suggestions:
|
|
2617
2737
|
- Try a more general query (e.g., 'list', 'get', 'search', 'create')
|
|
2618
2738
|
- Verify the platform name is correct
|
|
2619
|
-
- Check available platforms with ${
|
|
2739
|
+
- Check available platforms with ${pc7.cyan("one platforms")}
|
|
2620
2740
|
|
|
2621
2741
|
Examples of good queries:
|
|
2622
2742
|
- "search contacts"
|
|
@@ -2641,15 +2761,15 @@ Examples of good queries:
|
|
|
2641
2761
|
[
|
|
2642
2762
|
{ key: "method", label: "Method" },
|
|
2643
2763
|
{ key: "title", label: "Title" },
|
|
2644
|
-
{ key: "actionId", label: "Action ID", color:
|
|
2645
|
-
{ key: "path", label: "Path", color:
|
|
2764
|
+
{ key: "actionId", label: "Action ID", color: pc7.dim },
|
|
2765
|
+
{ key: "path", label: "Path", color: pc7.dim }
|
|
2646
2766
|
],
|
|
2647
2767
|
rows
|
|
2648
2768
|
);
|
|
2649
2769
|
console.log();
|
|
2650
2770
|
p6.note(
|
|
2651
|
-
`Get details: ${
|
|
2652
|
-
Execute: ${
|
|
2771
|
+
`Get details: ${pc7.cyan(`one actions knowledge ${platform} <actionId>`)}
|
|
2772
|
+
Execute: ${pc7.cyan(`one actions execute ${platform} <actionId> <connectionKey>`)}`,
|
|
2653
2773
|
"Next Steps"
|
|
2654
2774
|
);
|
|
2655
2775
|
} catch (error2) {
|
|
@@ -2682,7 +2802,7 @@ async function actionsKnowledgeCommand(platform, actionId, options) {
|
|
|
2682
2802
|
}
|
|
2683
2803
|
return;
|
|
2684
2804
|
}
|
|
2685
|
-
intro(
|
|
2805
|
+
intro(pc7.bgCyan(pc7.black(" One ")));
|
|
2686
2806
|
const { apiKey, actionIds, connectionKeys } = getConfig();
|
|
2687
2807
|
const api = new OneApi(apiKey, getApiBase());
|
|
2688
2808
|
if (!isActionAllowed(actionId, actionIds)) {
|
|
@@ -2707,7 +2827,7 @@ async function actionsKnowledgeCommand(platform, actionId, options) {
|
|
|
2707
2827
|
}
|
|
2708
2828
|
}
|
|
2709
2829
|
const spinner5 = createSpinner();
|
|
2710
|
-
spinner5.start(`Loading knowledge for action ${
|
|
2830
|
+
spinner5.start(`Loading knowledge for action ${pc7.dim(actionId)}...`);
|
|
2711
2831
|
try {
|
|
2712
2832
|
const { details, cacheHit, entry } = await resolveActionDetails(api, actionId, {
|
|
2713
2833
|
useCache: options.cache !== false
|
|
@@ -2736,7 +2856,7 @@ async function actionsKnowledgeCommand(platform, actionId, options) {
|
|
|
2736
2856
|
console.log(knowledgeWithGuidance);
|
|
2737
2857
|
console.log();
|
|
2738
2858
|
p6.note(
|
|
2739
|
-
`Execute: ${
|
|
2859
|
+
`Execute: ${pc7.cyan(`one actions execute ${platform} ${actionId} <connectionKey>`)}`,
|
|
2740
2860
|
"Next Step"
|
|
2741
2861
|
);
|
|
2742
2862
|
} catch (error2) {
|
|
@@ -2747,7 +2867,7 @@ async function actionsKnowledgeCommand(platform, actionId, options) {
|
|
|
2747
2867
|
}
|
|
2748
2868
|
}
|
|
2749
2869
|
async function actionsExecuteCommand(platform, actionId, connectionKey, options) {
|
|
2750
|
-
intro(
|
|
2870
|
+
intro(pc7.bgCyan(pc7.black(" One ")));
|
|
2751
2871
|
const { apiKey, permissions, actionIds, connectionKeys, knowledgeAgent } = getConfig();
|
|
2752
2872
|
if (knowledgeAgent) {
|
|
2753
2873
|
error(
|
|
@@ -2772,7 +2892,7 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
|
|
|
2772
2892
|
);
|
|
2773
2893
|
}
|
|
2774
2894
|
spinner5.stop(
|
|
2775
|
-
`Action: ${actionDetails.title} [${actionDetails.method}]` + (preflightCacheHit ?
|
|
2895
|
+
`Action: ${actionDetails.title} [${actionDetails.method}]` + (preflightCacheHit ? pc7.dim(" (cached)") : "")
|
|
2776
2896
|
);
|
|
2777
2897
|
const data = options.data ? parseJsonArg2(options.data, "--data") : void 0;
|
|
2778
2898
|
const pathVariables = options.pathVars ? parseJsonArg2(options.pathVars, "--path-vars") : void 0;
|
|
@@ -2792,9 +2912,9 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
|
|
|
2792
2912
|
}
|
|
2793
2913
|
console.log();
|
|
2794
2914
|
for (const m of validation.missing) {
|
|
2795
|
-
console.log(
|
|
2915
|
+
console.log(pc7.red(` ${m.flag} is missing "${m.param}"`));
|
|
2796
2916
|
if (m.description) {
|
|
2797
|
-
console.log(
|
|
2917
|
+
console.log(pc7.dim(` ${m.description}`));
|
|
2798
2918
|
}
|
|
2799
2919
|
}
|
|
2800
2920
|
console.log();
|
|
@@ -2819,7 +2939,7 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
|
|
|
2819
2939
|
}
|
|
2820
2940
|
console.log();
|
|
2821
2941
|
if (mockResponse) {
|
|
2822
|
-
console.log(
|
|
2942
|
+
console.log(pc7.bold("Mock Response:"));
|
|
2823
2943
|
console.log(JSON.stringify(mockResponse, null, 2));
|
|
2824
2944
|
} else {
|
|
2825
2945
|
note("No example output available for this action", "Mock");
|
|
@@ -2860,26 +2980,26 @@ async function actionsExecuteCommand(platform, actionId, connectionKey, options)
|
|
|
2860
2980
|
return;
|
|
2861
2981
|
}
|
|
2862
2982
|
console.log();
|
|
2863
|
-
console.log(
|
|
2983
|
+
console.log(pc7.dim("Request:"));
|
|
2864
2984
|
console.log(
|
|
2865
|
-
|
|
2985
|
+
pc7.dim(
|
|
2866
2986
|
` ${result.requestConfig.method} ${result.requestConfig.url}`
|
|
2867
2987
|
)
|
|
2868
2988
|
);
|
|
2869
2989
|
if (options.dryRun) {
|
|
2870
2990
|
if (result.requestConfig.data) {
|
|
2871
2991
|
console.log();
|
|
2872
|
-
console.log(
|
|
2873
|
-
console.log(
|
|
2992
|
+
console.log(pc7.dim("Body:"));
|
|
2993
|
+
console.log(pc7.dim(JSON.stringify(result.requestConfig.data, null, 2)));
|
|
2874
2994
|
}
|
|
2875
2995
|
console.log();
|
|
2876
2996
|
note("Dry run \u2014 request was not sent", "Dry Run");
|
|
2877
2997
|
} else {
|
|
2878
2998
|
console.log();
|
|
2879
|
-
console.log(
|
|
2999
|
+
console.log(pc7.bold("Response:"));
|
|
2880
3000
|
const rd = result.responseData;
|
|
2881
3001
|
if (rd && typeof rd === "object" && typeof rd.text === "string" && "contentType" in rd) {
|
|
2882
|
-
if (rd.contentType) console.log(
|
|
3002
|
+
if (rd.contentType) console.log(pc7.dim(`(${rd.contentType})`));
|
|
2883
3003
|
console.log(rd.text);
|
|
2884
3004
|
} else {
|
|
2885
3005
|
console.log(JSON.stringify(result.responseData, null, 2));
|
|
@@ -3083,7 +3203,7 @@ async function actionsExecuteParallelCommand() {
|
|
|
3083
3203
|
}
|
|
3084
3204
|
console.log();
|
|
3085
3205
|
for (const e of errors) {
|
|
3086
|
-
console.log(` ${
|
|
3206
|
+
console.log(` ${pc7.red("\u2717")} Segment ${e.segment} (${e.label}):`);
|
|
3087
3207
|
for (const msg of e.messages) {
|
|
3088
3208
|
console.log(` ${msg}`);
|
|
3089
3209
|
}
|
|
@@ -3178,17 +3298,17 @@ async function actionsExecuteParallelCommand() {
|
|
|
3178
3298
|
console.log();
|
|
3179
3299
|
for (const r of results) {
|
|
3180
3300
|
const label = `${r.platform}/${r.actionId}`;
|
|
3181
|
-
const time =
|
|
3301
|
+
const time = pc7.dim(`(${(r.durationMs / 1e3).toFixed(2)}s)`);
|
|
3182
3302
|
if (r.mock) {
|
|
3183
|
-
console.log(` [${r.segment}/${total}] ${label} ${
|
|
3184
|
-
if (r.response) console.log(` ${
|
|
3303
|
+
console.log(` [${r.segment}/${total}] ${label} ${pc7.cyan("\u25C7 mock")} ${time}`);
|
|
3304
|
+
if (r.response) console.log(` ${pc7.dim(JSON.stringify(r.response, null, 2).split("\n").join("\n "))}`);
|
|
3185
3305
|
} else if (r.dryRun) {
|
|
3186
|
-
console.log(` [${r.segment}/${total}] ${label} ${
|
|
3306
|
+
console.log(` [${r.segment}/${total}] ${label} ${pc7.yellow("\u2298 dry-run")} ${time}`);
|
|
3187
3307
|
} else if (r.status === "success") {
|
|
3188
|
-
console.log(` [${r.segment}/${total}] ${label} ${
|
|
3189
|
-
if (r.response) console.log(` ${
|
|
3308
|
+
console.log(` [${r.segment}/${total}] ${label} ${pc7.green("\u2713")} ${time}`);
|
|
3309
|
+
if (r.response) console.log(` ${pc7.dim(JSON.stringify(r.response, null, 2).split("\n").join("\n "))}`);
|
|
3190
3310
|
} else {
|
|
3191
|
-
console.log(` [${r.segment}/${total}] ${label} ${
|
|
3311
|
+
console.log(` [${r.segment}/${total}] ${label} ${pc7.red("\u2717")} ${time} \u2014 ${r.error}`);
|
|
3192
3312
|
}
|
|
3193
3313
|
}
|
|
3194
3314
|
console.log();
|
|
@@ -3203,22 +3323,22 @@ async function actionsExecuteParallelCommand() {
|
|
|
3203
3323
|
function colorMethod(method) {
|
|
3204
3324
|
switch (method.toUpperCase()) {
|
|
3205
3325
|
case "GET":
|
|
3206
|
-
return
|
|
3326
|
+
return pc7.green(method);
|
|
3207
3327
|
case "POST":
|
|
3208
|
-
return
|
|
3328
|
+
return pc7.yellow(method);
|
|
3209
3329
|
case "PUT":
|
|
3210
|
-
return
|
|
3330
|
+
return pc7.blue(method);
|
|
3211
3331
|
case "PATCH":
|
|
3212
|
-
return
|
|
3332
|
+
return pc7.magenta(method);
|
|
3213
3333
|
case "DELETE":
|
|
3214
|
-
return
|
|
3334
|
+
return pc7.red(method);
|
|
3215
3335
|
default:
|
|
3216
3336
|
return method;
|
|
3217
3337
|
}
|
|
3218
3338
|
}
|
|
3219
3339
|
|
|
3220
3340
|
// src/commands/flow.ts
|
|
3221
|
-
import
|
|
3341
|
+
import pc8 from "picocolors";
|
|
3222
3342
|
|
|
3223
3343
|
// src/lib/flow-validator.ts
|
|
3224
3344
|
import fs4 from "fs";
|
|
@@ -3976,25 +4096,25 @@ function previewValue(value, max = 120) {
|
|
|
3976
4096
|
}
|
|
3977
4097
|
function renderDryRef(ref) {
|
|
3978
4098
|
if (ref.status === "resolved") {
|
|
3979
|
-
return `${
|
|
4099
|
+
return `${pc8.green("\u2713")} ${ref.selector} ${pc8.dim("\u2192")} ${previewValue(ref.value)}`;
|
|
3980
4100
|
}
|
|
3981
4101
|
if (ref.status === "deferred") {
|
|
3982
|
-
return `${
|
|
4102
|
+
return `${pc8.dim("\u25CB")} ${ref.selector} ${pc8.dim("\u2192 pending (produced by a later step)")}`;
|
|
3983
4103
|
}
|
|
3984
|
-
return `${
|
|
4104
|
+
return `${pc8.yellow("!")} ${ref.selector} ${pc8.yellow("\u2192 unresolved \u2014 check the input/env name")}`;
|
|
3985
4105
|
}
|
|
3986
4106
|
function renderDryResolution(steps) {
|
|
3987
4107
|
const isExpr = (t) => t === "transform" || t === "condition" || t === "while";
|
|
3988
4108
|
for (const s of steps) {
|
|
3989
|
-
const label = s.name ? `${s.stepId} ${
|
|
3990
|
-
console.log(` ${
|
|
4109
|
+
const label = s.name ? `${s.stepId} ${pc8.dim(`"${s.name}"`)}` : s.stepId;
|
|
4110
|
+
console.log(` ${pc8.cyan("\u25B8")} ${label} ${pc8.dim(`(${s.type})`)}`);
|
|
3991
4111
|
if (s.error !== void 0) {
|
|
3992
|
-
console.log(` ${
|
|
4112
|
+
console.log(` ${pc8.red("error")} ${s.error}`);
|
|
3993
4113
|
} else if (isExpr(s.type) && s.deferred) {
|
|
3994
4114
|
const deps = s.references.map((r) => r.selector).join(", ");
|
|
3995
|
-
console.log(` ${
|
|
4115
|
+
console.log(` ${pc8.dim("\u25CB pending \u2014 depends on")} ${deps} ${pc8.dim("(produced by a later step)")}`);
|
|
3996
4116
|
} else if (isExpr(s.type)) {
|
|
3997
|
-
console.log(` ${
|
|
4117
|
+
console.log(` ${pc8.dim("=")} ${previewValue(s.resolved)}`);
|
|
3998
4118
|
}
|
|
3999
4119
|
if (!(isExpr(s.type) && s.deferred)) {
|
|
4000
4120
|
for (const ref of s.references) {
|
|
@@ -4002,7 +4122,7 @@ function renderDryResolution(steps) {
|
|
|
4002
4122
|
}
|
|
4003
4123
|
}
|
|
4004
4124
|
if (!isExpr(s.type) && s.references.length === 0 && s.error === void 0) {
|
|
4005
|
-
console.log(` ${
|
|
4125
|
+
console.log(` ${pc8.dim("(no interpolations)")}`);
|
|
4006
4126
|
}
|
|
4007
4127
|
}
|
|
4008
4128
|
}
|
|
@@ -4056,7 +4176,7 @@ async function autoResolveConnectionInputs(flow2, inputs, api) {
|
|
|
4056
4176
|
return resolved;
|
|
4057
4177
|
}
|
|
4058
4178
|
async function flowCreateCommand(key, options) {
|
|
4059
|
-
intro(
|
|
4179
|
+
intro(pc8.bgCyan(pc8.black(" One Workflow ")));
|
|
4060
4180
|
let flow2;
|
|
4061
4181
|
if (options.definition) {
|
|
4062
4182
|
let raw = options.definition;
|
|
@@ -4112,11 +4232,11 @@ ${errors.map((e) => ` ${e.path}: ${e.message}`).join("\n")}`);
|
|
|
4112
4232
|
return;
|
|
4113
4233
|
}
|
|
4114
4234
|
note(`Workflow "${flow2.name}" saved to ${flowPath}`, "Created");
|
|
4115
|
-
outro(`Validate: ${
|
|
4116
|
-
Execute: ${
|
|
4235
|
+
outro(`Validate: ${pc8.cyan(`one flow validate ${flow2.key}`)}
|
|
4236
|
+
Execute: ${pc8.cyan(`one flow execute ${flow2.key}`)}`);
|
|
4117
4237
|
}
|
|
4118
4238
|
async function flowExecuteCommand(keyOrPath, options) {
|
|
4119
|
-
intro(
|
|
4239
|
+
intro(pc8.bgCyan(pc8.black(" One Workflow ")));
|
|
4120
4240
|
const { apiKey, permissions, actionIds } = getConfig2();
|
|
4121
4241
|
const api = new OneApi(apiKey, getApiBase());
|
|
4122
4242
|
const spinner5 = createSpinner();
|
|
@@ -4149,7 +4269,7 @@ ${preflightErrors.map((e) => ` ${e.path}: ${e.message}`).join("\n")}`);
|
|
|
4149
4269
|
if (isAgentMode()) {
|
|
4150
4270
|
json({ event: "flow:deprecation", flowKey: flow2.key, warning: msg });
|
|
4151
4271
|
} else {
|
|
4152
|
-
console.error(
|
|
4272
|
+
console.error(pc8.yellow(`\u26A0 ${msg}`));
|
|
4153
4273
|
}
|
|
4154
4274
|
}
|
|
4155
4275
|
if (!options.allowBash && flowRequiresBash(flow2)) {
|
|
@@ -4183,7 +4303,7 @@ ${preflightErrors.map((e) => ` ${e.path}: ${e.message}`).join("\n")}`);
|
|
|
4183
4303
|
runner.requestPause();
|
|
4184
4304
|
if (!isAgentMode()) {
|
|
4185
4305
|
console.log(`
|
|
4186
|
-
${
|
|
4306
|
+
${pc8.yellow("Pausing after current step completes...")} (run ID: ${runId})`);
|
|
4187
4307
|
}
|
|
4188
4308
|
};
|
|
4189
4309
|
process.on("SIGINT", sigintHandler);
|
|
@@ -4203,12 +4323,12 @@ ${pc7.yellow("Pausing after current step completes...")} (run ID: ${runId})`);
|
|
|
4203
4323
|
} else if (options.verbose) {
|
|
4204
4324
|
const ts = (/* @__PURE__ */ new Date()).toISOString().split("T")[1].slice(0, 8);
|
|
4205
4325
|
if (event.event === "step:start") {
|
|
4206
|
-
console.log(` ${
|
|
4326
|
+
console.log(` ${pc8.dim(ts)} ${pc8.cyan("\u25B6")} ${event.stepName} ${pc8.dim(`(${event.type})`)}`);
|
|
4207
4327
|
} else if (event.event === "step:complete") {
|
|
4208
|
-
const status = event.status === "success" ?
|
|
4209
|
-
console.log(` ${
|
|
4328
|
+
const status = event.status === "success" ? pc8.green("\u2713") : event.status === "skipped" ? pc8.dim("\u25CB") : pc8.red("\u2717");
|
|
4329
|
+
console.log(` ${pc8.dim(ts)} ${status} ${event.stepId} ${pc8.dim(`${event.durationMs}ms`)}`);
|
|
4210
4330
|
} else if (event.event === "step:error") {
|
|
4211
|
-
console.log(` ${
|
|
4331
|
+
console.log(` ${pc8.dim(ts)} ${pc8.red("\u2717")} ${event.stepId}: ${event.error}`);
|
|
4212
4332
|
}
|
|
4213
4333
|
}
|
|
4214
4334
|
};
|
|
@@ -4257,8 +4377,8 @@ ${pc7.yellow("Pausing after current step completes...")} (run ID: ${runId})`);
|
|
|
4257
4377
|
console.log();
|
|
4258
4378
|
const missing = dryRunSteps.reduce((n, s) => n + s.references.filter((r) => r.status === "missing").length, 0);
|
|
4259
4379
|
note(
|
|
4260
|
-
`Dry run \u2014 no steps executed. Resolved ${dryRunSteps.length} step(s)` + (missing > 0 ? `; ${
|
|
4261
|
-
${
|
|
4380
|
+
`Dry run \u2014 no steps executed. Resolved ${dryRunSteps.length} step(s)` + (missing > 0 ? `; ${pc8.yellow(`${missing} unresolved input/env reference(s)`)}` : "") + `.
|
|
4381
|
+
${pc8.dim("$.steps.* refs resolve at runtime \u2014 re-run with --stop-after=<stepId> to resolve them against real output.")}`,
|
|
4262
4382
|
"Dry Run"
|
|
4263
4383
|
);
|
|
4264
4384
|
return;
|
|
@@ -4268,17 +4388,17 @@ ${pc7.dim("$.steps.* refs resolve at runtime \u2014 re-run with --stop-after=<st
|
|
|
4268
4388
|
const failed = stepEntries.filter(([, r]) => r.status === "failed").length;
|
|
4269
4389
|
const skipped = stepEntries.filter(([, r]) => r.status === "skipped").length;
|
|
4270
4390
|
console.log();
|
|
4271
|
-
console.log(` ${
|
|
4272
|
-
console.log(` ${
|
|
4273
|
-
console.log(` ${
|
|
4391
|
+
console.log(` ${pc8.green("\u2713")} ${succeeded} succeeded ${failed > 0 ? pc8.red(`\u2717 ${failed} failed`) : ""} ${skipped > 0 ? pc8.dim(`\u25CB ${skipped} skipped`) : ""}`);
|
|
4392
|
+
console.log(` ${pc8.dim(`Run ID: ${runId}`)}`);
|
|
4393
|
+
console.log(` ${pc8.dim(`Log: ${logPath}`)}`);
|
|
4274
4394
|
if (dryResolveTarget) {
|
|
4275
4395
|
console.log();
|
|
4276
|
-
console.log(` ${
|
|
4396
|
+
console.log(` ${pc8.dim(`Resolved (not executed) "${dryResolveTarget.stepId}":`)}`);
|
|
4277
4397
|
renderDryResolution([dryResolveTarget]);
|
|
4278
4398
|
}
|
|
4279
4399
|
if (stoppedAfter) {
|
|
4280
4400
|
note(
|
|
4281
|
-
`Stopped after step "${stoppedAfter}". Inspect step outputs with: ${
|
|
4401
|
+
`Stopped after step "${stoppedAfter}". Inspect step outputs with: ${pc8.cyan(`one flow inspect ${runId}`)}`,
|
|
4282
4402
|
"Stopped"
|
|
4283
4403
|
);
|
|
4284
4404
|
} else if (options.dryRun) {
|
|
@@ -4300,13 +4420,13 @@ ${pc7.dim("$.steps.* refs resolve at runtime \u2014 re-run with --stop-after=<st
|
|
|
4300
4420
|
});
|
|
4301
4421
|
process.exit(1);
|
|
4302
4422
|
}
|
|
4303
|
-
console.log(` ${
|
|
4304
|
-
console.log(` ${
|
|
4423
|
+
console.log(` ${pc8.dim(`Run ID: ${runId}`)}`);
|
|
4424
|
+
console.log(` ${pc8.dim(`Log: ${logPath}`)}`);
|
|
4305
4425
|
error(`Workflow failed: ${errorMsg}`);
|
|
4306
4426
|
}
|
|
4307
4427
|
}
|
|
4308
4428
|
async function flowListCommand() {
|
|
4309
|
-
intro(
|
|
4429
|
+
intro(pc8.bgCyan(pc8.black(" One Workflow ")));
|
|
4310
4430
|
const flows = listFlows();
|
|
4311
4431
|
if (isAgentMode()) {
|
|
4312
4432
|
json({ workflows: flows });
|
|
@@ -4338,7 +4458,7 @@ async function flowListCommand() {
|
|
|
4338
4458
|
console.log();
|
|
4339
4459
|
}
|
|
4340
4460
|
async function flowValidateCommand(keyOrPath) {
|
|
4341
|
-
intro(
|
|
4461
|
+
intro(pc8.bgCyan(pc8.black(" One Workflow ")));
|
|
4342
4462
|
const spinner5 = createSpinner();
|
|
4343
4463
|
spinner5.start(`Validating "${keyOrPath}"...`);
|
|
4344
4464
|
let flowData;
|
|
@@ -4367,7 +4487,7 @@ async function flowValidateCommand(keyOrPath) {
|
|
|
4367
4487
|
}
|
|
4368
4488
|
console.log();
|
|
4369
4489
|
for (const e of errors) {
|
|
4370
|
-
console.log(` ${
|
|
4490
|
+
console.log(` ${pc8.red("\u2717")} ${pc8.dim(e.path)}: ${e.message}`);
|
|
4371
4491
|
}
|
|
4372
4492
|
console.log();
|
|
4373
4493
|
error(`${errors.length} validation error(s) found`);
|
|
@@ -4380,7 +4500,7 @@ async function flowValidateCommand(keyOrPath) {
|
|
|
4380
4500
|
note(`Workflow "${flowData.key}" passed all validation checks`, "Valid");
|
|
4381
4501
|
}
|
|
4382
4502
|
async function flowResumeCommand(runId, options = {}) {
|
|
4383
|
-
intro(
|
|
4503
|
+
intro(pc8.bgCyan(pc8.black(" One Workflow ")));
|
|
4384
4504
|
const state = FlowRunner.loadRunState(runId);
|
|
4385
4505
|
if (!state) {
|
|
4386
4506
|
error(`Run "${runId}" not found`);
|
|
@@ -4433,8 +4553,8 @@ async function flowResumeCommand(runId, options = {}) {
|
|
|
4433
4553
|
});
|
|
4434
4554
|
return;
|
|
4435
4555
|
}
|
|
4436
|
-
console.log(` ${
|
|
4437
|
-
console.log(` ${
|
|
4556
|
+
console.log(` ${pc8.green("\u2713")} Resumed and completed successfully`);
|
|
4557
|
+
console.log(` ${pc8.dim(`Log: ${runner.getLogPath()}`)}`);
|
|
4438
4558
|
} catch (error2) {
|
|
4439
4559
|
spinner5.stop("Resume failed");
|
|
4440
4560
|
const errorMsg = error2 instanceof Error ? error2.message : String(error2);
|
|
@@ -4446,7 +4566,7 @@ async function flowResumeCommand(runId, options = {}) {
|
|
|
4446
4566
|
}
|
|
4447
4567
|
}
|
|
4448
4568
|
async function flowRunsCommand(flowKey) {
|
|
4449
|
-
intro(
|
|
4569
|
+
intro(pc8.bgCyan(pc8.black(" One Workflow ")));
|
|
4450
4570
|
const runs = FlowRunner.listRuns(flowKey);
|
|
4451
4571
|
if (isAgentMode()) {
|
|
4452
4572
|
json({
|
|
@@ -4486,7 +4606,7 @@ async function flowRunsCommand(flowKey) {
|
|
|
4486
4606
|
console.log();
|
|
4487
4607
|
}
|
|
4488
4608
|
async function flowInspectCommand(runId, options = {}) {
|
|
4489
|
-
intro(
|
|
4609
|
+
intro(pc8.bgCyan(pc8.black(" One Workflow ")));
|
|
4490
4610
|
const state = FlowRunner.loadRunState(runId);
|
|
4491
4611
|
if (!state) {
|
|
4492
4612
|
const msg = `No run found for id "${runId}". List runs with: one flow runs`;
|
|
@@ -4515,44 +4635,44 @@ async function flowInspectCommand(runId, options = {}) {
|
|
|
4515
4635
|
return;
|
|
4516
4636
|
}
|
|
4517
4637
|
console.log();
|
|
4518
|
-
console.log(` ${
|
|
4519
|
-
console.log(` ${
|
|
4520
|
-
if (state.currentStepId) console.log(` ${
|
|
4638
|
+
console.log(` ${pc8.bold(state.flowKey)} ${pc8.dim(`run ${state.runId}`)} ${colorStatus(state.status)}`);
|
|
4639
|
+
console.log(` ${pc8.dim(`Started: ${state.startedAt}${state.completedAt ? ` \xB7 Ended: ${state.completedAt}` : ""}`)}`);
|
|
4640
|
+
if (state.currentStepId) console.log(` ${pc8.dim(`Current step: ${state.currentStepId}`)}`);
|
|
4521
4641
|
console.log();
|
|
4522
4642
|
if (stepEntries.length === 0) {
|
|
4523
4643
|
note("No step outputs recorded yet for this run.", "Steps");
|
|
4524
4644
|
} else {
|
|
4525
4645
|
for (const [id, result] of stepEntries) {
|
|
4526
|
-
const icon = result.status === "success" ?
|
|
4527
|
-
const dur = result.durationMs !== void 0 ?
|
|
4528
|
-
const retries = result.retries ?
|
|
4529
|
-
console.log(` ${icon} ${id} ${
|
|
4646
|
+
const icon = result.status === "success" ? pc8.green("\u2713") : result.status === "skipped" ? pc8.dim("\u25CB") : result.status === "timeout" ? pc8.yellow("\u29D6") : pc8.red("\u2717");
|
|
4647
|
+
const dur = result.durationMs !== void 0 ? pc8.dim(` ${result.durationMs}ms`) : "";
|
|
4648
|
+
const retries = result.retries ? pc8.dim(` (${result.retries} retr${result.retries === 1 ? "y" : "ies"})`) : "";
|
|
4649
|
+
console.log(` ${icon} ${id} ${pc8.dim(`[${result.status}]`)}${dur}${retries}`);
|
|
4530
4650
|
if (result.error) {
|
|
4531
|
-
console.log(` ${
|
|
4651
|
+
console.log(` ${pc8.red("error")} ${result.error}${result.errorCode ? pc8.dim(` (${result.errorCode})`) : ""}`);
|
|
4532
4652
|
}
|
|
4533
4653
|
if (result.output !== void 0) {
|
|
4534
4654
|
const json2 = JSON.stringify(result.output, null, options.full ? 2 : 0) ?? String(result.output);
|
|
4535
|
-
const shown = options.full || json2.length <= 240 ? json2 : `${json2.slice(0, 239)}\u2026 ${
|
|
4536
|
-
const indented = options.full ? shown.split("\n").map((l) => ` ${l}`).join("\n") : ` ${
|
|
4655
|
+
const shown = options.full || json2.length <= 240 ? json2 : `${json2.slice(0, 239)}\u2026 ${pc8.dim("(--full for all)")}`;
|
|
4656
|
+
const indented = options.full ? shown.split("\n").map((l) => ` ${l}`).join("\n") : ` ${pc8.dim("output")} ${shown}`;
|
|
4537
4657
|
console.log(indented);
|
|
4538
4658
|
}
|
|
4539
4659
|
}
|
|
4540
4660
|
}
|
|
4541
4661
|
console.log();
|
|
4542
|
-
console.log(` ${
|
|
4543
|
-
console.log(` ${
|
|
4662
|
+
console.log(` ${pc8.dim(`State: ${statePath}`)}`);
|
|
4663
|
+
console.log(` ${pc8.dim(`Log: ${path6.join(".one/flows/.logs", `${state.flowKey}-${state.runId}.log`)}`)}`);
|
|
4544
4664
|
console.log();
|
|
4545
4665
|
}
|
|
4546
4666
|
function colorStatus(status) {
|
|
4547
4667
|
switch (status) {
|
|
4548
4668
|
case "completed":
|
|
4549
|
-
return
|
|
4669
|
+
return pc8.green(status);
|
|
4550
4670
|
case "running":
|
|
4551
|
-
return
|
|
4671
|
+
return pc8.cyan(status);
|
|
4552
4672
|
case "paused":
|
|
4553
|
-
return
|
|
4673
|
+
return pc8.yellow(status);
|
|
4554
4674
|
case "failed":
|
|
4555
|
-
return
|
|
4675
|
+
return pc8.red(status);
|
|
4556
4676
|
default:
|
|
4557
4677
|
return status;
|
|
4558
4678
|
}
|
|
@@ -4730,7 +4850,7 @@ async function flowScaffoldCommand(template) {
|
|
|
4730
4850
|
}
|
|
4731
4851
|
|
|
4732
4852
|
// src/commands/relay.ts
|
|
4733
|
-
import
|
|
4853
|
+
import pc9 from "picocolors";
|
|
4734
4854
|
function getConfig3() {
|
|
4735
4855
|
const apiKey = getApiKey();
|
|
4736
4856
|
if (!apiKey) {
|
|
@@ -4771,15 +4891,15 @@ async function relayCreateCommand(options) {
|
|
|
4771
4891
|
}
|
|
4772
4892
|
spinner5.stop("Relay endpoint created");
|
|
4773
4893
|
console.log();
|
|
4774
|
-
console.log(` ${
|
|
4775
|
-
console.log(` ${
|
|
4776
|
-
console.log(` ${
|
|
4777
|
-
if (result.description) console.log(` ${
|
|
4778
|
-
if (result.eventFilters?.length) console.log(` ${
|
|
4779
|
-
if (result.webhookPayload?.id) console.log(` ${
|
|
4894
|
+
console.log(` ${pc9.dim("ID:")} ${result.id}`);
|
|
4895
|
+
console.log(` ${pc9.dim("URL:")} ${result.url}`);
|
|
4896
|
+
console.log(` ${pc9.dim("Active:")} ${result.active}`);
|
|
4897
|
+
if (result.description) console.log(` ${pc9.dim("Description:")} ${result.description}`);
|
|
4898
|
+
if (result.eventFilters?.length) console.log(` ${pc9.dim("Events:")} ${result.eventFilters.join(", ")}`);
|
|
4899
|
+
if (result.webhookPayload?.id) console.log(` ${pc9.dim("Webhook ID:")} ${result.webhookPayload.id}`);
|
|
4780
4900
|
if (result.warning) {
|
|
4781
4901
|
console.log();
|
|
4782
|
-
console.log(` ${
|
|
4902
|
+
console.log(` ${pc9.yellow("\u26A0 Warning:")} ${result.warning}`);
|
|
4783
4903
|
}
|
|
4784
4904
|
console.log();
|
|
4785
4905
|
} catch (error2) {
|
|
@@ -4825,12 +4945,12 @@ async function relayListCommand(options) {
|
|
|
4825
4945
|
{ key: "description", label: "Description" },
|
|
4826
4946
|
{ key: "events", label: "Events" },
|
|
4827
4947
|
{ key: "actions", label: "Actions" },
|
|
4828
|
-
{ key: "id", label: "ID", color:
|
|
4948
|
+
{ key: "id", label: "ID", color: pc9.dim }
|
|
4829
4949
|
],
|
|
4830
4950
|
endpoints.map((e) => ({
|
|
4831
|
-
status: e.active ?
|
|
4832
|
-
description: e.description ||
|
|
4833
|
-
events: e.eventFilters?.join(", ") ||
|
|
4951
|
+
status: e.active ? pc9.green("\u25CF") : pc9.dim("\u25CB"),
|
|
4952
|
+
description: e.description || pc9.dim("(none)"),
|
|
4953
|
+
events: e.eventFilters?.join(", ") || pc9.dim("all"),
|
|
4834
4954
|
actions: String(e.actions?.length || 0),
|
|
4835
4955
|
id: e.id.slice(0, 8)
|
|
4836
4956
|
}))
|
|
@@ -4853,18 +4973,18 @@ async function relayGetCommand(id) {
|
|
|
4853
4973
|
}
|
|
4854
4974
|
spinner5.stop("Relay endpoint loaded");
|
|
4855
4975
|
console.log();
|
|
4856
|
-
console.log(` ${
|
|
4857
|
-
console.log(` ${
|
|
4858
|
-
console.log(` ${
|
|
4859
|
-
if (result.description) console.log(` ${
|
|
4860
|
-
if (result.eventFilters?.length) console.log(` ${
|
|
4861
|
-
console.log(` ${
|
|
4976
|
+
console.log(` ${pc9.dim("ID:")} ${result.id}`);
|
|
4977
|
+
console.log(` ${pc9.dim("URL:")} ${result.url}`);
|
|
4978
|
+
console.log(` ${pc9.dim("Active:")} ${result.active}`);
|
|
4979
|
+
if (result.description) console.log(` ${pc9.dim("Description:")} ${result.description}`);
|
|
4980
|
+
if (result.eventFilters?.length) console.log(` ${pc9.dim("Events:")} ${result.eventFilters.join(", ")}`);
|
|
4981
|
+
console.log(` ${pc9.dim("Actions:")} ${result.actions?.length || 0}`);
|
|
4862
4982
|
if (result.actions?.length) {
|
|
4863
4983
|
for (const [i, action] of result.actions.entries()) {
|
|
4864
|
-
console.log(` ${
|
|
4984
|
+
console.log(` ${pc9.dim(`[${i}]`)} type=${action.type}${action.actionId ? ` actionId=${action.actionId}` : ""}${action.url ? ` url=${action.url}` : ""}`);
|
|
4865
4985
|
}
|
|
4866
4986
|
}
|
|
4867
|
-
console.log(` ${
|
|
4987
|
+
console.log(` ${pc9.dim("Created:")} ${result.createdAt}`);
|
|
4868
4988
|
console.log();
|
|
4869
4989
|
} catch (error2) {
|
|
4870
4990
|
spinner5.stop("Failed to load relay endpoint");
|
|
@@ -4889,9 +5009,9 @@ async function relayUpdateCommand(id, options) {
|
|
|
4889
5009
|
return;
|
|
4890
5010
|
}
|
|
4891
5011
|
spinner5.stop("Relay endpoint updated");
|
|
4892
|
-
console.log(` ${
|
|
4893
|
-
console.log(` ${
|
|
4894
|
-
console.log(` ${
|
|
5012
|
+
console.log(` ${pc9.dim("ID:")} ${result.id}`);
|
|
5013
|
+
console.log(` ${pc9.dim("Active:")} ${result.active}`);
|
|
5014
|
+
console.log(` ${pc9.dim("Actions:")} ${result.actions?.length || 0}`);
|
|
4895
5015
|
console.log();
|
|
4896
5016
|
} catch (error2) {
|
|
4897
5017
|
spinner5.stop("Failed to update relay endpoint");
|
|
@@ -4932,9 +5052,9 @@ async function relayActivateCommand(id, options) {
|
|
|
4932
5052
|
return;
|
|
4933
5053
|
}
|
|
4934
5054
|
spinner5.stop("Relay endpoint activated");
|
|
4935
|
-
console.log(` ${
|
|
4936
|
-
console.log(` ${
|
|
4937
|
-
console.log(` ${
|
|
5055
|
+
console.log(` ${pc9.dim("ID:")} ${result.id}`);
|
|
5056
|
+
console.log(` ${pc9.dim("Active:")} ${result.active}`);
|
|
5057
|
+
console.log(` ${pc9.dim("Actions:")} ${result.actions?.length || 0}`);
|
|
4938
5058
|
console.log();
|
|
4939
5059
|
} catch (error2) {
|
|
4940
5060
|
spinner5.stop("Failed to activate relay endpoint");
|
|
@@ -4979,11 +5099,11 @@ async function relayEventsCommand(options) {
|
|
|
4979
5099
|
{ key: "platform", label: "Platform" },
|
|
4980
5100
|
{ key: "eventType", label: "Event Type" },
|
|
4981
5101
|
{ key: "timestamp", label: "Timestamp" },
|
|
4982
|
-
{ key: "id", label: "ID", color:
|
|
5102
|
+
{ key: "id", label: "ID", color: pc9.dim }
|
|
4983
5103
|
],
|
|
4984
5104
|
events.map((e) => ({
|
|
4985
5105
|
platform: e.platform,
|
|
4986
|
-
eventType: e.eventType ||
|
|
5106
|
+
eventType: e.eventType || pc9.dim("unknown"),
|
|
4987
5107
|
timestamp: e.timestamp || e.createdAt,
|
|
4988
5108
|
id: e.id.slice(0, 8)
|
|
4989
5109
|
}))
|
|
@@ -5006,11 +5126,11 @@ async function relayEventGetCommand(id) {
|
|
|
5006
5126
|
}
|
|
5007
5127
|
spinner5.stop("Relay event loaded");
|
|
5008
5128
|
console.log();
|
|
5009
|
-
console.log(` ${
|
|
5010
|
-
console.log(` ${
|
|
5011
|
-
console.log(` ${
|
|
5012
|
-
console.log(` ${
|
|
5013
|
-
console.log(` ${
|
|
5129
|
+
console.log(` ${pc9.dim("ID:")} ${result.id}`);
|
|
5130
|
+
console.log(` ${pc9.dim("Platform:")} ${result.platform}`);
|
|
5131
|
+
console.log(` ${pc9.dim("Event:")} ${result.eventType}`);
|
|
5132
|
+
console.log(` ${pc9.dim("Timestamp:")} ${result.timestamp || result.createdAt}`);
|
|
5133
|
+
console.log(` ${pc9.dim("Payload:")}`);
|
|
5014
5134
|
console.log(JSON.stringify(result.payload, null, 2));
|
|
5015
5135
|
console.log();
|
|
5016
5136
|
} catch (error2) {
|
|
@@ -5047,11 +5167,11 @@ async function relayDeliveriesCommand(options) {
|
|
|
5047
5167
|
{ key: "error", label: "Error" }
|
|
5048
5168
|
],
|
|
5049
5169
|
items.map((d) => ({
|
|
5050
|
-
status: d.status === "success" ?
|
|
5051
|
-
code: d.statusCode != null ? String(d.statusCode) :
|
|
5170
|
+
status: d.status === "success" ? pc9.green(d.status) : pc9.red(d.status),
|
|
5171
|
+
code: d.statusCode != null ? String(d.statusCode) : pc9.dim("-"),
|
|
5052
5172
|
attempt: String(d.attempt),
|
|
5053
|
-
deliveredAt: d.deliveredAt ||
|
|
5054
|
-
error: d.error ?
|
|
5173
|
+
deliveredAt: d.deliveredAt || pc9.dim("-"),
|
|
5174
|
+
error: d.error ? pc9.red(d.error.slice(0, 50)) : pc9.dim("-")
|
|
5055
5175
|
}))
|
|
5056
5176
|
);
|
|
5057
5177
|
} catch (error2) {
|
|
@@ -5079,14 +5199,14 @@ async function relayPlatformsCommand() {
|
|
|
5079
5199
|
printTable(
|
|
5080
5200
|
[
|
|
5081
5201
|
{ key: "platform", label: "Platform" },
|
|
5082
|
-
{ key: "eventTypeCount", label: "Event types", color:
|
|
5202
|
+
{ key: "eventTypeCount", label: "Event types", color: pc9.dim }
|
|
5083
5203
|
],
|
|
5084
5204
|
platforms.map((p10) => ({ platform: p10.platform, eventTypeCount: String(p10.eventTypeCount) }))
|
|
5085
5205
|
);
|
|
5086
5206
|
console.log();
|
|
5087
5207
|
console.log(
|
|
5088
|
-
|
|
5089
|
-
` Run ${
|
|
5208
|
+
pc9.dim(
|
|
5209
|
+
` Run ${pc9.cyan("one relay event-types <platform>")} to see the full event list for a platform.
|
|
5090
5210
|
`
|
|
5091
5211
|
)
|
|
5092
5212
|
);
|
|
@@ -5099,7 +5219,7 @@ async function relayEventTypesCommand(platform) {
|
|
|
5099
5219
|
const { apiKey } = getConfig3();
|
|
5100
5220
|
const api = new OneApi(apiKey, getApiBase());
|
|
5101
5221
|
const spinner5 = createSpinner();
|
|
5102
|
-
spinner5.start(`Loading event types for ${
|
|
5222
|
+
spinner5.start(`Loading event types for ${pc9.cyan(platform)}...`);
|
|
5103
5223
|
try {
|
|
5104
5224
|
const eventTypes = await api.listRelayEventTypes(platform);
|
|
5105
5225
|
if (isAgentMode()) {
|
|
@@ -5810,7 +5930,7 @@ async function enrichPhase(api, db, config2, model, idField, connectionKey, plat
|
|
|
5810
5930
|
);
|
|
5811
5931
|
let batchHitRateLimit = false;
|
|
5812
5932
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
5813
|
-
const
|
|
5933
|
+
const pending2 = [];
|
|
5814
5934
|
for (let j = 0; j < results.length; j++) {
|
|
5815
5935
|
const result = results[j];
|
|
5816
5936
|
const row = batch[j];
|
|
@@ -5829,7 +5949,7 @@ async function enrichPhase(api, db, config2, model, idField, connectionKey, plat
|
|
|
5829
5949
|
const fp = merged[config2.invalidateOn] ?? row[config2.invalidateOn];
|
|
5830
5950
|
merged[ENRICH_FINGERPRINT_COLUMN] = fp == null ? null : String(fp);
|
|
5831
5951
|
}
|
|
5832
|
-
|
|
5952
|
+
pending2.push({ merged, id });
|
|
5833
5953
|
} else if (result.status === "fulfilled" && result.value === null) {
|
|
5834
5954
|
rateLimited++;
|
|
5835
5955
|
skipped++;
|
|
@@ -5838,14 +5958,14 @@ async function enrichPhase(api, db, config2, model, idField, connectionKey, plat
|
|
|
5838
5958
|
skipped++;
|
|
5839
5959
|
}
|
|
5840
5960
|
}
|
|
5841
|
-
let writes =
|
|
5842
|
-
if (ctx.transform &&
|
|
5843
|
-
const transformed = await transformRecords(ctx.transform,
|
|
5961
|
+
let writes = pending2;
|
|
5962
|
+
if (ctx.transform && pending2.length > 0) {
|
|
5963
|
+
const transformed = await transformRecords(ctx.transform, pending2.map((p10) => p10.merged));
|
|
5844
5964
|
if (transformed) {
|
|
5845
5965
|
const byId = /* @__PURE__ */ new Map();
|
|
5846
5966
|
for (const r of transformed) byId.set(r[idField], r);
|
|
5847
5967
|
writes = [];
|
|
5848
|
-
for (const p10 of
|
|
5968
|
+
for (const p10 of pending2) {
|
|
5849
5969
|
const t = byId.get(p10.id);
|
|
5850
5970
|
if (!t) continue;
|
|
5851
5971
|
if (!t[tsField]) t[tsField] = now;
|
|
@@ -7798,7 +7918,7 @@ function suggestSearchablePaths(records, limit = 15) {
|
|
|
7798
7918
|
// src/lib/memory/sync/index.ts
|
|
7799
7919
|
import { spawn as spawn4 } from "child_process";
|
|
7800
7920
|
import * as p7 from "@clack/prompts";
|
|
7801
|
-
import
|
|
7921
|
+
import pc10 from "picocolors";
|
|
7802
7922
|
async function syncInstallCommand() {
|
|
7803
7923
|
if (await isSqliteAvailable()) {
|
|
7804
7924
|
if (isAgentMode()) {
|
|
@@ -7863,15 +7983,15 @@ async function syncDoctorCommand() {
|
|
|
7863
7983
|
return;
|
|
7864
7984
|
}
|
|
7865
7985
|
for (const c of checks) {
|
|
7866
|
-
const mark = c.ok ?
|
|
7867
|
-
console.log(` ${mark} ${c.name}${c.detail ?
|
|
7986
|
+
const mark = c.ok ? pc10.green("\u2713") : pc10.red("\u2717");
|
|
7987
|
+
console.log(` ${mark} ${c.name}${c.detail ? pc10.dim(` \u2014 ${c.detail}`) : ""}`);
|
|
7868
7988
|
}
|
|
7869
7989
|
if (!allOk) {
|
|
7870
7990
|
console.log(`
|
|
7871
|
-
${
|
|
7991
|
+
${pc10.yellow("Sync is not ready.")} Try: ${pc10.bold("one sync install")}`);
|
|
7872
7992
|
} else {
|
|
7873
7993
|
console.log(`
|
|
7874
|
-
${
|
|
7994
|
+
${pc10.green("Sync is ready.")}`);
|
|
7875
7995
|
}
|
|
7876
7996
|
}
|
|
7877
7997
|
function getApi() {
|
|
@@ -7914,11 +8034,11 @@ async function syncProfilesCommand(platform) {
|
|
|
7914
8034
|
if (p10.enrich) extras.push("enrich");
|
|
7915
8035
|
if (p10.identityKey || p10.identityKeys) extras.push("identity");
|
|
7916
8036
|
if (p10.dateFilter) extras.push("incremental");
|
|
7917
|
-
const tags = extras.length > 0 ? ` ${
|
|
7918
|
-
console.log(` ${
|
|
8037
|
+
const tags = extras.length > 0 ? ` ${pc10.dim(`[${extras.join(", ")}]`)}` : "";
|
|
8038
|
+
console.log(` ${pc10.bold(`${p10.platform}/${p10.model}`.padEnd(35))} ${p10.description}${tags}`);
|
|
7919
8039
|
}
|
|
7920
8040
|
console.log(`
|
|
7921
|
-
${profiles.length} built-in profile(s). Run ${
|
|
8041
|
+
${profiles.length} built-in profile(s). Run ${pc10.bold("one sync init <platform> <model>")} to use one.`);
|
|
7922
8042
|
}
|
|
7923
8043
|
async function syncModelsCommand(platform) {
|
|
7924
8044
|
const api = getApi();
|
|
@@ -7936,7 +8056,7 @@ async function syncModelsCommand(platform) {
|
|
|
7936
8056
|
return;
|
|
7937
8057
|
}
|
|
7938
8058
|
const lines = models.map(
|
|
7939
|
-
(m) => ` ${
|
|
8059
|
+
(m) => ` ${pc10.bold(m.name.padEnd(30))} ${pc10.dim(m.listAction.method)} ${pc10.dim(m.listAction.path)}`
|
|
7940
8060
|
);
|
|
7941
8061
|
note(lines.join("\n"), `${platform} \u2014 ${models.length} models`);
|
|
7942
8062
|
} catch (err) {
|
|
@@ -8040,15 +8160,15 @@ async function syncInitCommand(platform, model, options) {
|
|
|
8040
8160
|
note(JSON.stringify(template, null, 2), "Sync profile template");
|
|
8041
8161
|
if (inferred && inferred.reasoning.length > 0) {
|
|
8042
8162
|
console.log(`
|
|
8043
|
-
${
|
|
8044
|
-
for (const r of inferred.reasoning) console.log(` ${
|
|
8163
|
+
${pc10.bold("Inferred from knowledge:")}`);
|
|
8164
|
+
for (const r of inferred.reasoning) console.log(` ${pc10.dim("\u2022")} ${r}`);
|
|
8045
8165
|
}
|
|
8046
8166
|
if (testReport) {
|
|
8047
8167
|
console.log(`
|
|
8048
|
-
${
|
|
8168
|
+
${pc10.bold("Test results:")}`);
|
|
8049
8169
|
for (const c of testReport.checks) {
|
|
8050
|
-
const mark = c.ok ?
|
|
8051
|
-
console.log(` ${mark} ${c.name}${c.detail ?
|
|
8170
|
+
const mark = c.ok ? pc10.green("\u2713") : pc10.red("\u2717");
|
|
8171
|
+
console.log(` ${mark} ${c.name}${c.detail ? pc10.dim(` \u2014 ${c.detail}`) : ""}`);
|
|
8052
8172
|
}
|
|
8053
8173
|
}
|
|
8054
8174
|
console.log(`
|
|
@@ -8131,17 +8251,17 @@ async function syncTestCommand(platformModel, options = {}) {
|
|
|
8131
8251
|
return;
|
|
8132
8252
|
}
|
|
8133
8253
|
for (const c of report.checks) {
|
|
8134
|
-
const mark = c.ok ?
|
|
8135
|
-
console.log(` ${mark} ${c.name}${c.detail ?
|
|
8254
|
+
const mark = c.ok ? pc10.green("\u2713") : pc10.red("\u2717");
|
|
8255
|
+
console.log(` ${mark} ${c.name}${c.detail ? pc10.dim(` \u2014 ${c.detail}`) : ""}`);
|
|
8136
8256
|
}
|
|
8137
8257
|
if (report.detectedColumns && report.detectedColumns.length > 0) {
|
|
8138
8258
|
console.log(`
|
|
8139
|
-
${
|
|
8259
|
+
${pc10.bold("Detected columns:")}`);
|
|
8140
8260
|
for (const col of report.detectedColumns.slice(0, 20)) {
|
|
8141
|
-
console.log(` ${col.name.padEnd(30)} ${
|
|
8261
|
+
console.log(` ${col.name.padEnd(30)} ${pc10.dim(col.type)}`);
|
|
8142
8262
|
}
|
|
8143
8263
|
if (report.detectedColumns.length > 20) {
|
|
8144
|
-
console.log(
|
|
8264
|
+
console.log(pc10.dim(` ... and ${report.detectedColumns.length - 20} more`));
|
|
8145
8265
|
}
|
|
8146
8266
|
}
|
|
8147
8267
|
if (report.identityKeysPreview) {
|
|
@@ -8149,45 +8269,45 @@ async function syncTestCommand(platformModel, options = {}) {
|
|
|
8149
8269
|
const total = perRecord.reduce((a, b) => a + b, 0);
|
|
8150
8270
|
const min = perRecord.length ? Math.min(...perRecord) : 0;
|
|
8151
8271
|
const max = perRecord.length ? Math.max(...perRecord) : 0;
|
|
8152
|
-
const mark = total === 0 ?
|
|
8272
|
+
const mark = total === 0 ? pc10.yellow("~") : pc10.green("\u2713");
|
|
8153
8273
|
console.log(`
|
|
8154
|
-
${
|
|
8274
|
+
${pc10.bold("Merge + identity keys")} ${pc10.dim(`(cross-platform \u2014 #128)`)}`);
|
|
8155
8275
|
console.log(` ${mark} ${perRecord.length} sample${perRecord.length === 1 ? "" : "s"}, ${min}\u2013${max} key${max === 1 ? "" : "s"} per record`);
|
|
8156
8276
|
if (sampleKeys.length > 0) {
|
|
8157
|
-
console.log(` ${
|
|
8277
|
+
console.log(` ${pc10.dim("e.g.")} ${sampleKeys.slice(0, 8).map((k) => pc10.cyan(k)).join(", ")}`);
|
|
8158
8278
|
} else if (resolvesAfterEnrich) {
|
|
8159
|
-
console.log(` ${
|
|
8279
|
+
console.log(` ${pc10.dim("note:")} 0 on these list-shape samples \u2014 this profile enriches, and its identityKeys paths resolve in the enrich phase.`);
|
|
8160
8280
|
} else {
|
|
8161
|
-
console.log(` ${
|
|
8281
|
+
console.log(` ${pc10.yellow("note:")} no identity keys resolved on these samples \u2014 check the identityKey/identityKeys paths.`);
|
|
8162
8282
|
}
|
|
8163
8283
|
if (entityFanOut) {
|
|
8164
|
-
console.log(` ${
|
|
8165
|
-
console.log(` ${
|
|
8166
|
-
console.log(` ${
|
|
8167
|
-
console.log(` ${
|
|
8284
|
+
console.log(` ${pc10.yellow("warn:")} identityKey resolved to MULTIPLE values on ${entityFanOut.count} of ${perRecord.length} samples \u2014 those records get NO merge key.`);
|
|
8285
|
+
console.log(` ${pc10.dim("saw:")} ${entityFanOut.sampleValues.map((v) => pc10.cyan(v)).join(", ")}`);
|
|
8286
|
+
console.log(` ${pc10.dim('A singular identityKey means "this record IS this entity", so a fan-out has no safe answer.')}`);
|
|
8287
|
+
console.log(` ${pc10.dim("Point it at a single-valued path, or move it to identityKeys[] for participant associations.")}`);
|
|
8168
8288
|
}
|
|
8169
8289
|
}
|
|
8170
8290
|
if (searchablePreview) {
|
|
8171
8291
|
console.log(`
|
|
8172
|
-
${
|
|
8173
|
-
console.log(` ${
|
|
8174
|
-
console.log(` ${
|
|
8292
|
+
${pc10.bold("Searchable preview")} ${pc10.dim(`(${searchablePreview.mode}, ${searchablePreview.sampledRecords} sample${searchablePreview.sampledRecords === 1 ? "" : "s"})`)}`);
|
|
8293
|
+
console.log(` ${pc10.dim("length:")} ${searchablePreview.length} chars (first sample)`);
|
|
8294
|
+
console.log(` ${pc10.dim("text:")} ${searchablePreview.text.slice(0, 300)}${searchablePreview.length > 300 ? pc10.dim(" \u2026") : ""}`);
|
|
8175
8295
|
if (searchablePreview.paths) {
|
|
8176
|
-
console.log(` ${
|
|
8296
|
+
console.log(` ${pc10.dim("paths:")} ${pc10.dim('(hit rate across all samples \u2014 differentiates "wrong path" from "field sometimes missing")')}`);
|
|
8177
8297
|
for (const p10 of searchablePreview.paths) {
|
|
8178
8298
|
const rate = `${p10.hits}/${p10.total}`;
|
|
8179
|
-
const mark = p10.hits === p10.total ?
|
|
8180
|
-
const trailer = p10.sample ?
|
|
8299
|
+
const mark = p10.hits === p10.total ? pc10.green("\u2713") : p10.hits === 0 ? pc10.red("\u2717") : pc10.yellow("~");
|
|
8300
|
+
const trailer = p10.sample ? pc10.dim(` \u2192 "${p10.sample}"`) : p10.hits === 0 ? pc10.dim(" (no sample matched \u2014 typo, or field never populated in this page)") : "";
|
|
8181
8301
|
console.log(` ${mark} ${rate.padStart(5)} ${p10.path}${trailer}`);
|
|
8182
8302
|
}
|
|
8183
8303
|
} else {
|
|
8184
|
-
console.log(` ${
|
|
8185
|
-
console.log(` ${
|
|
8304
|
+
console.log(` ${pc10.yellow("note:")} no memory.searchable declared \u2014 using the default walker (walks every field, often noisy).`);
|
|
8305
|
+
console.log(` ${pc10.dim("tip:")} run \`one sync suggest-searchable ${platform}/${model}\` for an auto-ranked starter list, or pick paths by hand and add them to profile.memory.searchable.`);
|
|
8186
8306
|
}
|
|
8187
8307
|
}
|
|
8188
8308
|
console.log(
|
|
8189
8309
|
`
|
|
8190
|
-
${report.ok ?
|
|
8310
|
+
${report.ok ? pc10.green("Profile looks good.") : pc10.red("Profile has issues.")} ` + (report.ok ? `Run: ${pc10.bold(`one sync run ${platform} --models ${model}`)}` : "Fix the issues above and test again.")
|
|
8191
8311
|
);
|
|
8192
8312
|
}
|
|
8193
8313
|
function buildSearchablePreview(profile, samples) {
|
|
@@ -8228,8 +8348,8 @@ async function syncRunCommand(platform, options) {
|
|
|
8228
8348
|
if (profileDrift.length > 0 && !isAgentMode()) {
|
|
8229
8349
|
for (const d of profileDrift) {
|
|
8230
8350
|
console.log(
|
|
8231
|
-
` ${
|
|
8232
|
-
Run ${
|
|
8351
|
+
` ${pc10.yellow("!")} ${platform}/${d.model} is missing ${d.missing.map((f) => pc10.bold(f)).join(", ")} from the current built-in profile.
|
|
8352
|
+
Run ${pc10.bold(`one sync init ${platform} ${d.model}`)} to pick ${d.missing.length > 1 ? "them" : "it"} up.`
|
|
8233
8353
|
);
|
|
8234
8354
|
}
|
|
8235
8355
|
}
|
|
@@ -8272,21 +8392,21 @@ async function syncRunCommand(platform, options) {
|
|
|
8272
8392
|
return;
|
|
8273
8393
|
}
|
|
8274
8394
|
for (const r of results) {
|
|
8275
|
-
const status = r.status === "complete" ?
|
|
8276
|
-
console.log(` ${
|
|
8395
|
+
const status = r.status === "complete" ? pc10.green("complete") : r.status === "dry-run" ? pc10.yellow("dry-run") : pc10.red("failed");
|
|
8396
|
+
console.log(` ${pc10.bold(r.model)} \u2014 ${r.recordsSynced} records, ${r.pagesProcessed} pages, ${r.duration} [${status}]`);
|
|
8277
8397
|
if (r.reconcileSkipped) {
|
|
8278
|
-
console.log(` ${
|
|
8398
|
+
console.log(` ${pc10.yellow("--full-refresh reconcile skipped \u2014 pagination truncated (e.g. --max-pages). Re-run without the cap to prune stale rows.")}`);
|
|
8279
8399
|
}
|
|
8280
8400
|
const sc = r.statusCounts;
|
|
8281
8401
|
if (sc && (sc.archived > 0 || sc.active > 0)) {
|
|
8282
|
-
const archivedColor = sc.archived > sc.active ?
|
|
8283
|
-
console.log(` memory: ${
|
|
8402
|
+
const archivedColor = sc.archived > sc.active ? pc10.red : pc10.dim;
|
|
8403
|
+
console.log(` memory: ${pc10.green(String(sc.active))} active, ${archivedColor(String(sc.archived))} archived`);
|
|
8284
8404
|
}
|
|
8285
8405
|
if (r.error) {
|
|
8286
8406
|
const errParts = [r.error.message];
|
|
8287
8407
|
if (r.error.httpStatus) errParts.push(`HTTP ${r.error.httpStatus}`);
|
|
8288
8408
|
if (r.error.retryAfter) errParts.push(`retry after ${r.error.retryAfter}s`);
|
|
8289
|
-
console.log(` ${
|
|
8409
|
+
console.log(` ${pc10.red(errParts.join(" \u2014 "))}`);
|
|
8290
8410
|
}
|
|
8291
8411
|
}
|
|
8292
8412
|
}
|
|
@@ -8312,8 +8432,8 @@ async function syncQueryCommand(platformModel, options) {
|
|
|
8312
8432
|
json(result);
|
|
8313
8433
|
return;
|
|
8314
8434
|
}
|
|
8315
|
-
console.log(
|
|
8316
|
-
console.log(
|
|
8435
|
+
console.log(pc10.dim(`Query: ${result.query}`));
|
|
8436
|
+
console.log(pc10.dim(`Source: local | Last sync: ${result.lastSync ?? "never"} | Age: ${result.syncAge ?? "n/a"}`));
|
|
8317
8437
|
console.log(JSON.stringify(result.results, null, 2));
|
|
8318
8438
|
console.log(`
|
|
8319
8439
|
${result.total} results`);
|
|
@@ -8335,7 +8455,7 @@ async function syncSearchCommand(query, options) {
|
|
|
8335
8455
|
return;
|
|
8336
8456
|
}
|
|
8337
8457
|
for (const r of result.results) {
|
|
8338
|
-
console.log(` ${
|
|
8458
|
+
console.log(` ${pc10.bold(`${r.platform}/${r.model}`)} ${pc10.dim(`(rank: ${r.rank.toFixed(2)})`)}`);
|
|
8339
8459
|
console.log(` ${JSON.stringify(r.record)}`);
|
|
8340
8460
|
}
|
|
8341
8461
|
console.log(`
|
|
@@ -8486,25 +8606,25 @@ async function syncSuggestSearchableCommand(platformModel, options = {}) {
|
|
|
8486
8606
|
return;
|
|
8487
8607
|
}
|
|
8488
8608
|
console.log(`
|
|
8489
|
-
${
|
|
8609
|
+
${pc10.bold("memory.searchable \u2014 ranked suggestions")} ${pc10.dim(`(${samples.length} samples)`)}`);
|
|
8490
8610
|
if (suggestions.length === 0) {
|
|
8491
|
-
console.log(` ${
|
|
8611
|
+
console.log(` ${pc10.yellow("no high-signal leaves found")} \u2014 page may be all UUIDs / timestamps / enum markers. Inspect the sample with \`sync test\` and pick paths manually.`);
|
|
8492
8612
|
return;
|
|
8493
8613
|
}
|
|
8494
8614
|
for (const s of suggestions) {
|
|
8495
8615
|
const hitPct = Math.round(s.hitRate * 100);
|
|
8496
8616
|
const noisePct = Math.round(s.noiseFraction * 100);
|
|
8497
|
-
const noiseBadge = noisePct > 0 ?
|
|
8617
|
+
const noiseBadge = noisePct > 0 ? pc10.dim(` noise=${noisePct}%`) : "";
|
|
8498
8618
|
console.log(
|
|
8499
|
-
` ${
|
|
8619
|
+
` ${pc10.green(String(s.score).padStart(5))} ${pc10.cyan(s.path.padEnd(52))}` + pc10.dim(` ${hitPct}% hit`) + pc10.dim(` avg=${s.avgLength}ch`) + noiseBadge + (s.sampleValue ? pc10.dim(`
|
|
8500
8620
|
\u2192 "${s.sampleValue.slice(0, 140)}"`) : "")
|
|
8501
8621
|
);
|
|
8502
8622
|
}
|
|
8503
8623
|
console.log(`
|
|
8504
|
-
${
|
|
8505
|
-
console.log(" " +
|
|
8624
|
+
${pc10.bold("Paste-ready:")}`);
|
|
8625
|
+
console.log(" " + pc10.cyan(`one sync init ${platform} ${model} --config '${JSON.stringify(configPatch)}'`));
|
|
8506
8626
|
console.log(`
|
|
8507
|
-
${
|
|
8627
|
+
${pc10.dim("then preview: ")}${pc10.cyan(`one sync test ${platform}/${model} --show-searchable`)}`);
|
|
8508
8628
|
}
|
|
8509
8629
|
async function syncListCommand(platform) {
|
|
8510
8630
|
const profiles = listProfiles(platform);
|
|
@@ -8538,10 +8658,10 @@ async function syncListCommand(platform) {
|
|
|
8538
8658
|
return;
|
|
8539
8659
|
}
|
|
8540
8660
|
for (const s of syncs) {
|
|
8541
|
-
const status = s.status === "idle" ?
|
|
8542
|
-
const legacy = s.legacyDbSize && s.legacyDbSize !== "0 B" ?
|
|
8661
|
+
const status = s.status === "idle" ? pc10.green("idle") : s.status === "syncing" ? pc10.yellow(`syncing \u2014 page ${s.pagesProcessed}`) : pc10.red("failed");
|
|
8662
|
+
const legacy = s.legacyDbSize && s.legacyDbSize !== "0 B" ? pc10.yellow(` legacy .db ${s.legacyDbSize}`) : "";
|
|
8543
8663
|
console.log(
|
|
8544
|
-
` ${
|
|
8664
|
+
` ${pc10.bold(`${s.platform}/${s.model}`.padEnd(35))} ${String(s.totalRecords).padStart(8)} records ${status} ${pc10.dim(s.lastSync ? `last: ${s.lastSync}` : "never synced")}` + legacy
|
|
8545
8665
|
);
|
|
8546
8666
|
}
|
|
8547
8667
|
}
|
|
@@ -8620,8 +8740,8 @@ async function syncScheduleAddCommand(platform, options) {
|
|
|
8620
8740
|
}
|
|
8621
8741
|
const verb = replaced ? "Replaced existing schedule" : "Scheduled sync";
|
|
8622
8742
|
outro(
|
|
8623
|
-
`${verb} ${
|
|
8624
|
-
Logs: ${
|
|
8743
|
+
`${verb} ${pc10.bold(entry.id)} \u2014 every ${pc10.bold(entry.every)} (cron: ${pc10.dim(entry.cronExpr)})
|
|
8744
|
+
Logs: ${pc10.dim(entry.logFile)}`
|
|
8625
8745
|
);
|
|
8626
8746
|
} catch (err) {
|
|
8627
8747
|
error(err instanceof Error ? err.message : String(err));
|
|
@@ -8640,14 +8760,14 @@ async function syncScheduleListCommand() {
|
|
|
8640
8760
|
}
|
|
8641
8761
|
for (const e of entries) {
|
|
8642
8762
|
const modelsStr = e.models ? ` [${e.models.join(",")}]` : "";
|
|
8643
|
-
const installed = e.cronInstalled ?
|
|
8763
|
+
const installed = e.cronInstalled ? pc10.green("\u25CF") : pc10.red("\u2717");
|
|
8644
8764
|
console.log(
|
|
8645
|
-
` ${installed} ${
|
|
8765
|
+
` ${installed} ${pc10.bold(e.id.padEnd(32))} every ${pc10.bold(e.every.padEnd(5))} ${pc10.dim(e.cronExpr.padEnd(13))}${modelsStr}`
|
|
8646
8766
|
);
|
|
8647
|
-
console.log(` ${
|
|
8767
|
+
console.log(` ${pc10.dim("cwd:")} ${e.cwd}`);
|
|
8648
8768
|
}
|
|
8649
8769
|
console.log(`
|
|
8650
|
-
${
|
|
8770
|
+
${pc10.dim("\u25CF = cron line installed \u2717 = registry drift, run `sync schedule repair <id>`")}`);
|
|
8651
8771
|
} catch (err) {
|
|
8652
8772
|
error(err instanceof Error ? err.message : String(err));
|
|
8653
8773
|
}
|
|
@@ -8671,7 +8791,7 @@ async function syncScheduleRemoveCommand(idOrPlatform, options) {
|
|
|
8671
8791
|
return;
|
|
8672
8792
|
}
|
|
8673
8793
|
for (const r of result.removed) {
|
|
8674
|
-
console.log(` ${
|
|
8794
|
+
console.log(` ${pc10.green("\u2713")} removed ${pc10.bold(r.id)} ${pc10.dim(`(${r.cwd})`)}`);
|
|
8675
8795
|
}
|
|
8676
8796
|
} catch (err) {
|
|
8677
8797
|
error(err instanceof Error ? err.message : String(err));
|
|
@@ -8689,21 +8809,21 @@ async function syncScheduleStatusCommand() {
|
|
|
8689
8809
|
return;
|
|
8690
8810
|
}
|
|
8691
8811
|
for (const s of statuses) {
|
|
8692
|
-
const driftMarker = s.drift === "ok" ?
|
|
8693
|
-
console.log(` ${driftMarker} ${
|
|
8694
|
-
console.log(` ${
|
|
8695
|
-
console.log(` ${
|
|
8696
|
-
console.log(` ${
|
|
8812
|
+
const driftMarker = s.drift === "ok" ? pc10.green("\u25CF") : s.drift === "missing-cron" ? pc10.red("\u2717 missing cron line") : pc10.yellow(`\u26A0 ${s.drift}`);
|
|
8813
|
+
console.log(` ${driftMarker} ${pc10.bold(s.entry.id)} \u2014 every ${s.entry.every} (${pc10.dim(s.entry.cronExpr)})`);
|
|
8814
|
+
console.log(` ${pc10.dim("cwd:")} ${s.entry.cwd}`);
|
|
8815
|
+
console.log(` ${pc10.dim("last run:")} ${s.lastRunAt ?? pc10.yellow("never")}`);
|
|
8816
|
+
console.log(` ${pc10.dim("log:")} ${s.entry.logFile} ${s.logExists ? pc10.dim(`(${s.logSize} bytes)`) : pc10.yellow("(empty)")}`);
|
|
8697
8817
|
if (s.logTail.length > 0) {
|
|
8698
|
-
console.log(
|
|
8818
|
+
console.log(pc10.dim(" last lines:"));
|
|
8699
8819
|
for (const line of s.logTail.slice(-3)) {
|
|
8700
|
-
console.log(
|
|
8820
|
+
console.log(pc10.dim(` ${line}`));
|
|
8701
8821
|
}
|
|
8702
8822
|
}
|
|
8703
8823
|
}
|
|
8704
8824
|
if (statuses.some((s) => s.drift !== "ok")) {
|
|
8705
8825
|
console.log(`
|
|
8706
|
-
${
|
|
8826
|
+
${pc10.yellow("Drift detected.")} Run ${pc10.bold("one sync schedule repair <id>")} to heal.`);
|
|
8707
8827
|
}
|
|
8708
8828
|
} catch (err) {
|
|
8709
8829
|
error(err instanceof Error ? err.message : String(err));
|
|
@@ -8716,7 +8836,7 @@ async function syncScheduleRepairCommand(id) {
|
|
|
8716
8836
|
json({ status: "repaired", ...healed });
|
|
8717
8837
|
return;
|
|
8718
8838
|
}
|
|
8719
|
-
outro(`Repaired ${
|
|
8839
|
+
outro(`Repaired ${pc10.bold(healed.id)}: re-installed cron line with current node/cli paths.`);
|
|
8720
8840
|
} catch (err) {
|
|
8721
8841
|
error(err instanceof Error ? err.message : String(err));
|
|
8722
8842
|
}
|
|
@@ -9207,7 +9327,7 @@ function parseValue(raw) {
|
|
|
9207
9327
|
}
|
|
9208
9328
|
|
|
9209
9329
|
// src/commands/mem/records.ts
|
|
9210
|
-
import
|
|
9330
|
+
import pc11 from "picocolors";
|
|
9211
9331
|
async function memAddCommand(type, dataRaw, flags) {
|
|
9212
9332
|
requireMemoryInit();
|
|
9213
9333
|
const data = parseJsonArg(dataRaw, "data");
|
|
@@ -9406,7 +9526,7 @@ function summarizeRecord(r) {
|
|
|
9406
9526
|
const v = d[field];
|
|
9407
9527
|
if (typeof v === "string" && v.trim()) return v.trim().slice(0, 80);
|
|
9408
9528
|
}
|
|
9409
|
-
return
|
|
9529
|
+
return pc11.dim("(untitled)");
|
|
9410
9530
|
}
|
|
9411
9531
|
function relativeTime(iso) {
|
|
9412
9532
|
if (!iso) return "";
|
|
@@ -9469,7 +9589,7 @@ async function memFindByKeyCommand(key, secondKey, flags) {
|
|
|
9469
9589
|
});
|
|
9470
9590
|
return;
|
|
9471
9591
|
}
|
|
9472
|
-
const label = matchedKeys.map((k) =>
|
|
9592
|
+
const label = matchedKeys.map((k) => pc11.cyan(k)).join(pc11.dim(" + "));
|
|
9473
9593
|
if (records.length === 0) {
|
|
9474
9594
|
console.log(`
|
|
9475
9595
|
No records linked to ${label}.
|
|
@@ -9477,27 +9597,27 @@ async function memFindByKeyCommand(key, secondKey, flags) {
|
|
|
9477
9597
|
return;
|
|
9478
9598
|
}
|
|
9479
9599
|
console.log();
|
|
9480
|
-
console.log(` ${label} ${
|
|
9600
|
+
console.log(` ${label} ${pc11.dim("\u2014")} ${records.length}${truncated ? "+" : ""} record${records.length === 1 ? "" : "s"} across ${byType.size} type${byType.size === 1 ? "" : "s"}`);
|
|
9481
9601
|
console.log();
|
|
9482
9602
|
const typeWidth = Math.min(30, Math.max(...[...byType.keys()].map((t) => t.length)));
|
|
9483
9603
|
for (const [type, list] of byType) {
|
|
9484
|
-
console.log(` ${
|
|
9604
|
+
console.log(` ${pc11.bold(type.padEnd(typeWidth))} ${pc11.dim(`${list.length} record${list.length === 1 ? "" : "s"}`)}`);
|
|
9485
9605
|
for (const r of list.slice(0, perType)) {
|
|
9486
|
-
console.log(` ${
|
|
9606
|
+
console.log(` ${pc11.dim("\xB7")} ${summarizeRecord(r)} ${pc11.dim(relativeTime(r.updated_at))} ${pc11.dim(r.id)}`);
|
|
9487
9607
|
}
|
|
9488
9608
|
if (list.length > perType) {
|
|
9489
|
-
console.log(` ${
|
|
9609
|
+
console.log(` ${pc11.dim(`\u2026 and ${list.length - perType} more (raise --limit)`)}`);
|
|
9490
9610
|
}
|
|
9491
9611
|
}
|
|
9492
9612
|
if (truncated) {
|
|
9493
9613
|
console.log();
|
|
9494
|
-
console.log(` ${
|
|
9614
|
+
console.log(` ${pc11.yellow("\u26A0")} Stopped at ${FIND_BY_KEY_FETCH_CAP} matches \u2014 there are more, and types sorting after the last one shown are missing entirely. Re-run with --type <type> to see them.`);
|
|
9495
9615
|
}
|
|
9496
9616
|
console.log();
|
|
9497
9617
|
}
|
|
9498
9618
|
|
|
9499
9619
|
// src/commands/mem/doctor.ts
|
|
9500
|
-
import
|
|
9620
|
+
import pc12 from "picocolors";
|
|
9501
9621
|
async function memDoctorCommand() {
|
|
9502
9622
|
const checks = [];
|
|
9503
9623
|
const cfg = getMemoryConfig();
|
|
@@ -9604,19 +9724,19 @@ function emit(checks, capInfo) {
|
|
|
9604
9724
|
return;
|
|
9605
9725
|
}
|
|
9606
9726
|
for (const c of checks) {
|
|
9607
|
-
const mark = c.ok ?
|
|
9608
|
-
const detail = c.detail ?
|
|
9727
|
+
const mark = c.ok ? pc12.green("\u2713") : pc12.red("\u2717");
|
|
9728
|
+
const detail = c.detail ? pc12.dim(` \u2014 ${c.detail}`) : "";
|
|
9609
9729
|
console.log(` ${mark} ${c.name}${detail}`);
|
|
9610
9730
|
}
|
|
9611
9731
|
if (!allOk) {
|
|
9612
|
-
console.log("\n" +
|
|
9732
|
+
console.log("\n" + pc12.yellow("Memory is not fully healthy."));
|
|
9613
9733
|
process.exitCode = 1;
|
|
9614
9734
|
} else {
|
|
9615
|
-
console.log("\n" +
|
|
9735
|
+
console.log("\n" + pc12.green("Memory is healthy."));
|
|
9616
9736
|
}
|
|
9617
9737
|
const line = semanticSearchUpgradeLine({ vectorSearchAvailable: capInfo.vectorSearchAvailable });
|
|
9618
9738
|
if (line) console.log(`
|
|
9619
|
-
${
|
|
9739
|
+
${pc12.dim(line)}`);
|
|
9620
9740
|
}
|
|
9621
9741
|
|
|
9622
9742
|
// src/commands/mem/export.ts
|
|
@@ -9911,7 +10031,7 @@ function registerMemoryCommands(program2) {
|
|
|
9911
10031
|
}
|
|
9912
10032
|
|
|
9913
10033
|
// src/commands/cache.ts
|
|
9914
|
-
import
|
|
10034
|
+
import pc13 from "picocolors";
|
|
9915
10035
|
async function cacheClearCommand(actionId) {
|
|
9916
10036
|
if (actionId) {
|
|
9917
10037
|
const deleted = clearEntry(actionId);
|
|
@@ -9920,9 +10040,9 @@ async function cacheClearCommand(actionId) {
|
|
|
9920
10040
|
return;
|
|
9921
10041
|
}
|
|
9922
10042
|
if (deleted) {
|
|
9923
|
-
console.log(`Cleared cache for ${
|
|
10043
|
+
console.log(`Cleared cache for ${pc13.cyan(actionId)}`);
|
|
9924
10044
|
} else {
|
|
9925
|
-
console.log(`No cache entry found for ${
|
|
10045
|
+
console.log(`No cache entry found for ${pc13.dim(actionId)}`);
|
|
9926
10046
|
}
|
|
9927
10047
|
} else {
|
|
9928
10048
|
const count = clearAll();
|
|
@@ -9959,7 +10079,7 @@ async function cacheListCommand(options) {
|
|
|
9959
10079
|
type: e.type,
|
|
9960
10080
|
key: e.entry.key,
|
|
9961
10081
|
age: formatAge(getAge(e.entry)),
|
|
9962
|
-
status: isFresh(e.entry) ?
|
|
10082
|
+
status: isFresh(e.entry) ? pc13.green("fresh") : pc13.yellow("expired")
|
|
9963
10083
|
}));
|
|
9964
10084
|
printTable(
|
|
9965
10085
|
[
|
|
@@ -10050,13 +10170,13 @@ async function cacheUpdateAllCommand() {
|
|
|
10050
10170
|
if (errors.length > 0) {
|
|
10051
10171
|
console.log();
|
|
10052
10172
|
for (const e of errors) {
|
|
10053
|
-
console.log(` ${
|
|
10173
|
+
console.log(` ${pc13.red("\u2717")} ${e.key}: ${pc13.dim(e.error)}`);
|
|
10054
10174
|
}
|
|
10055
10175
|
}
|
|
10056
10176
|
}
|
|
10057
10177
|
|
|
10058
10178
|
// src/commands/guide.ts
|
|
10059
|
-
import
|
|
10179
|
+
import pc14 from "picocolors";
|
|
10060
10180
|
|
|
10061
10181
|
// src/lib/guide-content.ts
|
|
10062
10182
|
var GUIDE_OVERVIEW = `# One CLI \u2014 Agent Guide
|
|
@@ -10884,6 +11004,12 @@ one sync schedule repair <id> # Re-install broken cron line
|
|
|
10884
11004
|
\`\`\`
|
|
10885
11005
|
Backed by system cron (macOS/Linux). Schedules tracked in a global registry at \`~/.one/sync/schedules.json\`.
|
|
10886
11006
|
|
|
11007
|
+
Cron runs jobs with a bare \`PATH=/usr/bin:/bin\`. The CLI pins the absolute \`node\` and CLI paths into the cron
|
|
11008
|
+
line, and its background auto-updater resolves \`npm\` next to that \`node\` rather than through \`PATH\`, so a
|
|
11009
|
+
scheduled install still upgrades itself. If an install repeatedly fails anyway, the reason is appended to
|
|
11010
|
+
\`~/.one/auto-update.log\` and a warning goes to stderr \u2014 check there before assuming a schedule is running the
|
|
11011
|
+
current version. \`one --agent sync schedule status\` reports drift and tails the logs.
|
|
11012
|
+
|
|
10887
11013
|
## Record Enrichment
|
|
10888
11014
|
|
|
10889
11015
|
When a list endpoint returns lightweight records (e.g. just IDs), add an \`enrich\` config to call a detail endpoint per record and merge the full data before storing:
|
|
@@ -11211,14 +11337,14 @@ async function guideCommand(topic = "all") {
|
|
|
11211
11337
|
json({ topic, title, content, availableTopics });
|
|
11212
11338
|
return;
|
|
11213
11339
|
}
|
|
11214
|
-
intro(
|
|
11340
|
+
intro(pc14.bgCyan(pc14.black(" One Guide ")));
|
|
11215
11341
|
console.log();
|
|
11216
11342
|
console.log(content);
|
|
11217
|
-
console.log(
|
|
11343
|
+
console.log(pc14.dim("\u2500".repeat(60)));
|
|
11218
11344
|
console.log(
|
|
11219
|
-
|
|
11345
|
+
pc14.dim("Available topics: ") + availableTopics.map((t) => pc14.cyan(t.topic)).join(", ")
|
|
11220
11346
|
);
|
|
11221
|
-
console.log(
|
|
11347
|
+
console.log(pc14.dim(`Run ${pc14.cyan("one guide <topic>")} for a specific section.`));
|
|
11222
11348
|
}
|
|
11223
11349
|
|
|
11224
11350
|
// src/lib/platform-meta.ts
|
|
@@ -11541,20 +11667,20 @@ function buildWorkflowIdeas(connections) {
|
|
|
11541
11667
|
// src/commands/logout.ts
|
|
11542
11668
|
import fs12 from "fs";
|
|
11543
11669
|
import * as p9 from "@clack/prompts";
|
|
11544
|
-
function formatWhoami(config2, apiKey,
|
|
11670
|
+
function formatWhoami(config2, apiKey, pc16) {
|
|
11545
11671
|
const whoami = config2.whoami;
|
|
11546
11672
|
const env = getEnvFromApiKey(apiKey);
|
|
11547
|
-
const envLabel = env === "test" ?
|
|
11673
|
+
const envLabel = env === "test" ? pc16.yellow("test") : pc16.green("live");
|
|
11548
11674
|
const lines = [];
|
|
11549
11675
|
if (whoami) {
|
|
11550
11676
|
const contextParts = [];
|
|
11551
11677
|
if (whoami.organization) contextParts.push(whoami.organization.name);
|
|
11552
11678
|
if (whoami.project) contextParts.push(whoami.project.name);
|
|
11553
11679
|
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
11554
|
-
lines.push(`${
|
|
11555
|
-
lines.push(`${whoami.user.name} ${
|
|
11680
|
+
lines.push(`${pc16.bold(scopeDisplay)} ${pc16.dim("\xB7")} ${envLabel}`);
|
|
11681
|
+
lines.push(`${whoami.user.name} ${pc16.dim(`(${whoami.user.email})`)}`);
|
|
11556
11682
|
} else {
|
|
11557
|
-
lines.push(`${
|
|
11683
|
+
lines.push(`${pc16.dim("Key:")} ${apiKey.slice(0, 8)}... ${pc16.dim("\xB7")} ${envLabel}`);
|
|
11558
11684
|
}
|
|
11559
11685
|
return lines;
|
|
11560
11686
|
}
|
|
@@ -11583,7 +11709,7 @@ async function logoutCommand() {
|
|
|
11583
11709
|
json({ status: cleared ? "logged_out" : "not_logged_in", message: cleared ? "Credentials cleared." : "No config found." });
|
|
11584
11710
|
return;
|
|
11585
11711
|
}
|
|
11586
|
-
const
|
|
11712
|
+
const pc16 = (await import("picocolors")).default;
|
|
11587
11713
|
const globalConfig = readGlobalConfig();
|
|
11588
11714
|
const projectConfig = readProjectConfig();
|
|
11589
11715
|
const hasGlobal = globalConfig?.apiKey != null;
|
|
@@ -11592,13 +11718,13 @@ async function logoutCommand() {
|
|
|
11592
11718
|
if (hasGlobal && hasProject) {
|
|
11593
11719
|
const infoLines = ["You are logged in with multiple configs.", ""];
|
|
11594
11720
|
if (projectConfig) {
|
|
11595
|
-
infoLines.push(`${
|
|
11596
|
-
infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey,
|
|
11721
|
+
infoLines.push(`${pc16.cyan("Local config:")}`);
|
|
11722
|
+
infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey, pc16));
|
|
11597
11723
|
infoLines.push("");
|
|
11598
11724
|
}
|
|
11599
11725
|
if (globalConfig) {
|
|
11600
|
-
infoLines.push(`${
|
|
11601
|
-
infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey,
|
|
11726
|
+
infoLines.push(`${pc16.magenta("Global config:")}`);
|
|
11727
|
+
infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey, pc16));
|
|
11602
11728
|
}
|
|
11603
11729
|
p9.note(infoLines.join("\n"));
|
|
11604
11730
|
const choice = await p9.select({
|
|
@@ -11616,14 +11742,14 @@ async function logoutCommand() {
|
|
|
11616
11742
|
targetScope = choice;
|
|
11617
11743
|
} else if (hasProject) {
|
|
11618
11744
|
const infoLines = ["You are logged in.", ""];
|
|
11619
|
-
infoLines.push(`${
|
|
11620
|
-
infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey,
|
|
11745
|
+
infoLines.push(`${pc16.dim("Stored in")} ${pc16.cyan("local config")}`);
|
|
11746
|
+
infoLines.push(...formatWhoami(projectConfig, projectConfig.apiKey, pc16));
|
|
11621
11747
|
p9.note(infoLines.join("\n"));
|
|
11622
11748
|
targetScope = "project";
|
|
11623
11749
|
} else if (hasGlobal) {
|
|
11624
11750
|
const infoLines = ["You are logged in.", ""];
|
|
11625
|
-
infoLines.push(`${
|
|
11626
|
-
infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey,
|
|
11751
|
+
infoLines.push(`${pc16.dim("Stored in")} ${pc16.magenta("global config")}`);
|
|
11752
|
+
infoLines.push(...formatWhoami(globalConfig, globalConfig.apiKey, pc16));
|
|
11627
11753
|
p9.note(infoLines.join("\n"));
|
|
11628
11754
|
targetScope = "global";
|
|
11629
11755
|
} else {
|
|
@@ -11660,12 +11786,24 @@ async function logoutCommand() {
|
|
|
11660
11786
|
// src/lib/analytics.ts
|
|
11661
11787
|
import { createRequire as createRequire2 } from "module";
|
|
11662
11788
|
import { randomUUID, createHash } from "crypto";
|
|
11663
|
-
import
|
|
11789
|
+
import pc15 from "picocolors";
|
|
11664
11790
|
var require3 = createRequire2(import.meta.url);
|
|
11665
11791
|
var DEFAULT_POSTHOG_HOST = "https://us.i.posthog.com";
|
|
11666
11792
|
var DEFAULT_POSTHOG_KEY = "phc_a9ok4w0uxiZcVoSWOISIlin85lHMXQD3vWPaYnuRlRV";
|
|
11793
|
+
var SEND_MAX_ATTEMPTS = 3;
|
|
11794
|
+
var QUEUE_MAX_AGE_MS = 24 * 60 * 60 * 1e3;
|
|
11795
|
+
var EXIT_GRACE_MS = 300;
|
|
11667
11796
|
var inFlight = /* @__PURE__ */ new Set();
|
|
11797
|
+
var pending = /* @__PURE__ */ new Set();
|
|
11798
|
+
var dispatched = /* @__PURE__ */ new Set();
|
|
11668
11799
|
var delivered = /* @__PURE__ */ new Set();
|
|
11800
|
+
var UUID_SHAPE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
11801
|
+
function uuidFromInsertId(insertId) {
|
|
11802
|
+
if (UUID_SHAPE.test(insertId)) return insertId.toLowerCase();
|
|
11803
|
+
const h = createHash("sha1").update(`one-cli-event:${insertId}`).digest("hex");
|
|
11804
|
+
const variant = (parseInt(h[16], 16) & 3 | 8).toString(16);
|
|
11805
|
+
return `${h.slice(0, 8)}-${h.slice(8, 12)}-5${h.slice(13, 16)}-${variant}${h.slice(17, 20)}-${h.slice(20, 32)}`;
|
|
11806
|
+
}
|
|
11669
11807
|
function posthogHost() {
|
|
11670
11808
|
return process.env.ONE_POSTHOG_HOST || DEFAULT_POSTHOG_HOST;
|
|
11671
11809
|
}
|
|
@@ -11721,9 +11859,10 @@ function personSet() {
|
|
|
11721
11859
|
}
|
|
11722
11860
|
function send(item) {
|
|
11723
11861
|
const insertId = item.properties.$insert_id;
|
|
11862
|
+
if (insertId) dispatched.add(insertId);
|
|
11724
11863
|
const controller = new AbortController();
|
|
11725
11864
|
inFlight.add(controller);
|
|
11726
|
-
|
|
11865
|
+
const run = (async () => {
|
|
11727
11866
|
try {
|
|
11728
11867
|
const res = await fetch(`${posthogHost()}/i/v0/e/`, {
|
|
11729
11868
|
method: "POST",
|
|
@@ -11732,6 +11871,8 @@ function send(item) {
|
|
|
11732
11871
|
api_key: posthogKey(),
|
|
11733
11872
|
event: item.event,
|
|
11734
11873
|
distinct_id: item.distinct_id,
|
|
11874
|
+
// PostHog's dedupe key — a re-sent copy is dropped on ingest.
|
|
11875
|
+
uuid: item.uuid ?? (insertId ? uuidFromInsertId(insertId) : void 0),
|
|
11735
11876
|
properties: item.properties,
|
|
11736
11877
|
timestamp: item.timestamp
|
|
11737
11878
|
}),
|
|
@@ -11745,6 +11886,8 @@ function send(item) {
|
|
|
11745
11886
|
inFlight.delete(controller);
|
|
11746
11887
|
}
|
|
11747
11888
|
})();
|
|
11889
|
+
pending.add(run);
|
|
11890
|
+
void run.finally(() => pending.delete(run));
|
|
11748
11891
|
}
|
|
11749
11892
|
function capture(event, properties = {}, opts = {}) {
|
|
11750
11893
|
if (isTelemetryDisabled()) {
|
|
@@ -11754,7 +11897,10 @@ function capture(event, properties = {}, opts = {}) {
|
|
|
11754
11897
|
const did = opts.distinctId ?? distinctId();
|
|
11755
11898
|
const props = { ...baseProperties(), ...properties };
|
|
11756
11899
|
if (props.$insert_id === void 0) props.$insert_id = randomUUID();
|
|
11757
|
-
|
|
11900
|
+
const insertId = props.$insert_id;
|
|
11901
|
+
if (opts.personProfile === false) {
|
|
11902
|
+
props.$process_person_profile = false;
|
|
11903
|
+
} else if (did === distinctId()) {
|
|
11758
11904
|
const set = personSet();
|
|
11759
11905
|
if (set) props.$set = set;
|
|
11760
11906
|
}
|
|
@@ -11762,7 +11908,8 @@ function capture(event, properties = {}, opts = {}) {
|
|
|
11762
11908
|
event,
|
|
11763
11909
|
distinct_id: did,
|
|
11764
11910
|
properties: props,
|
|
11765
|
-
timestamp: opts.timestamp ?? (/* @__PURE__ */ new Date()).toISOString()
|
|
11911
|
+
timestamp: opts.timestamp ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
11912
|
+
uuid: uuidFromInsertId(insertId)
|
|
11766
11913
|
};
|
|
11767
11914
|
appendAnalyticsQueue(JSON.stringify(item));
|
|
11768
11915
|
}
|
|
@@ -11856,7 +12003,12 @@ function emitRollup(did, group) {
|
|
|
11856
12003
|
window_end: new Date(group[group.length - 1].ts).toISOString(),
|
|
11857
12004
|
$insert_id: insertId
|
|
11858
12005
|
},
|
|
11859
|
-
{
|
|
12006
|
+
{
|
|
12007
|
+
distinctId: did,
|
|
12008
|
+
timestamp: new Date(group[group.length - 1].ts).toISOString(),
|
|
12009
|
+
// Rollups bill at the anonymous rate; the person already exists.
|
|
12010
|
+
personProfile: false
|
|
12011
|
+
}
|
|
11860
12012
|
);
|
|
11861
12013
|
debugLog(`rollup \u2014 ${group.length} command(s) for ${did}`);
|
|
11862
12014
|
}
|
|
@@ -11874,32 +12026,69 @@ function drainQueue() {
|
|
|
11874
12026
|
writeAnalyticsQueue([]);
|
|
11875
12027
|
return;
|
|
11876
12028
|
}
|
|
12029
|
+
const now = Date.now();
|
|
12030
|
+
const kept = [];
|
|
12031
|
+
let changed = false;
|
|
11877
12032
|
for (const line of readAnalyticsQueue()) {
|
|
12033
|
+
let item;
|
|
11878
12034
|
try {
|
|
11879
|
-
|
|
11880
|
-
if (item?.properties?.$insert_id) send(item);
|
|
12035
|
+
item = JSON.parse(line);
|
|
11881
12036
|
} catch {
|
|
12037
|
+
changed = true;
|
|
12038
|
+
continue;
|
|
12039
|
+
}
|
|
12040
|
+
const insertId = item?.properties?.$insert_id;
|
|
12041
|
+
if (!insertId) {
|
|
12042
|
+
changed = true;
|
|
12043
|
+
continue;
|
|
12044
|
+
}
|
|
12045
|
+
const age = now - Date.parse(item.timestamp);
|
|
12046
|
+
const attempts = item.attempts ?? 0;
|
|
12047
|
+
if (!(age < QUEUE_MAX_AGE_MS) || attempts >= SEND_MAX_ATTEMPTS) {
|
|
12048
|
+
debugLog(`"${item.event}" dropped (${attempts} attempts, ${Math.round(age / 6e4)} min old)`);
|
|
12049
|
+
changed = true;
|
|
12050
|
+
continue;
|
|
11882
12051
|
}
|
|
12052
|
+
if (dispatched.has(insertId)) {
|
|
12053
|
+
kept.push(line);
|
|
12054
|
+
continue;
|
|
12055
|
+
}
|
|
12056
|
+
item.attempts = attempts + 1;
|
|
12057
|
+
if (!item.uuid) item.uuid = uuidFromInsertId(insertId);
|
|
12058
|
+
kept.push(JSON.stringify(item));
|
|
12059
|
+
changed = true;
|
|
12060
|
+
send(item);
|
|
11883
12061
|
}
|
|
12062
|
+
if (changed) writeAnalyticsQueue(kept);
|
|
11884
12063
|
}
|
|
11885
|
-
function flush() {
|
|
12064
|
+
async function flush() {
|
|
12065
|
+
if (pending.size > 0) {
|
|
12066
|
+
await Promise.race([
|
|
12067
|
+
Promise.allSettled([...pending]),
|
|
12068
|
+
new Promise((resolve) => setTimeout(resolve, EXIT_GRACE_MS))
|
|
12069
|
+
]);
|
|
12070
|
+
}
|
|
11886
12071
|
for (const controller of inFlight) controller.abort();
|
|
11887
12072
|
const remaining = readAnalyticsQueue().filter((line) => {
|
|
11888
12073
|
try {
|
|
11889
|
-
const
|
|
11890
|
-
|
|
12074
|
+
const item = JSON.parse(line);
|
|
12075
|
+
const id = item.properties?.$insert_id;
|
|
12076
|
+
if (!id || delivered.has(id)) return false;
|
|
12077
|
+
return (item.attempts ?? 0) < SEND_MAX_ATTEMPTS;
|
|
11891
12078
|
} catch {
|
|
11892
12079
|
return false;
|
|
11893
12080
|
}
|
|
11894
12081
|
});
|
|
11895
12082
|
writeAnalyticsQueue(remaining);
|
|
12083
|
+
dispatched.clear();
|
|
12084
|
+
delivered.clear();
|
|
11896
12085
|
}
|
|
11897
12086
|
function maybeShowTelemetryNotice() {
|
|
11898
12087
|
if (isTelemetryDisabled() || isAgentMode()) return;
|
|
11899
12088
|
if (telemetryNoticeShown()) return;
|
|
11900
12089
|
markTelemetryNoticeShown();
|
|
11901
12090
|
process.stderr.write(
|
|
11902
|
-
|
|
12091
|
+
pc15.dim(
|
|
11903
12092
|
"One CLI collects usage analytics (which commands run, linked to your One account) to improve the product.\nNo arguments, inputs, or secrets are ever collected. Opt out anytime with ONE_NO_TELEMETRY=1.\n"
|
|
11904
12093
|
)
|
|
11905
12094
|
);
|
|
@@ -12006,7 +12195,8 @@ program.hook("preAction", (thisCommand, actionCommand) => {
|
|
|
12006
12195
|
program.hook("postAction", async () => {
|
|
12007
12196
|
await closeBackendIfCached();
|
|
12008
12197
|
flushUsageRollups();
|
|
12009
|
-
|
|
12198
|
+
drainQueue();
|
|
12199
|
+
await flush();
|
|
12010
12200
|
if (!updateCheckPromise) return;
|
|
12011
12201
|
const info = await updateCheckPromise;
|
|
12012
12202
|
if (!info) return;
|
|
@@ -12328,21 +12518,21 @@ program.command("whoami").description("Show the user, organization, and project
|
|
|
12328
12518
|
});
|
|
12329
12519
|
return;
|
|
12330
12520
|
}
|
|
12331
|
-
const
|
|
12521
|
+
const pc16 = (await import("picocolors")).default;
|
|
12332
12522
|
const contextParts = [];
|
|
12333
12523
|
if (whoami.organization) contextParts.push(whoami.organization.name);
|
|
12334
12524
|
if (whoami.project) contextParts.push(whoami.project.name);
|
|
12335
12525
|
const scopeDisplay = contextParts.length > 0 ? contextParts.join(" / ") : "Personal";
|
|
12336
|
-
const envLabel = env === "test" ?
|
|
12337
|
-
const configLabel = configScope === "project" ?
|
|
12526
|
+
const envLabel = env === "test" ? pc16.yellow("test") : pc16.green("live");
|
|
12527
|
+
const configLabel = configScope === "project" ? pc16.cyan("project config") : pc16.magenta("global config");
|
|
12338
12528
|
console.log();
|
|
12339
|
-
console.log(` ${
|
|
12340
|
-
console.log(` ${whoami.user.name} ${
|
|
12341
|
-
if (whoami.organization) console.log(` ${
|
|
12342
|
-
if (whoami.project) console.log(` ${
|
|
12529
|
+
console.log(` ${pc16.bold(scopeDisplay)} ${pc16.dim("\xB7")} ${envLabel}`);
|
|
12530
|
+
console.log(` ${whoami.user.name} ${pc16.dim(`(${whoami.user.email})`)}`);
|
|
12531
|
+
if (whoami.organization) console.log(` ${pc16.dim("Org:")} ${whoami.organization.name} ${pc16.dim(`(${whoami.organization.id})`)}`);
|
|
12532
|
+
if (whoami.project) console.log(` ${pc16.dim("Project:")} ${whoami.project.name} ${pc16.dim(`(${whoami.project.id})`)}`);
|
|
12343
12533
|
console.log();
|
|
12344
|
-
console.log(` ${
|
|
12345
|
-
console.log(` ${
|
|
12534
|
+
console.log(` ${pc16.dim("Using")} ${configLabel}`);
|
|
12535
|
+
console.log(` ${pc16.dim("API:")} ${apiBase}`);
|
|
12346
12536
|
console.log();
|
|
12347
12537
|
});
|
|
12348
12538
|
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) => {
|