@withone/cli 1.16.0 → 1.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-SX2Y4HDW.js → chunk-QW4MBV4F.js} +6 -4
- package/dist/{flow-runner-7RUK2WMF.js → flow-runner-AJGIUT6E.js} +1 -1
- package/dist/index.js +301 -274
- package/package.json +1 -1
- package/skills/one/SKILL.md +116 -0
- package/skills/one/references/flows.md +278 -0
- package/skills/one/references/relay.md +179 -0
- package/skills/one-actions/SKILL.md +0 -157
- package/skills/one-flow/SKILL.md +0 -917
- package/skills/one-relay/SKILL.md +0 -303
package/dist/index.js
CHANGED
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
loadFlow,
|
|
12
12
|
resolveFlowPath,
|
|
13
13
|
saveFlow
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-QW4MBV4F.js";
|
|
15
15
|
|
|
16
16
|
// src/index.ts
|
|
17
17
|
import { createRequire as createRequire2 } from "module";
|
|
@@ -19,9 +19,10 @@ import { Command } from "commander";
|
|
|
19
19
|
|
|
20
20
|
// src/commands/init.ts
|
|
21
21
|
import * as p3 from "@clack/prompts";
|
|
22
|
-
import
|
|
22
|
+
import pc2 from "picocolors";
|
|
23
|
+
import fs3 from "fs";
|
|
23
24
|
import path3 from "path";
|
|
24
|
-
import
|
|
25
|
+
import os3 from "os";
|
|
25
26
|
import { fileURLToPath } from "url";
|
|
26
27
|
|
|
27
28
|
// src/lib/config.ts
|
|
@@ -530,122 +531,69 @@ function formatList(list) {
|
|
|
530
531
|
|
|
531
532
|
// src/commands/init.ts
|
|
532
533
|
import open2 from "open";
|
|
533
|
-
|
|
534
|
-
// src/lib/table.ts
|
|
535
|
-
import pc2 from "picocolors";
|
|
536
|
-
function printTable(columns, rows) {
|
|
537
|
-
if (rows.length === 0) return;
|
|
538
|
-
const gap = " ";
|
|
539
|
-
const indent = " ";
|
|
540
|
-
const widths = columns.map((col) => {
|
|
541
|
-
const headerLen = col.label.length;
|
|
542
|
-
const maxValueLen = Math.max(...rows.map((row) => stripAnsi(row[col.key] || "").length));
|
|
543
|
-
return Math.max(headerLen, maxValueLen);
|
|
544
|
-
});
|
|
545
|
-
const header = columns.map((col, i) => {
|
|
546
|
-
const padded = col.align === "right" ? col.label.padStart(widths[i]) : col.label.padEnd(widths[i]);
|
|
547
|
-
return pc2.dim(padded);
|
|
548
|
-
}).join(gap);
|
|
549
|
-
console.log(`${indent}${header}`);
|
|
550
|
-
const separator = columns.map((_, i) => pc2.dim("\u2500".repeat(widths[i]))).join(gap);
|
|
551
|
-
console.log(`${indent}${separator}`);
|
|
552
|
-
for (const row of rows) {
|
|
553
|
-
const line = columns.map((col, i) => {
|
|
554
|
-
const raw = row[col.key] || "";
|
|
555
|
-
const rawLen = stripAnsi(raw).length;
|
|
556
|
-
const padding = widths[i] - rawLen;
|
|
557
|
-
const colored = col.color ? col.color(raw) : raw;
|
|
558
|
-
if (col.align === "right") {
|
|
559
|
-
return " ".repeat(Math.max(0, padding)) + colored;
|
|
560
|
-
}
|
|
561
|
-
return colored + " ".repeat(Math.max(0, padding));
|
|
562
|
-
}).join(gap);
|
|
563
|
-
console.log(`${indent}${line}`);
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
function stripAnsi(str) {
|
|
567
|
-
return str.replace(/\x1b\[[0-9;]*m/g, "");
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
// src/commands/init.ts
|
|
571
534
|
async function initCommand(options) {
|
|
572
535
|
if (isAgentMode()) {
|
|
573
536
|
error("This command requires interactive input. Run without --agent.");
|
|
574
537
|
}
|
|
575
538
|
const existingConfig = readConfig();
|
|
539
|
+
printBanner();
|
|
576
540
|
if (existingConfig) {
|
|
577
|
-
p3.intro(pc3.bgCyan(pc3.black(" One ")));
|
|
578
541
|
await handleExistingConfig(existingConfig.apiKey, options);
|
|
579
542
|
return;
|
|
580
543
|
}
|
|
581
|
-
printBanner();
|
|
582
544
|
await freshSetup(options);
|
|
583
545
|
}
|
|
584
546
|
async function handleExistingConfig(apiKey, options) {
|
|
585
547
|
const statuses = getAgentStatuses();
|
|
586
548
|
const masked = maskApiKey(apiKey);
|
|
549
|
+
const skillInstalled = isSkillInstalled();
|
|
587
550
|
console.log();
|
|
588
|
-
console.log(` ${
|
|
589
|
-
console.log(` ${
|
|
590
|
-
console.log(` ${
|
|
591
|
-
console.log(` ${
|
|
592
|
-
console.log();
|
|
593
|
-
printTable(
|
|
594
|
-
[
|
|
595
|
-
{ key: "agent", label: "Agent" },
|
|
596
|
-
{ key: "global", label: "Global" },
|
|
597
|
-
{ key: "project", label: "Project" }
|
|
598
|
-
],
|
|
599
|
-
statuses.map((s) => ({
|
|
600
|
-
agent: s.agent.name,
|
|
601
|
-
global: !s.detected ? pc3.dim("-") : s.globalMcp ? pc3.green("\u25CF yes") : pc3.yellow("\u25CB no"),
|
|
602
|
-
project: s.projectMcp === null ? pc3.dim("-") : s.projectMcp ? pc3.green("\u25CF yes") : pc3.yellow("\u25CB no")
|
|
603
|
-
}))
|
|
604
|
-
);
|
|
605
|
-
const notDetected = statuses.filter((s) => !s.detected);
|
|
606
|
-
if (notDetected.length > 0) {
|
|
607
|
-
console.log(` ${pc3.dim("- = not detected on this machine")}`);
|
|
608
|
-
}
|
|
551
|
+
console.log(` ${pc2.bold("Current Setup")}`);
|
|
552
|
+
console.log(` ${pc2.dim("\u2500".repeat(42))}`);
|
|
553
|
+
console.log(` ${pc2.dim("API Key:")} ${masked}`);
|
|
554
|
+
console.log(` ${pc2.dim("Skill:")} ${skillInstalled ? pc2.green("installed") : pc2.yellow("not installed")}`);
|
|
555
|
+
console.log(` ${pc2.dim("Config:")} ${getConfigPath()}`);
|
|
609
556
|
const ac = getAccessControl();
|
|
610
557
|
if (Object.keys(ac).length > 0) {
|
|
611
|
-
console.log(` ${pc3.bold("Access Control")}`);
|
|
612
|
-
console.log(` ${pc3.dim("\u2500".repeat(42))}`);
|
|
613
|
-
if (ac.permissions) console.log(` ${pc3.dim("Permissions:")} ${ac.permissions}`);
|
|
614
|
-
if (ac.connectionKeys) console.log(` ${pc3.dim("Connections:")} ${ac.connectionKeys.join(", ")}`);
|
|
615
|
-
if (ac.actionIds) console.log(` ${pc3.dim("Action IDs:")} ${ac.actionIds.join(", ")}`);
|
|
616
|
-
if (ac.knowledgeAgent) console.log(` ${pc3.dim("Knowledge only:")} yes`);
|
|
617
558
|
console.log();
|
|
559
|
+
console.log(` ${pc2.bold("Access Control")}`);
|
|
560
|
+
console.log(` ${pc2.dim("\u2500".repeat(42))}`);
|
|
561
|
+
if (ac.permissions) console.log(` ${pc2.dim("Permissions:")} ${ac.permissions}`);
|
|
562
|
+
if (ac.connectionKeys) console.log(` ${pc2.dim("Connections:")} ${ac.connectionKeys.join(", ")}`);
|
|
563
|
+
if (ac.actionIds) console.log(` ${pc2.dim("Action IDs:")} ${ac.actionIds.join(", ")}`);
|
|
564
|
+
if (ac.knowledgeAgent) console.log(` ${pc2.dim("Knowledge only:")} yes`);
|
|
618
565
|
}
|
|
566
|
+
console.log();
|
|
619
567
|
const actionOptions = [];
|
|
620
568
|
actionOptions.push({
|
|
621
|
-
value: "
|
|
622
|
-
label: "Update
|
|
569
|
+
value: "install-skills",
|
|
570
|
+
label: skillInstalled ? "Update skill" : "Install skill",
|
|
571
|
+
hint: skillInstalled ? "reinstall latest version" : "recommended"
|
|
623
572
|
});
|
|
624
573
|
actionOptions.push({
|
|
625
|
-
value: "
|
|
626
|
-
label: "
|
|
574
|
+
value: "show-prompt",
|
|
575
|
+
label: "Show agent onboarding prompt",
|
|
576
|
+
hint: "copy-paste to your AI agent"
|
|
577
|
+
});
|
|
578
|
+
actionOptions.push({
|
|
579
|
+
value: "add-connection",
|
|
580
|
+
label: "Connect a platform",
|
|
581
|
+
hint: "add Gmail, Slack, Shopify, etc."
|
|
582
|
+
});
|
|
583
|
+
actionOptions.push({
|
|
584
|
+
value: "update-key",
|
|
585
|
+
label: "Update API key"
|
|
627
586
|
});
|
|
628
|
-
const agentsMissingGlobal = statuses.filter((s) => s.detected && !s.globalMcp);
|
|
629
|
-
if (agentsMissingGlobal.length > 0) {
|
|
630
|
-
actionOptions.push({
|
|
631
|
-
value: "install-more",
|
|
632
|
-
label: "Install MCP to more agents",
|
|
633
|
-
hint: `${agentsMissingGlobal.map((s) => s.agent.name).join(", ")} (not recommended)`
|
|
634
|
-
});
|
|
635
|
-
}
|
|
636
|
-
const agentsMissingProject = statuses.filter((s) => s.projectMcp === false);
|
|
637
|
-
if (agentsMissingProject.length > 0) {
|
|
638
|
-
actionOptions.push({
|
|
639
|
-
value: "install-project",
|
|
640
|
-
label: "Install MCP for this project",
|
|
641
|
-
hint: `${agentsMissingProject.map((s) => s.agent.name).join(", ")} (not recommended)`
|
|
642
|
-
});
|
|
643
|
-
}
|
|
644
587
|
actionOptions.push({
|
|
645
588
|
value: "access-control",
|
|
646
589
|
label: "Configure access control",
|
|
647
590
|
hint: "permissions, connections, actions"
|
|
648
591
|
});
|
|
592
|
+
actionOptions.push({
|
|
593
|
+
value: "install-mcp",
|
|
594
|
+
label: "Install MCP server",
|
|
595
|
+
hint: "not recommended \u2014 use skills instead"
|
|
596
|
+
});
|
|
649
597
|
actionOptions.push({
|
|
650
598
|
value: "start-fresh",
|
|
651
599
|
label: "Start fresh (reconfigure everything)"
|
|
@@ -659,30 +607,34 @@ async function handleExistingConfig(apiKey, options) {
|
|
|
659
607
|
return;
|
|
660
608
|
}
|
|
661
609
|
switch (action) {
|
|
662
|
-
case "update-key":
|
|
663
|
-
await handleUpdateKey(statuses);
|
|
664
|
-
break;
|
|
665
610
|
case "install-skills": {
|
|
666
|
-
const success = await
|
|
611
|
+
const success = await promptSkillInstall();
|
|
667
612
|
if (success) {
|
|
668
|
-
|
|
613
|
+
printOnboardingPrompt();
|
|
614
|
+
p3.outro("Skill installed. Paste the prompt above to your AI agent.");
|
|
669
615
|
} else {
|
|
670
|
-
const __dirname2 = path3.dirname(fileURLToPath(import.meta.url));
|
|
671
|
-
const skillsDir = path3.resolve(__dirname2, "..", "skills");
|
|
672
|
-
p3.log.warn(`Skills installation failed. You can try manually: ${pc3.cyan(`npx skills add ${skillsDir}`)}`);
|
|
673
616
|
p3.outro("Done.");
|
|
674
617
|
}
|
|
675
618
|
break;
|
|
676
619
|
}
|
|
677
|
-
case "
|
|
678
|
-
|
|
620
|
+
case "show-prompt":
|
|
621
|
+
printOnboardingPrompt();
|
|
622
|
+
p3.outro("Paste the prompt above to your AI agent.");
|
|
623
|
+
break;
|
|
624
|
+
case "add-connection":
|
|
625
|
+
await promptConnectIntegrations(apiKey);
|
|
626
|
+
p3.outro("Done.");
|
|
679
627
|
break;
|
|
680
|
-
case "
|
|
681
|
-
await
|
|
628
|
+
case "update-key":
|
|
629
|
+
await handleUpdateKey(statuses);
|
|
682
630
|
break;
|
|
683
631
|
case "access-control":
|
|
684
632
|
await configCommand();
|
|
685
633
|
break;
|
|
634
|
+
case "install-mcp":
|
|
635
|
+
await promptAndInstallMcp(apiKey, options);
|
|
636
|
+
p3.outro("Done.");
|
|
637
|
+
break;
|
|
686
638
|
case "start-fresh":
|
|
687
639
|
await freshSetup({ yes: true });
|
|
688
640
|
break;
|
|
@@ -690,7 +642,7 @@ async function handleExistingConfig(apiKey, options) {
|
|
|
690
642
|
}
|
|
691
643
|
async function handleUpdateKey(statuses) {
|
|
692
644
|
p3.note(`Get your API key at:
|
|
693
|
-
${
|
|
645
|
+
${pc2.cyan(getApiKeyUrl())}`, "API Key");
|
|
694
646
|
const openBrowser = await p3.confirm({
|
|
695
647
|
message: "Open browser to get API key?",
|
|
696
648
|
initialValue: true
|
|
@@ -751,108 +703,161 @@ ${pc3.cyan(getApiKeyUrl())}`, "API Key");
|
|
|
751
703
|
}
|
|
752
704
|
p3.outro("API key updated.");
|
|
753
705
|
}
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
706
|
+
var SKILL_AGENTS = [
|
|
707
|
+
{ id: "claude-code", name: "Claude Code", skillDir: ".claude/skills", primary: true },
|
|
708
|
+
{ id: "claude-desktop", name: "Claude Desktop", skillDir: ".claude/skills", primary: true },
|
|
709
|
+
{ id: "codex", name: "Codex", skillDir: ".codex/skills", primary: true },
|
|
710
|
+
{ id: "cursor", name: "Cursor", skillDir: ".cursor/skills" },
|
|
711
|
+
{ id: "windsurf", name: "Windsurf", skillDir: ".codeium/windsurf/skills" },
|
|
712
|
+
{ id: "kiro", name: "Kiro", skillDir: ".kiro/skills" },
|
|
713
|
+
{ id: "goose", name: "Goose", skillDir: ".config/goose/skills" },
|
|
714
|
+
{ id: "amp", name: "Amp", skillDir: ".amp/skills" },
|
|
715
|
+
{ id: "opencode", name: "OpenCode", skillDir: ".opencode/skills" },
|
|
716
|
+
{ id: "roo", name: "Roo", skillDir: ".roo/skills" }
|
|
717
|
+
];
|
|
718
|
+
var CANONICAL_SKILL_DIR = ".agents/skills";
|
|
719
|
+
function getSkillSourceDir() {
|
|
720
|
+
const __dirname2 = path3.dirname(fileURLToPath(import.meta.url));
|
|
721
|
+
return path3.resolve(__dirname2, "..", "skills", "one");
|
|
722
|
+
}
|
|
723
|
+
function getCanonicalSkillPath() {
|
|
724
|
+
return path3.join(os3.homedir(), CANONICAL_SKILL_DIR, "one");
|
|
725
|
+
}
|
|
726
|
+
function getAgentSkillPath(agent) {
|
|
727
|
+
return path3.join(os3.homedir(), agent.skillDir, "one");
|
|
728
|
+
}
|
|
729
|
+
function isSkillInstalled() {
|
|
730
|
+
return fs3.existsSync(path3.join(getCanonicalSkillPath(), "SKILL.md"));
|
|
731
|
+
}
|
|
732
|
+
function isSkillInstalledForAgent(agent) {
|
|
733
|
+
return fs3.existsSync(path3.join(getAgentSkillPath(agent), "SKILL.md"));
|
|
734
|
+
}
|
|
735
|
+
function copyDirSync(src, dest) {
|
|
736
|
+
fs3.mkdirSync(dest, { recursive: true });
|
|
737
|
+
for (const entry of fs3.readdirSync(src, { withFileTypes: true })) {
|
|
738
|
+
const srcPath = path3.join(src, entry.name);
|
|
739
|
+
const destPath = path3.join(dest, entry.name);
|
|
740
|
+
if (entry.isDirectory()) {
|
|
741
|
+
copyDirSync(srcPath, destPath);
|
|
742
|
+
} else {
|
|
743
|
+
fs3.copyFileSync(srcPath, destPath);
|
|
765
744
|
}
|
|
766
|
-
installMcpConfig(agent, apiKey, "global", ac);
|
|
767
|
-
updateConfigAgents(agent.id);
|
|
768
|
-
p3.log.success(`${agent.name}: MCP installed`);
|
|
769
|
-
p3.outro("Done.");
|
|
770
|
-
return;
|
|
771
745
|
}
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
p3.outro("No changes made.");
|
|
781
|
-
return;
|
|
746
|
+
}
|
|
747
|
+
function installSkillForAgents(agentIds) {
|
|
748
|
+
const source = getSkillSourceDir();
|
|
749
|
+
const canonical = getCanonicalSkillPath();
|
|
750
|
+
const installed = [];
|
|
751
|
+
const failed = [];
|
|
752
|
+
if (!fs3.existsSync(path3.join(source, "SKILL.md"))) {
|
|
753
|
+
return { installed: [], failed: ["skill source not found"] };
|
|
782
754
|
}
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
755
|
+
try {
|
|
756
|
+
if (fs3.existsSync(canonical)) {
|
|
757
|
+
fs3.rmSync(canonical, { recursive: true });
|
|
758
|
+
}
|
|
759
|
+
copyDirSync(source, canonical);
|
|
760
|
+
} catch {
|
|
761
|
+
return { installed: [], failed: ["canonical copy"] };
|
|
788
762
|
}
|
|
789
|
-
|
|
763
|
+
const seen = /* @__PURE__ */ new Map();
|
|
764
|
+
for (const id of agentIds) {
|
|
765
|
+
const agent = SKILL_AGENTS.find((a) => a.id === id);
|
|
766
|
+
if (!agent) continue;
|
|
767
|
+
const agentPath = getAgentSkillPath(agent);
|
|
768
|
+
if (seen.has(agentPath)) {
|
|
769
|
+
(seen.get(agentPath) ? installed : failed).push(agent.name);
|
|
770
|
+
continue;
|
|
771
|
+
}
|
|
772
|
+
try {
|
|
773
|
+
const agentSkillsDir = path3.dirname(agentPath);
|
|
774
|
+
fs3.mkdirSync(agentSkillsDir, { recursive: true });
|
|
775
|
+
try {
|
|
776
|
+
fs3.lstatSync(agentPath);
|
|
777
|
+
fs3.rmSync(agentPath, { recursive: true });
|
|
778
|
+
} catch {
|
|
779
|
+
}
|
|
780
|
+
const relative = path3.relative(agentSkillsDir, canonical);
|
|
781
|
+
fs3.symlinkSync(relative, agentPath);
|
|
782
|
+
installed.push(agent.name);
|
|
783
|
+
seen.set(agentPath, true);
|
|
784
|
+
} catch {
|
|
785
|
+
failed.push(agent.name);
|
|
786
|
+
seen.set(agentPath, false);
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
return { installed, failed };
|
|
790
790
|
}
|
|
791
|
-
async function
|
|
792
|
-
const
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
791
|
+
async function promptSkillInstall() {
|
|
792
|
+
const primaryAgents = SKILL_AGENTS.filter((a) => a.primary);
|
|
793
|
+
const otherAgents = SKILL_AGENTS.filter((a) => !a.primary);
|
|
794
|
+
const options = [
|
|
795
|
+
...primaryAgents.map((a) => ({
|
|
796
|
+
value: a.id,
|
|
797
|
+
label: a.name,
|
|
798
|
+
hint: isSkillInstalledForAgent(a) ? pc2.green("installed") : void 0
|
|
799
|
+
})),
|
|
800
|
+
{
|
|
801
|
+
value: "_other",
|
|
802
|
+
label: "Other agents",
|
|
803
|
+
hint: otherAgents.map((a) => a.name).join(", ")
|
|
804
|
+
}
|
|
805
|
+
];
|
|
806
|
+
const choice = await p3.multiselect({
|
|
807
|
+
message: "Install the One skill to:",
|
|
808
|
+
options,
|
|
809
|
+
initialValues: primaryAgents.map((a) => a.id)
|
|
810
|
+
});
|
|
811
|
+
if (p3.isCancel(choice)) {
|
|
812
|
+
return false;
|
|
813
|
+
}
|
|
814
|
+
let selectedIds = choice;
|
|
815
|
+
if (selectedIds.includes("_other")) {
|
|
816
|
+
selectedIds = selectedIds.filter((id) => id !== "_other");
|
|
817
|
+
const otherChoice = await p3.multiselect({
|
|
818
|
+
message: "Select additional agents:",
|
|
819
|
+
options: otherAgents.map((a) => ({
|
|
820
|
+
value: a.id,
|
|
821
|
+
label: a.name,
|
|
822
|
+
hint: isSkillInstalledForAgent(a) ? pc2.green("installed") : void 0
|
|
823
|
+
}))
|
|
798
824
|
});
|
|
799
|
-
if (p3.isCancel(
|
|
800
|
-
|
|
801
|
-
return;
|
|
825
|
+
if (!p3.isCancel(otherChoice)) {
|
|
826
|
+
selectedIds.push(...otherChoice);
|
|
802
827
|
}
|
|
803
|
-
installMcpConfig(agent, apiKey, "project", ac);
|
|
804
|
-
const configPath = getAgentConfigPath(agent, "project");
|
|
805
|
-
p3.log.success(`${agent.name}: ${configPath} created`);
|
|
806
|
-
p3.note(
|
|
807
|
-
pc3.yellow("Project config files can be committed to share with your team.\n") + pc3.yellow("Team members will need their own API key."),
|
|
808
|
-
"Tip"
|
|
809
|
-
);
|
|
810
|
-
p3.outro("Done.");
|
|
811
|
-
return;
|
|
812
828
|
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
});
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
829
|
+
if (selectedIds.length === 0) {
|
|
830
|
+
p3.log.info("No agents selected.");
|
|
831
|
+
return false;
|
|
832
|
+
}
|
|
833
|
+
const spinner5 = p3.spinner();
|
|
834
|
+
spinner5.start("Installing skill...");
|
|
835
|
+
const { installed, failed } = installSkillForAgents(selectedIds);
|
|
836
|
+
spinner5.stop(installed.length > 0 ? "Skill installed" : "Installation failed");
|
|
837
|
+
for (const name of installed) {
|
|
838
|
+
p3.log.success(`${name}: ${pc2.green("\u2713")} skill installed`);
|
|
823
839
|
}
|
|
824
|
-
const
|
|
825
|
-
|
|
826
|
-
installMcpConfig(s.agent, apiKey, "project", ac);
|
|
827
|
-
const configPath = getAgentConfigPath(s.agent, "project");
|
|
828
|
-
p3.log.success(`${s.agent.name}: ${configPath} created`);
|
|
840
|
+
for (const name of failed) {
|
|
841
|
+
p3.log.warn(`${name}: failed to install`);
|
|
829
842
|
}
|
|
830
|
-
|
|
831
|
-
pc3.yellow("Project config files can be committed to share with your team.\n") + pc3.yellow("Team members will need their own API key."),
|
|
832
|
-
"Tip"
|
|
833
|
-
);
|
|
834
|
-
p3.outro("Done.");
|
|
843
|
+
return installed.length > 0;
|
|
835
844
|
}
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
process.removeListener("SIGINT", handler);
|
|
853
|
-
resolve(false);
|
|
854
|
-
});
|
|
855
|
-
});
|
|
845
|
+
function printOnboardingPrompt() {
|
|
846
|
+
console.log();
|
|
847
|
+
console.log(pc2.bold(" Copy-paste this to your AI agent:"));
|
|
848
|
+
console.log();
|
|
849
|
+
console.log(pc2.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"));
|
|
850
|
+
console.log(pc2.cyan(" \u2502"));
|
|
851
|
+
console.log(pc2.cyan(" \u2502 The One CLI (`one`) is now installed on this machine. It"));
|
|
852
|
+
console.log(pc2.cyan(" \u2502 lets you interact with 250+ third-party platforms (Gmail,"));
|
|
853
|
+
console.log(pc2.cyan(" \u2502 Slack, Shopify, HubSpot, Stripe, GitHub, etc.) through"));
|
|
854
|
+
console.log(pc2.cyan(" \u2502 their APIs. Whenever you need to interact with any"));
|
|
855
|
+
console.log(pc2.cyan(" \u2502 third-party platform or external service, use the `one`"));
|
|
856
|
+
console.log(pc2.cyan(" \u2502 skill. Please save this to your project instructions or"));
|
|
857
|
+
console.log(pc2.cyan(" \u2502 memory so you remember it in future conversations."));
|
|
858
|
+
console.log(pc2.cyan(" \u2502"));
|
|
859
|
+
console.log(pc2.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"));
|
|
860
|
+
console.log();
|
|
856
861
|
}
|
|
857
862
|
async function promptAndInstallMcp(apiKey, options) {
|
|
858
863
|
const allAgents = getAllAgents();
|
|
@@ -935,7 +940,7 @@ Project scope is supported by: ${supported}`,
|
|
|
935
940
|
const allInstalled = [...projectAgents, ...nonProjectAgents];
|
|
936
941
|
updateConfigAgentsList(allInstalled.map((a) => a.id));
|
|
937
942
|
p3.note(
|
|
938
|
-
|
|
943
|
+
pc2.yellow("Project config files can be committed to share with your team.\n") + pc2.yellow("Team members will need their own API key."),
|
|
939
944
|
"Tip"
|
|
940
945
|
);
|
|
941
946
|
return;
|
|
@@ -952,7 +957,7 @@ Project scope is supported by: ${supported}`,
|
|
|
952
957
|
}
|
|
953
958
|
async function freshSetup(options) {
|
|
954
959
|
p3.note(`Get your API key at:
|
|
955
|
-
${
|
|
960
|
+
${pc2.cyan(getApiKeyUrl())}`, "API Key");
|
|
956
961
|
const openBrowser = await p3.confirm({
|
|
957
962
|
message: "Open browser to get API key?",
|
|
958
963
|
initialValue: true
|
|
@@ -994,20 +999,7 @@ ${pc3.cyan(getApiKeyUrl())}`, "API Key");
|
|
|
994
999
|
installedAgents: [],
|
|
995
1000
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
996
1001
|
});
|
|
997
|
-
|
|
998
|
-
message: "Install One skills to your AI agents? (recommended)",
|
|
999
|
-
initialValue: true
|
|
1000
|
-
});
|
|
1001
|
-
if (!p3.isCancel(installSkills) && installSkills) {
|
|
1002
|
-
const success = await runSkillsInstall();
|
|
1003
|
-
if (success) {
|
|
1004
|
-
p3.log.success("Skills installed successfully.");
|
|
1005
|
-
} else {
|
|
1006
|
-
const __dirname2 = path3.dirname(fileURLToPath(import.meta.url));
|
|
1007
|
-
const skillsDir = path3.resolve(__dirname2, "..", "skills");
|
|
1008
|
-
p3.log.warn(`Skills installation failed. You can try manually: ${pc3.cyan(`npx skills add ${skillsDir}`)}`);
|
|
1009
|
-
}
|
|
1010
|
-
}
|
|
1002
|
+
await promptSkillInstall();
|
|
1011
1003
|
await promptConnectIntegrations(apiKey);
|
|
1012
1004
|
const installMcp = await p3.confirm({
|
|
1013
1005
|
message: "Install One MCP server to your AI agents? (not recommended)",
|
|
@@ -1017,29 +1009,26 @@ ${pc3.cyan(getApiKeyUrl())}`, "API Key");
|
|
|
1017
1009
|
await promptAndInstallMcp(apiKey, options);
|
|
1018
1010
|
}
|
|
1019
1011
|
p3.note(
|
|
1020
|
-
`Config saved to: ${
|
|
1012
|
+
`Config saved to: ${pc2.dim(getConfigPath())}`,
|
|
1021
1013
|
"Setup Complete"
|
|
1022
1014
|
);
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
"Next Step"
|
|
1026
|
-
);
|
|
1027
|
-
p3.outro("Your AI agents now have access to One integrations!");
|
|
1015
|
+
printOnboardingPrompt();
|
|
1016
|
+
p3.outro("Done! Paste the prompt above to your AI agent.");
|
|
1028
1017
|
}
|
|
1029
1018
|
function printBanner() {
|
|
1030
1019
|
console.log();
|
|
1031
|
-
console.log(
|
|
1032
|
-
console.log(
|
|
1033
|
-
console.log(
|
|
1034
|
-
console.log(
|
|
1035
|
-
console.log(
|
|
1036
|
-
console.log(
|
|
1037
|
-
console.log(
|
|
1038
|
-
console.log(
|
|
1039
|
-
console.log(
|
|
1040
|
-
console.log(
|
|
1020
|
+
console.log(pc2.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"));
|
|
1021
|
+
console.log(pc2.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"));
|
|
1022
|
+
console.log(pc2.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 "));
|
|
1023
|
+
console.log(pc2.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 "));
|
|
1024
|
+
console.log(pc2.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 "));
|
|
1025
|
+
console.log(pc2.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 "));
|
|
1026
|
+
console.log(pc2.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 "));
|
|
1027
|
+
console.log(pc2.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 "));
|
|
1028
|
+
console.log(pc2.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"));
|
|
1029
|
+
console.log(pc2.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"));
|
|
1041
1030
|
console.log();
|
|
1042
|
-
console.log(
|
|
1031
|
+
console.log(pc2.dim(" I N F R A S T R U C T U R E F O R A G E N T S"));
|
|
1043
1032
|
console.log();
|
|
1044
1033
|
}
|
|
1045
1034
|
var TOP_INTEGRATIONS = [
|
|
@@ -1084,13 +1073,13 @@ async function promptConnectIntegrations(apiKey) {
|
|
|
1084
1073
|
} catch {
|
|
1085
1074
|
p3.note("https://app.withone.ai/connections", "Open in browser");
|
|
1086
1075
|
}
|
|
1087
|
-
p3.log.info(`Connect from the dashboard, or use ${
|
|
1076
|
+
p3.log.info(`Connect from the dashboard, or use ${pc2.cyan("one add <platform>")}`);
|
|
1088
1077
|
break;
|
|
1089
1078
|
}
|
|
1090
1079
|
const platform = choice;
|
|
1091
1080
|
const integration = TOP_INTEGRATIONS.find((i) => i.value === platform);
|
|
1092
1081
|
const label = integration?.label ?? platform;
|
|
1093
|
-
p3.log.info(`Opening browser to connect ${
|
|
1082
|
+
p3.log.info(`Opening browser to connect ${pc2.cyan(label)}...`);
|
|
1094
1083
|
try {
|
|
1095
1084
|
await openConnectionPage(platform);
|
|
1096
1085
|
} catch {
|
|
@@ -1103,13 +1092,13 @@ async function promptConnectIntegrations(apiKey) {
|
|
|
1103
1092
|
try {
|
|
1104
1093
|
await api.waitForConnection(platform, 5 * 60 * 1e3, 5e3);
|
|
1105
1094
|
spinner5.stop(`${label} connected!`);
|
|
1106
|
-
p3.log.success(`${
|
|
1095
|
+
p3.log.success(`${pc2.green("\u2713")} ${label} is now available to your AI agents`);
|
|
1107
1096
|
connected.push(platform);
|
|
1108
1097
|
first = false;
|
|
1109
1098
|
} catch (error2) {
|
|
1110
1099
|
spinner5.stop("Connection timed out");
|
|
1111
1100
|
if (error2 instanceof TimeoutError) {
|
|
1112
|
-
p3.log.warn(`No worries. Connect later with: ${
|
|
1101
|
+
p3.log.warn(`No worries. Connect later with: ${pc2.cyan(`one add ${platform}`)}`);
|
|
1113
1102
|
}
|
|
1114
1103
|
first = false;
|
|
1115
1104
|
}
|
|
@@ -1123,14 +1112,6 @@ function maskApiKey(key) {
|
|
|
1123
1112
|
if (key.length <= 12) return key.slice(0, 8) + "...";
|
|
1124
1113
|
return key.slice(0, 8) + "..." + key.slice(-4);
|
|
1125
1114
|
}
|
|
1126
|
-
function updateConfigAgents(agentId) {
|
|
1127
|
-
const config = readConfig();
|
|
1128
|
-
if (!config) return;
|
|
1129
|
-
if (!config.installedAgents.includes(agentId)) {
|
|
1130
|
-
config.installedAgents.push(agentId);
|
|
1131
|
-
writeConfig(config);
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
1115
|
function updateConfigAgentsList(agentIds) {
|
|
1135
1116
|
const config = readConfig();
|
|
1136
1117
|
if (!config) return;
|
|
@@ -1181,6 +1162,42 @@ function countMatchingChars(a, b) {
|
|
|
1181
1162
|
return count;
|
|
1182
1163
|
}
|
|
1183
1164
|
|
|
1165
|
+
// src/lib/table.ts
|
|
1166
|
+
import pc3 from "picocolors";
|
|
1167
|
+
function printTable(columns, rows) {
|
|
1168
|
+
if (rows.length === 0) return;
|
|
1169
|
+
const gap = " ";
|
|
1170
|
+
const indent = " ";
|
|
1171
|
+
const widths = columns.map((col) => {
|
|
1172
|
+
const headerLen = col.label.length;
|
|
1173
|
+
const maxValueLen = Math.max(...rows.map((row) => stripAnsi(row[col.key] || "").length));
|
|
1174
|
+
return Math.max(headerLen, maxValueLen);
|
|
1175
|
+
});
|
|
1176
|
+
const header = columns.map((col, i) => {
|
|
1177
|
+
const padded = col.align === "right" ? col.label.padStart(widths[i]) : col.label.padEnd(widths[i]);
|
|
1178
|
+
return pc3.dim(padded);
|
|
1179
|
+
}).join(gap);
|
|
1180
|
+
console.log(`${indent}${header}`);
|
|
1181
|
+
const separator = columns.map((_, i) => pc3.dim("\u2500".repeat(widths[i]))).join(gap);
|
|
1182
|
+
console.log(`${indent}${separator}`);
|
|
1183
|
+
for (const row of rows) {
|
|
1184
|
+
const line = columns.map((col, i) => {
|
|
1185
|
+
const raw = row[col.key] || "";
|
|
1186
|
+
const rawLen = stripAnsi(raw).length;
|
|
1187
|
+
const padding = widths[i] - rawLen;
|
|
1188
|
+
const colored = col.color ? col.color(raw) : raw;
|
|
1189
|
+
if (col.align === "right") {
|
|
1190
|
+
return " ".repeat(Math.max(0, padding)) + colored;
|
|
1191
|
+
}
|
|
1192
|
+
return colored + " ".repeat(Math.max(0, padding));
|
|
1193
|
+
}).join(gap);
|
|
1194
|
+
console.log(`${indent}${line}`);
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
function stripAnsi(str) {
|
|
1198
|
+
return str.replace(/\x1b\[[0-9;]*m/g, "");
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1184
1201
|
// src/commands/connection.ts
|
|
1185
1202
|
async function connectionAddCommand(platformArg) {
|
|
1186
1203
|
if (isAgentMode()) {
|
|
@@ -2513,7 +2530,7 @@ function validateFlow(flow2) {
|
|
|
2513
2530
|
}
|
|
2514
2531
|
|
|
2515
2532
|
// src/commands/flow.ts
|
|
2516
|
-
import
|
|
2533
|
+
import fs4 from "fs";
|
|
2517
2534
|
function getConfig2() {
|
|
2518
2535
|
const apiKey = getApiKey();
|
|
2519
2536
|
if (!apiKey) {
|
|
@@ -2571,7 +2588,7 @@ async function flowCreateCommand(key, options) {
|
|
|
2571
2588
|
if (raw.startsWith("@")) {
|
|
2572
2589
|
const filePath = raw.slice(1);
|
|
2573
2590
|
try {
|
|
2574
|
-
raw =
|
|
2591
|
+
raw = fs4.readFileSync(filePath, "utf-8");
|
|
2575
2592
|
} catch (err) {
|
|
2576
2593
|
error(`Cannot read file "${filePath}": ${err.message}`);
|
|
2577
2594
|
}
|
|
@@ -2754,7 +2771,7 @@ async function flowValidateCommand(keyOrPath) {
|
|
|
2754
2771
|
let flowData;
|
|
2755
2772
|
try {
|
|
2756
2773
|
const flowPath = resolveFlowPath(keyOrPath);
|
|
2757
|
-
const content =
|
|
2774
|
+
const content = fs4.readFileSync(flowPath, "utf-8");
|
|
2758
2775
|
flowData = JSON.parse(content);
|
|
2759
2776
|
} catch (err) {
|
|
2760
2777
|
spinner5.stop("Validation failed");
|
|
@@ -3451,7 +3468,7 @@ Before using any feature, read its guide section first: \`one guide actions\`, \
|
|
|
3451
3468
|
|
|
3452
3469
|
## Features
|
|
3453
3470
|
|
|
3454
|
-
### 1. Actions \u2014 Execute API calls on
|
|
3471
|
+
### 1. Actions \u2014 Execute API calls on 250+ platforms
|
|
3455
3472
|
Search for actions, read their docs, and execute them. This is the core workflow.
|
|
3456
3473
|
|
|
3457
3474
|
**Quick start:**
|
|
@@ -3812,7 +3829,7 @@ function buildStep1() {
|
|
|
3812
3829
|
nextCommand: "one onboard --step 2",
|
|
3813
3830
|
message: `# One CLI \u2014 Agent Onboarding
|
|
3814
3831
|
|
|
3815
|
-
You now have access to the One CLI. It connects you to
|
|
3832
|
+
You now have access to the One CLI. It connects you to 250+ platforms
|
|
3816
3833
|
(Gmail, Slack, Stripe, Notion, etc.) \u2014 you'll learn the details shortly.
|
|
3817
3834
|
|
|
3818
3835
|
IMPORTANT: Your only task right now is to send the message below to the
|
|
@@ -3822,7 +3839,7 @@ Do not offer demos yet. Just send this message and wait for their reply:
|
|
|
3822
3839
|
---
|
|
3823
3840
|
|
|
3824
3841
|
I just got access to the One CLI \u2014 it connects me to your platforms like
|
|
3825
|
-
Gmail, Slack, Stripe, and
|
|
3842
|
+
Gmail, Slack, Stripe, and 250+ others so I can work with them directly.
|
|
3826
3843
|
I'll show you what I can do in a moment.
|
|
3827
3844
|
|
|
3828
3845
|
First, one quick setup step: right now only this conversation knows about
|
|
@@ -3851,7 +3868,7 @@ If they declined, skip this section.
|
|
|
3851
3868
|
## One CLI \u2014 Platform Integrations
|
|
3852
3869
|
|
|
3853
3870
|
The One CLI (\`one\`) is installed and configured on this machine. It is a
|
|
3854
|
-
command-line tool that gives AI agents the ability to interact with
|
|
3871
|
+
command-line tool that gives AI agents the ability to interact with 250+
|
|
3855
3872
|
third-party platforms (Gmail, Slack, Shopify, HubSpot, Stripe, GitHub,
|
|
3856
3873
|
Notion, Salesforce, etc.) through a single, unified interface.
|
|
3857
3874
|
|
|
@@ -3946,7 +3963,7 @@ function buildStep3(connections) {
|
|
|
3946
3963
|
The user can connect any of these popular platforms:
|
|
3947
3964
|
Gmail, Google Calendar, Slack, Notion, Shopify, Stripe, HubSpot, GitHub,
|
|
3948
3965
|
Salesforce, QuickBooks, Asana, Jira, Linear, Intercom, Zendesk, Twilio,
|
|
3949
|
-
and
|
|
3966
|
+
and 250+ more. Run \`one platforms\` for the full list.`);
|
|
3950
3967
|
sections.push("## Onboarding complete!\n\nYou're all set. Use `one --agent guide` any time you need the full reference.");
|
|
3951
3968
|
return {
|
|
3952
3969
|
step: 3,
|
|
@@ -3977,7 +3994,7 @@ platform before you can start using actions. Suggest they run:
|
|
|
3977
3994
|
one add slack
|
|
3978
3995
|
one add <any-platform>
|
|
3979
3996
|
|
|
3980
|
-
Run \`one platforms\` to see all
|
|
3997
|
+
Run \`one platforms\` to see all 250+ available platforms.`;
|
|
3981
3998
|
}
|
|
3982
3999
|
const header = `## Current State
|
|
3983
4000
|
|
|
@@ -4037,20 +4054,23 @@ function buildWorkflowIdeas(connections) {
|
|
|
4037
4054
|
|
|
4038
4055
|
// src/commands/update.ts
|
|
4039
4056
|
import { createRequire } from "module";
|
|
4040
|
-
import { spawn
|
|
4057
|
+
import { spawn } from "child_process";
|
|
4041
4058
|
import { readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
4042
4059
|
import { homedir } from "os";
|
|
4043
4060
|
import { join } from "path";
|
|
4044
4061
|
var require2 = createRequire(import.meta.url);
|
|
4045
4062
|
var { version: currentVersion } = require2("../package.json");
|
|
4046
4063
|
var CACHE_PATH = join(homedir(), ".one", "update-check.json");
|
|
4047
|
-
var CHECK_INTERVAL_MS =
|
|
4048
|
-
|
|
4064
|
+
var CHECK_INTERVAL_MS = 4 * 60 * 60 * 1e3;
|
|
4065
|
+
var AGE_GATE_MS = 30 * 60 * 1e3;
|
|
4066
|
+
async function fetchLatestVersionInfo() {
|
|
4049
4067
|
try {
|
|
4050
|
-
const res = await fetch("https://registry.npmjs.org/@withone/cli
|
|
4068
|
+
const res = await fetch("https://registry.npmjs.org/@withone/cli");
|
|
4051
4069
|
if (!res.ok) return null;
|
|
4052
4070
|
const data = await res.json();
|
|
4053
|
-
|
|
4071
|
+
const latest = data["dist-tags"]?.latest;
|
|
4072
|
+
if (!latest) return null;
|
|
4073
|
+
return { version: latest, publishedAt: data.time?.[latest] ?? null };
|
|
4054
4074
|
} catch {
|
|
4055
4075
|
return null;
|
|
4056
4076
|
}
|
|
@@ -4062,24 +4082,26 @@ function readCache() {
|
|
|
4062
4082
|
return null;
|
|
4063
4083
|
}
|
|
4064
4084
|
}
|
|
4065
|
-
function writeCache(latestVersion) {
|
|
4085
|
+
function writeCache(latestVersion, publishedAt) {
|
|
4066
4086
|
try {
|
|
4067
4087
|
mkdirSync(join(homedir(), ".one"), { recursive: true });
|
|
4068
|
-
writeFileSync(CACHE_PATH, JSON.stringify({ lastCheck: Date.now(), latestVersion }));
|
|
4088
|
+
writeFileSync(CACHE_PATH, JSON.stringify({ lastCheck: Date.now(), latestVersion, publishedAt }));
|
|
4069
4089
|
} catch {
|
|
4070
4090
|
}
|
|
4071
4091
|
}
|
|
4072
4092
|
async function checkLatestVersion() {
|
|
4073
|
-
const
|
|
4074
|
-
if (
|
|
4075
|
-
return
|
|
4093
|
+
const info = await fetchLatestVersionInfo();
|
|
4094
|
+
if (info) writeCache(info.version, info.publishedAt);
|
|
4095
|
+
return info?.version ?? null;
|
|
4076
4096
|
}
|
|
4077
4097
|
async function checkLatestVersionCached() {
|
|
4078
4098
|
const cache = readCache();
|
|
4079
4099
|
if (cache && Date.now() - cache.lastCheck < CHECK_INTERVAL_MS) {
|
|
4080
|
-
return cache.latestVersion;
|
|
4100
|
+
return { version: cache.latestVersion, publishedAt: cache.publishedAt ?? null };
|
|
4081
4101
|
}
|
|
4082
|
-
|
|
4102
|
+
const info = await fetchLatestVersionInfo();
|
|
4103
|
+
if (info) writeCache(info.version, info.publishedAt);
|
|
4104
|
+
return info;
|
|
4083
4105
|
}
|
|
4084
4106
|
function getCurrentVersion() {
|
|
4085
4107
|
return currentVersion;
|
|
@@ -4104,7 +4126,7 @@ async function updateCommand() {
|
|
|
4104
4126
|
s.stop(`Update available: v${currentVersion} \u2192 v${latestVersion}`);
|
|
4105
4127
|
console.log(`Updating @withone/cli: v${currentVersion} \u2192 v${latestVersion}...`);
|
|
4106
4128
|
const code = await new Promise((resolve) => {
|
|
4107
|
-
const child =
|
|
4129
|
+
const child = spawn("npm", ["install", "-g", "@withone/cli@latest", "--force"], {
|
|
4108
4130
|
stdio: isAgentMode() ? "pipe" : "inherit",
|
|
4109
4131
|
shell: true
|
|
4110
4132
|
});
|
|
@@ -4121,12 +4143,24 @@ async function updateCommand() {
|
|
|
4121
4143
|
error("Update failed \u2014 try running: npm install -g @withone/cli@latest");
|
|
4122
4144
|
}
|
|
4123
4145
|
}
|
|
4146
|
+
function autoUpdate(targetVersion, publishedAt) {
|
|
4147
|
+
if (publishedAt) {
|
|
4148
|
+
const age = Date.now() - new Date(publishedAt).getTime();
|
|
4149
|
+
if (age < AGE_GATE_MS) return;
|
|
4150
|
+
}
|
|
4151
|
+
const child = spawn("npm", ["install", "-g", `@withone/cli@${targetVersion}`], {
|
|
4152
|
+
detached: true,
|
|
4153
|
+
stdio: "ignore",
|
|
4154
|
+
shell: true
|
|
4155
|
+
});
|
|
4156
|
+
child.unref();
|
|
4157
|
+
}
|
|
4124
4158
|
|
|
4125
4159
|
// src/index.ts
|
|
4126
4160
|
var require3 = createRequire2(import.meta.url);
|
|
4127
4161
|
var { version } = require3("../package.json");
|
|
4128
4162
|
var program = new Command();
|
|
4129
|
-
program.name("one").option("--agent", "Machine-readable JSON output (no colors, spinners, or prompts)").description(`One CLI \u2014 Connect AI agents to
|
|
4163
|
+
program.name("one").option("--agent", "Machine-readable JSON output (no colors, spinners, or prompts)").description(`One CLI \u2014 Connect AI agents to 250+ platforms through one interface.
|
|
4130
4164
|
|
|
4131
4165
|
Setup:
|
|
4132
4166
|
one init Set up API key and install MCP server
|
|
@@ -4170,7 +4204,7 @@ program.name("one").option("--agent", "Machine-readable JSON output (no colors,
|
|
|
4170
4204
|
-d '{"to":"j@example.com","subject":"Hello","body":"Hi!","connectionKey":"live::gmail::default::abc123"}'
|
|
4171
4205
|
|
|
4172
4206
|
Platform names are always kebab-case (e.g. hub-spot, ship-station, google-calendar).
|
|
4173
|
-
Run 'one platforms' to browse all
|
|
4207
|
+
Run 'one platforms' to browse all 250+ available platforms.`).version(version);
|
|
4174
4208
|
var updateCheckPromise;
|
|
4175
4209
|
program.hook("preAction", (thisCommand) => {
|
|
4176
4210
|
const opts = program.opts();
|
|
@@ -4184,18 +4218,11 @@ program.hook("preAction", (thisCommand) => {
|
|
|
4184
4218
|
});
|
|
4185
4219
|
program.hook("postAction", async () => {
|
|
4186
4220
|
if (!updateCheckPromise) return;
|
|
4187
|
-
const
|
|
4188
|
-
if (!
|
|
4221
|
+
const info = await updateCheckPromise;
|
|
4222
|
+
if (!info) return;
|
|
4189
4223
|
const current = getCurrentVersion();
|
|
4190
|
-
if (current ===
|
|
4191
|
-
|
|
4192
|
-
process.stderr.write(`
|
|
4193
|
-
Update available: v${current} \u2192 v${latestVersion}. Run "one update" to upgrade.
|
|
4194
|
-
`);
|
|
4195
|
-
} else {
|
|
4196
|
-
console.log(`
|
|
4197
|
-
\x1B[33mUpdate available: v${current} \u2192 v${latestVersion}. Run \x1B[1mone update\x1B[22m to upgrade.\x1B[0m`);
|
|
4198
|
-
}
|
|
4224
|
+
if (current === info.version) return;
|
|
4225
|
+
autoUpdate(info.version, info.publishedAt);
|
|
4199
4226
|
});
|
|
4200
4227
|
program.command("init").description("Set up One and install MCP to your AI agents").option("-y, --yes", "Skip confirmations").option("-g, --global", "Install MCP globally (available in all projects)").option("-p, --project", "Install MCP for this project only (creates .mcp.json)").action(async (options) => {
|
|
4201
4228
|
await initCommand(options);
|