@withone/cli 1.16.0 → 1.17.2
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 +289 -390
- 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
|
|
@@ -222,12 +223,6 @@ var AGENTS = [
|
|
|
222
223
|
projectConfigPath: ".kiro/settings/mcp.json"
|
|
223
224
|
}
|
|
224
225
|
];
|
|
225
|
-
function getAllAgents() {
|
|
226
|
-
return AGENTS;
|
|
227
|
-
}
|
|
228
|
-
function supportsProjectScope(agent) {
|
|
229
|
-
return agent.projectConfigPath !== void 0;
|
|
230
|
-
}
|
|
231
226
|
function getAgentConfigPath(agent, scope = "global") {
|
|
232
227
|
if (scope === "project" && agent.projectConfigPath) {
|
|
233
228
|
return path2.join(process.cwd(), agent.projectConfigPath);
|
|
@@ -530,117 +525,59 @@ function formatList(list) {
|
|
|
530
525
|
|
|
531
526
|
// src/commands/init.ts
|
|
532
527
|
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
528
|
async function initCommand(options) {
|
|
572
529
|
if (isAgentMode()) {
|
|
573
530
|
error("This command requires interactive input. Run without --agent.");
|
|
574
531
|
}
|
|
575
532
|
const existingConfig = readConfig();
|
|
533
|
+
printBanner();
|
|
576
534
|
if (existingConfig) {
|
|
577
|
-
p3.intro(pc3.bgCyan(pc3.black(" One ")));
|
|
578
535
|
await handleExistingConfig(existingConfig.apiKey, options);
|
|
579
536
|
return;
|
|
580
537
|
}
|
|
581
|
-
printBanner();
|
|
582
538
|
await freshSetup(options);
|
|
583
539
|
}
|
|
584
540
|
async function handleExistingConfig(apiKey, options) {
|
|
585
541
|
const statuses = getAgentStatuses();
|
|
586
542
|
const masked = maskApiKey(apiKey);
|
|
543
|
+
const skillInstalled = isSkillInstalled();
|
|
587
544
|
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
|
-
}
|
|
545
|
+
console.log(` ${pc2.bold("Current Setup")}`);
|
|
546
|
+
console.log(` ${pc2.dim("\u2500".repeat(42))}`);
|
|
547
|
+
console.log(` ${pc2.dim("API Key:")} ${masked}`);
|
|
548
|
+
console.log(` ${pc2.dim("Skill:")} ${skillInstalled ? pc2.green("installed") : pc2.yellow("not installed")}`);
|
|
549
|
+
console.log(` ${pc2.dim("Config:")} ${getConfigPath()}`);
|
|
609
550
|
const ac = getAccessControl();
|
|
610
551
|
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
552
|
console.log();
|
|
553
|
+
console.log(` ${pc2.bold("Access Control")}`);
|
|
554
|
+
console.log(` ${pc2.dim("\u2500".repeat(42))}`);
|
|
555
|
+
if (ac.permissions) console.log(` ${pc2.dim("Permissions:")} ${ac.permissions}`);
|
|
556
|
+
if (ac.connectionKeys) console.log(` ${pc2.dim("Connections:")} ${ac.connectionKeys.join(", ")}`);
|
|
557
|
+
if (ac.actionIds) console.log(` ${pc2.dim("Action IDs:")} ${ac.actionIds.join(", ")}`);
|
|
558
|
+
if (ac.knowledgeAgent) console.log(` ${pc2.dim("Knowledge only:")} yes`);
|
|
618
559
|
}
|
|
560
|
+
console.log();
|
|
619
561
|
const actionOptions = [];
|
|
620
562
|
actionOptions.push({
|
|
621
|
-
value: "
|
|
622
|
-
label: "Update
|
|
563
|
+
value: "install-skills",
|
|
564
|
+
label: skillInstalled ? "Update skill" : "Install skill",
|
|
565
|
+
hint: skillInstalled ? "reinstall latest version" : "recommended"
|
|
623
566
|
});
|
|
624
567
|
actionOptions.push({
|
|
625
|
-
value: "
|
|
626
|
-
label: "
|
|
568
|
+
value: "show-prompt",
|
|
569
|
+
label: "Show agent onboarding prompt",
|
|
570
|
+
hint: "copy-paste to your AI agent"
|
|
571
|
+
});
|
|
572
|
+
actionOptions.push({
|
|
573
|
+
value: "add-connection",
|
|
574
|
+
label: "Connect a platform",
|
|
575
|
+
hint: "add Gmail, Slack, Shopify, etc."
|
|
576
|
+
});
|
|
577
|
+
actionOptions.push({
|
|
578
|
+
value: "update-key",
|
|
579
|
+
label: "Update API key"
|
|
627
580
|
});
|
|
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
581
|
actionOptions.push({
|
|
645
582
|
value: "access-control",
|
|
646
583
|
label: "Configure access control",
|
|
@@ -659,26 +596,26 @@ async function handleExistingConfig(apiKey, options) {
|
|
|
659
596
|
return;
|
|
660
597
|
}
|
|
661
598
|
switch (action) {
|
|
662
|
-
case "update-key":
|
|
663
|
-
await handleUpdateKey(statuses);
|
|
664
|
-
break;
|
|
665
599
|
case "install-skills": {
|
|
666
|
-
const success = await
|
|
600
|
+
const success = await promptSkillInstall();
|
|
667
601
|
if (success) {
|
|
668
|
-
|
|
602
|
+
printOnboardingPrompt();
|
|
603
|
+
p3.outro("Skill installed. Paste the prompt above to your AI agent.");
|
|
669
604
|
} 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
605
|
p3.outro("Done.");
|
|
674
606
|
}
|
|
675
607
|
break;
|
|
676
608
|
}
|
|
677
|
-
case "
|
|
678
|
-
|
|
609
|
+
case "show-prompt":
|
|
610
|
+
printOnboardingPrompt();
|
|
611
|
+
p3.outro("Paste the prompt above to your AI agent.");
|
|
679
612
|
break;
|
|
680
|
-
case "
|
|
681
|
-
await
|
|
613
|
+
case "add-connection":
|
|
614
|
+
await promptConnectIntegrations(apiKey);
|
|
615
|
+
p3.outro("Done.");
|
|
616
|
+
break;
|
|
617
|
+
case "update-key":
|
|
618
|
+
await handleUpdateKey(statuses);
|
|
682
619
|
break;
|
|
683
620
|
case "access-control":
|
|
684
621
|
await configCommand();
|
|
@@ -690,7 +627,7 @@ async function handleExistingConfig(apiKey, options) {
|
|
|
690
627
|
}
|
|
691
628
|
async function handleUpdateKey(statuses) {
|
|
692
629
|
p3.note(`Get your API key at:
|
|
693
|
-
${
|
|
630
|
+
${pc2.cyan(getApiKeyUrl())}`, "API Key");
|
|
694
631
|
const openBrowser = await p3.confirm({
|
|
695
632
|
message: "Open browser to get API key?",
|
|
696
633
|
initialValue: true
|
|
@@ -751,208 +688,165 @@ ${pc3.cyan(getApiKeyUrl())}`, "API Key");
|
|
|
751
688
|
}
|
|
752
689
|
p3.outro("API key updated.");
|
|
753
690
|
}
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
691
|
+
var SKILL_AGENTS = [
|
|
692
|
+
{ id: "claude-code", name: "Claude Code", skillDir: ".claude/skills", primary: true },
|
|
693
|
+
{ id: "claude-desktop", name: "Claude Desktop", skillDir: ".claude/skills", primary: true },
|
|
694
|
+
{ id: "codex", name: "Codex", skillDir: ".codex/skills", primary: true },
|
|
695
|
+
{ id: "cursor", name: "Cursor", skillDir: ".cursor/skills" },
|
|
696
|
+
{ id: "windsurf", name: "Windsurf", skillDir: ".codeium/windsurf/skills" },
|
|
697
|
+
{ id: "kiro", name: "Kiro", skillDir: ".kiro/skills" },
|
|
698
|
+
{ id: "goose", name: "Goose", skillDir: ".config/goose/skills" },
|
|
699
|
+
{ id: "amp", name: "Amp", skillDir: ".amp/skills" },
|
|
700
|
+
{ id: "opencode", name: "OpenCode", skillDir: ".opencode/skills" },
|
|
701
|
+
{ id: "roo", name: "Roo", skillDir: ".roo/skills" }
|
|
702
|
+
];
|
|
703
|
+
var CANONICAL_SKILL_DIR = ".agents/skills";
|
|
704
|
+
function getSkillSourceDir() {
|
|
705
|
+
const __dirname2 = path3.dirname(fileURLToPath(import.meta.url));
|
|
706
|
+
return path3.resolve(__dirname2, "..", "skills", "one");
|
|
707
|
+
}
|
|
708
|
+
function getCanonicalSkillPath() {
|
|
709
|
+
return path3.join(os3.homedir(), CANONICAL_SKILL_DIR, "one");
|
|
710
|
+
}
|
|
711
|
+
function getAgentSkillPath(agent) {
|
|
712
|
+
return path3.join(os3.homedir(), agent.skillDir, "one");
|
|
713
|
+
}
|
|
714
|
+
function isSkillInstalled() {
|
|
715
|
+
return fs3.existsSync(path3.join(getCanonicalSkillPath(), "SKILL.md"));
|
|
716
|
+
}
|
|
717
|
+
function isSkillInstalledForAgent(agent) {
|
|
718
|
+
return fs3.existsSync(path3.join(getAgentSkillPath(agent), "SKILL.md"));
|
|
719
|
+
}
|
|
720
|
+
function copyDirSync(src, dest) {
|
|
721
|
+
fs3.mkdirSync(dest, { recursive: true });
|
|
722
|
+
for (const entry of fs3.readdirSync(src, { withFileTypes: true })) {
|
|
723
|
+
const srcPath = path3.join(src, entry.name);
|
|
724
|
+
const destPath = path3.join(dest, entry.name);
|
|
725
|
+
if (entry.isDirectory()) {
|
|
726
|
+
copyDirSync(srcPath, destPath);
|
|
727
|
+
} else {
|
|
728
|
+
fs3.copyFileSync(srcPath, destPath);
|
|
765
729
|
}
|
|
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
730
|
}
|
|
772
|
-
const selected = await p3.multiselect({
|
|
773
|
-
message: "Select agents to install MCP:",
|
|
774
|
-
options: missing.map((s) => ({
|
|
775
|
-
value: s.agent.id,
|
|
776
|
-
label: s.agent.name
|
|
777
|
-
}))
|
|
778
|
-
});
|
|
779
|
-
if (p3.isCancel(selected)) {
|
|
780
|
-
p3.outro("No changes made.");
|
|
781
|
-
return;
|
|
782
|
-
}
|
|
783
|
-
const agents = missing.filter((s) => selected.includes(s.agent.id));
|
|
784
|
-
for (const s of agents) {
|
|
785
|
-
installMcpConfig(s.agent, apiKey, "global", ac);
|
|
786
|
-
updateConfigAgents(s.agent.id);
|
|
787
|
-
p3.log.success(`${s.agent.name}: MCP installed`);
|
|
788
|
-
}
|
|
789
|
-
p3.outro("Done.");
|
|
790
731
|
}
|
|
791
|
-
|
|
792
|
-
const
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
});
|
|
799
|
-
if (p3.isCancel(confirm3) || !confirm3) {
|
|
800
|
-
p3.outro("No changes made.");
|
|
801
|
-
return;
|
|
802
|
-
}
|
|
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;
|
|
732
|
+
function installSkillForAgents(agentIds) {
|
|
733
|
+
const source = getSkillSourceDir();
|
|
734
|
+
const canonical = getCanonicalSkillPath();
|
|
735
|
+
const installed = [];
|
|
736
|
+
const failed = [];
|
|
737
|
+
if (!fs3.existsSync(path3.join(source, "SKILL.md"))) {
|
|
738
|
+
return { installed: [], failed: ["skill source not found"] };
|
|
812
739
|
}
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
if (p3.isCancel(selected)) {
|
|
821
|
-
p3.outro("No changes made.");
|
|
822
|
-
return;
|
|
740
|
+
try {
|
|
741
|
+
if (fs3.existsSync(canonical)) {
|
|
742
|
+
fs3.rmSync(canonical, { recursive: true });
|
|
743
|
+
}
|
|
744
|
+
copyDirSync(source, canonical);
|
|
745
|
+
} catch {
|
|
746
|
+
return { installed: [], failed: ["canonical copy"] };
|
|
823
747
|
}
|
|
824
|
-
const
|
|
825
|
-
for (const
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
748
|
+
const seen = /* @__PURE__ */ new Map();
|
|
749
|
+
for (const id of agentIds) {
|
|
750
|
+
const agent = SKILL_AGENTS.find((a) => a.id === id);
|
|
751
|
+
if (!agent) continue;
|
|
752
|
+
const agentPath = getAgentSkillPath(agent);
|
|
753
|
+
if (seen.has(agentPath)) {
|
|
754
|
+
(seen.get(agentPath) ? installed : failed).push(agent.name);
|
|
755
|
+
continue;
|
|
756
|
+
}
|
|
757
|
+
try {
|
|
758
|
+
const agentSkillsDir = path3.dirname(agentPath);
|
|
759
|
+
fs3.mkdirSync(agentSkillsDir, { recursive: true });
|
|
760
|
+
try {
|
|
761
|
+
fs3.lstatSync(agentPath);
|
|
762
|
+
fs3.rmSync(agentPath, { recursive: true });
|
|
763
|
+
} catch {
|
|
764
|
+
}
|
|
765
|
+
const relative = path3.relative(agentSkillsDir, canonical);
|
|
766
|
+
fs3.symlinkSync(relative, agentPath);
|
|
767
|
+
installed.push(agent.name);
|
|
768
|
+
seen.set(agentPath, true);
|
|
769
|
+
} catch {
|
|
770
|
+
failed.push(agent.name);
|
|
771
|
+
seen.set(agentPath, false);
|
|
772
|
+
}
|
|
829
773
|
}
|
|
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.");
|
|
774
|
+
return { installed, failed };
|
|
835
775
|
}
|
|
836
|
-
async function
|
|
837
|
-
const
|
|
838
|
-
const
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
776
|
+
async function promptSkillInstall() {
|
|
777
|
+
const primaryAgents = SKILL_AGENTS.filter((a) => a.primary);
|
|
778
|
+
const otherAgents = SKILL_AGENTS.filter((a) => !a.primary);
|
|
779
|
+
const options = [
|
|
780
|
+
...primaryAgents.map((a) => ({
|
|
781
|
+
value: a.id,
|
|
782
|
+
label: a.name,
|
|
783
|
+
hint: isSkillInstalledForAgent(a) ? pc2.green("installed") : void 0
|
|
784
|
+
})),
|
|
785
|
+
{
|
|
786
|
+
value: "_other",
|
|
787
|
+
label: "Other agents",
|
|
788
|
+
hint: otherAgents.map((a) => a.name).join(", ")
|
|
789
|
+
}
|
|
790
|
+
];
|
|
791
|
+
const choice = await p3.multiselect({
|
|
792
|
+
message: "Install the One skill to:",
|
|
793
|
+
options,
|
|
794
|
+
initialValues: primaryAgents.map((a) => a.id)
|
|
855
795
|
});
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
value: agent.id,
|
|
869
|
-
label: agent.name
|
|
796
|
+
if (p3.isCancel(choice)) {
|
|
797
|
+
return false;
|
|
798
|
+
}
|
|
799
|
+
let selectedIds = choice;
|
|
800
|
+
if (selectedIds.includes("_other")) {
|
|
801
|
+
selectedIds = selectedIds.filter((id) => id !== "_other");
|
|
802
|
+
const otherChoice = await p3.multiselect({
|
|
803
|
+
message: "Select additional agents:",
|
|
804
|
+
options: otherAgents.map((a) => ({
|
|
805
|
+
value: a.id,
|
|
806
|
+
label: a.name,
|
|
807
|
+
hint: isSkillInstalledForAgent(a) ? pc2.green("installed") : void 0
|
|
870
808
|
}))
|
|
871
|
-
]
|
|
872
|
-
});
|
|
873
|
-
if (p3.isCancel(agentChoice)) {
|
|
874
|
-
p3.log.info("Skipped MCP installation.");
|
|
875
|
-
return;
|
|
876
|
-
}
|
|
877
|
-
const selectedAgents = agentChoice === "all" ? allAgents : allAgents.filter((a) => a.id === agentChoice);
|
|
878
|
-
let scope = "global";
|
|
879
|
-
const hasProjectScopeAgent = selectedAgents.some((a) => supportsProjectScope(a));
|
|
880
|
-
if (options.global) {
|
|
881
|
-
scope = "global";
|
|
882
|
-
} else if (options.project) {
|
|
883
|
-
scope = "project";
|
|
884
|
-
} else if (hasProjectScopeAgent) {
|
|
885
|
-
const scopeChoice = await p3.select({
|
|
886
|
-
message: "How do you want to install it?",
|
|
887
|
-
options: [
|
|
888
|
-
{
|
|
889
|
-
value: "global",
|
|
890
|
-
label: "Global (Recommended)",
|
|
891
|
-
hint: "Available in all your projects"
|
|
892
|
-
},
|
|
893
|
-
{
|
|
894
|
-
value: "project",
|
|
895
|
-
label: "Project only",
|
|
896
|
-
hint: "Creates config files in current directory"
|
|
897
|
-
}
|
|
898
|
-
]
|
|
899
809
|
});
|
|
900
|
-
if (p3.isCancel(
|
|
901
|
-
|
|
902
|
-
return;
|
|
903
|
-
}
|
|
904
|
-
scope = scopeChoice;
|
|
905
|
-
}
|
|
906
|
-
if (scope === "project") {
|
|
907
|
-
const projectAgents = selectedAgents.filter((a) => supportsProjectScope(a));
|
|
908
|
-
const nonProjectAgents = selectedAgents.filter((a) => !supportsProjectScope(a));
|
|
909
|
-
if (projectAgents.length === 0) {
|
|
910
|
-
const supported = allAgents.filter((a) => supportsProjectScope(a)).map((a) => a.name).join(", ");
|
|
911
|
-
p3.note(
|
|
912
|
-
`${selectedAgents.map((a) => a.name).join(", ")} does not support project-level MCP.
|
|
913
|
-
Project scope is supported by: ${supported}`,
|
|
914
|
-
"Not Supported"
|
|
915
|
-
);
|
|
916
|
-
p3.log.warn("Run again and choose global scope or a different agent.");
|
|
917
|
-
return;
|
|
918
|
-
}
|
|
919
|
-
for (const agent of projectAgents) {
|
|
920
|
-
const wasInstalled = isMcpInstalled(agent, "project");
|
|
921
|
-
installMcpConfig(agent, apiKey, "project");
|
|
922
|
-
const configPath = getAgentConfigPath(agent, "project");
|
|
923
|
-
const status = wasInstalled ? "updated" : "created";
|
|
924
|
-
p3.log.success(`${agent.name}: ${configPath} ${status}`);
|
|
925
|
-
}
|
|
926
|
-
if (nonProjectAgents.length > 0) {
|
|
927
|
-
p3.log.info(`Installing globally for agents without project scope support:`);
|
|
928
|
-
for (const agent of nonProjectAgents) {
|
|
929
|
-
const wasInstalled = isMcpInstalled(agent, "global");
|
|
930
|
-
installMcpConfig(agent, apiKey, "global");
|
|
931
|
-
const status = wasInstalled ? "updated" : "installed";
|
|
932
|
-
p3.log.success(`${agent.name}: MCP ${status} (global)`);
|
|
933
|
-
}
|
|
810
|
+
if (!p3.isCancel(otherChoice)) {
|
|
811
|
+
selectedIds.push(...otherChoice);
|
|
934
812
|
}
|
|
935
|
-
const allInstalled = [...projectAgents, ...nonProjectAgents];
|
|
936
|
-
updateConfigAgentsList(allInstalled.map((a) => a.id));
|
|
937
|
-
p3.note(
|
|
938
|
-
pc3.yellow("Project config files can be committed to share with your team.\n") + pc3.yellow("Team members will need their own API key."),
|
|
939
|
-
"Tip"
|
|
940
|
-
);
|
|
941
|
-
return;
|
|
942
813
|
}
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
814
|
+
if (selectedIds.length === 0) {
|
|
815
|
+
p3.log.info("No agents selected.");
|
|
816
|
+
return false;
|
|
817
|
+
}
|
|
818
|
+
const spinner5 = p3.spinner();
|
|
819
|
+
spinner5.start("Installing skill...");
|
|
820
|
+
const { installed, failed } = installSkillForAgents(selectedIds);
|
|
821
|
+
spinner5.stop(installed.length > 0 ? "Skill installed" : "Installation failed");
|
|
822
|
+
for (const name of installed) {
|
|
823
|
+
p3.log.success(`${name}: ${pc2.green("\u2713")} skill installed`);
|
|
824
|
+
}
|
|
825
|
+
for (const name of failed) {
|
|
826
|
+
p3.log.warn(`${name}: failed to install`);
|
|
950
827
|
}
|
|
951
|
-
|
|
828
|
+
return installed.length > 0;
|
|
829
|
+
}
|
|
830
|
+
function printOnboardingPrompt() {
|
|
831
|
+
console.log();
|
|
832
|
+
console.log(pc2.bold(" Copy-paste this to your AI agent:"));
|
|
833
|
+
console.log();
|
|
834
|
+
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"));
|
|
835
|
+
console.log(pc2.cyan(" \u2502"));
|
|
836
|
+
console.log(pc2.cyan(" \u2502 The One CLI (`one`) is now installed on this machine. It"));
|
|
837
|
+
console.log(pc2.cyan(" \u2502 lets you interact with 250+ third-party platforms (Gmail,"));
|
|
838
|
+
console.log(pc2.cyan(" \u2502 Slack, Shopify, HubSpot, Stripe, GitHub, etc.) through"));
|
|
839
|
+
console.log(pc2.cyan(" \u2502 their APIs. Whenever you need to interact with any"));
|
|
840
|
+
console.log(pc2.cyan(" \u2502 third-party platform or external service, use the `one`"));
|
|
841
|
+
console.log(pc2.cyan(" \u2502 skill. Please save this to your project instructions or"));
|
|
842
|
+
console.log(pc2.cyan(" \u2502 memory so you remember it in future conversations."));
|
|
843
|
+
console.log(pc2.cyan(" \u2502"));
|
|
844
|
+
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"));
|
|
845
|
+
console.log();
|
|
952
846
|
}
|
|
953
847
|
async function freshSetup(options) {
|
|
954
848
|
p3.note(`Get your API key at:
|
|
955
|
-
${
|
|
849
|
+
${pc2.cyan(getApiKeyUrl())}`, "API Key");
|
|
956
850
|
const openBrowser = await p3.confirm({
|
|
957
851
|
message: "Open browser to get API key?",
|
|
958
852
|
initialValue: true
|
|
@@ -994,52 +888,29 @@ ${pc3.cyan(getApiKeyUrl())}`, "API Key");
|
|
|
994
888
|
installedAgents: [],
|
|
995
889
|
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
996
890
|
});
|
|
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
|
-
}
|
|
891
|
+
await promptSkillInstall();
|
|
1011
892
|
await promptConnectIntegrations(apiKey);
|
|
1012
|
-
const installMcp = await p3.confirm({
|
|
1013
|
-
message: "Install One MCP server to your AI agents? (not recommended)",
|
|
1014
|
-
initialValue: false
|
|
1015
|
-
});
|
|
1016
|
-
if (!p3.isCancel(installMcp) && installMcp) {
|
|
1017
|
-
await promptAndInstallMcp(apiKey, options);
|
|
1018
|
-
}
|
|
1019
893
|
p3.note(
|
|
1020
|
-
`Config saved to: ${
|
|
894
|
+
`Config saved to: ${pc2.dim(getConfigPath())}`,
|
|
1021
895
|
"Setup Complete"
|
|
1022
896
|
);
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
"Next Step"
|
|
1026
|
-
);
|
|
1027
|
-
p3.outro("Your AI agents now have access to One integrations!");
|
|
897
|
+
printOnboardingPrompt();
|
|
898
|
+
p3.outro("Done! Paste the prompt above to your AI agent.");
|
|
1028
899
|
}
|
|
1029
900
|
function printBanner() {
|
|
1030
901
|
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(
|
|
902
|
+
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"));
|
|
903
|
+
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"));
|
|
904
|
+
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 "));
|
|
905
|
+
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 "));
|
|
906
|
+
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 "));
|
|
907
|
+
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 "));
|
|
908
|
+
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 "));
|
|
909
|
+
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 "));
|
|
910
|
+
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"));
|
|
911
|
+
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
912
|
console.log();
|
|
1042
|
-
console.log(
|
|
913
|
+
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
914
|
console.log();
|
|
1044
915
|
}
|
|
1045
916
|
var TOP_INTEGRATIONS = [
|
|
@@ -1084,13 +955,13 @@ async function promptConnectIntegrations(apiKey) {
|
|
|
1084
955
|
} catch {
|
|
1085
956
|
p3.note("https://app.withone.ai/connections", "Open in browser");
|
|
1086
957
|
}
|
|
1087
|
-
p3.log.info(`Connect from the dashboard, or use ${
|
|
958
|
+
p3.log.info(`Connect from the dashboard, or use ${pc2.cyan("one add <platform>")}`);
|
|
1088
959
|
break;
|
|
1089
960
|
}
|
|
1090
961
|
const platform = choice;
|
|
1091
962
|
const integration = TOP_INTEGRATIONS.find((i) => i.value === platform);
|
|
1092
963
|
const label = integration?.label ?? platform;
|
|
1093
|
-
p3.log.info(`Opening browser to connect ${
|
|
964
|
+
p3.log.info(`Opening browser to connect ${pc2.cyan(label)}...`);
|
|
1094
965
|
try {
|
|
1095
966
|
await openConnectionPage(platform);
|
|
1096
967
|
} catch {
|
|
@@ -1103,13 +974,13 @@ async function promptConnectIntegrations(apiKey) {
|
|
|
1103
974
|
try {
|
|
1104
975
|
await api.waitForConnection(platform, 5 * 60 * 1e3, 5e3);
|
|
1105
976
|
spinner5.stop(`${label} connected!`);
|
|
1106
|
-
p3.log.success(`${
|
|
977
|
+
p3.log.success(`${pc2.green("\u2713")} ${label} is now available to your AI agents`);
|
|
1107
978
|
connected.push(platform);
|
|
1108
979
|
first = false;
|
|
1109
980
|
} catch (error2) {
|
|
1110
981
|
spinner5.stop("Connection timed out");
|
|
1111
982
|
if (error2 instanceof TimeoutError) {
|
|
1112
|
-
p3.log.warn(`No worries. Connect later with: ${
|
|
983
|
+
p3.log.warn(`No worries. Connect later with: ${pc2.cyan(`one add ${platform}`)}`);
|
|
1113
984
|
}
|
|
1114
985
|
first = false;
|
|
1115
986
|
}
|
|
@@ -1123,24 +994,6 @@ function maskApiKey(key) {
|
|
|
1123
994
|
if (key.length <= 12) return key.slice(0, 8) + "...";
|
|
1124
995
|
return key.slice(0, 8) + "..." + key.slice(-4);
|
|
1125
996
|
}
|
|
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
|
-
function updateConfigAgentsList(agentIds) {
|
|
1135
|
-
const config = readConfig();
|
|
1136
|
-
if (!config) return;
|
|
1137
|
-
for (const id of agentIds) {
|
|
1138
|
-
if (!config.installedAgents.includes(id)) {
|
|
1139
|
-
config.installedAgents.push(id);
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
writeConfig(config);
|
|
1143
|
-
}
|
|
1144
997
|
|
|
1145
998
|
// src/commands/connection.ts
|
|
1146
999
|
import * as p4 from "@clack/prompts";
|
|
@@ -1181,6 +1034,42 @@ function countMatchingChars(a, b) {
|
|
|
1181
1034
|
return count;
|
|
1182
1035
|
}
|
|
1183
1036
|
|
|
1037
|
+
// src/lib/table.ts
|
|
1038
|
+
import pc3 from "picocolors";
|
|
1039
|
+
function printTable(columns, rows) {
|
|
1040
|
+
if (rows.length === 0) return;
|
|
1041
|
+
const gap = " ";
|
|
1042
|
+
const indent = " ";
|
|
1043
|
+
const widths = columns.map((col) => {
|
|
1044
|
+
const headerLen = col.label.length;
|
|
1045
|
+
const maxValueLen = Math.max(...rows.map((row) => stripAnsi(row[col.key] || "").length));
|
|
1046
|
+
return Math.max(headerLen, maxValueLen);
|
|
1047
|
+
});
|
|
1048
|
+
const header = columns.map((col, i) => {
|
|
1049
|
+
const padded = col.align === "right" ? col.label.padStart(widths[i]) : col.label.padEnd(widths[i]);
|
|
1050
|
+
return pc3.dim(padded);
|
|
1051
|
+
}).join(gap);
|
|
1052
|
+
console.log(`${indent}${header}`);
|
|
1053
|
+
const separator = columns.map((_, i) => pc3.dim("\u2500".repeat(widths[i]))).join(gap);
|
|
1054
|
+
console.log(`${indent}${separator}`);
|
|
1055
|
+
for (const row of rows) {
|
|
1056
|
+
const line = columns.map((col, i) => {
|
|
1057
|
+
const raw = row[col.key] || "";
|
|
1058
|
+
const rawLen = stripAnsi(raw).length;
|
|
1059
|
+
const padding = widths[i] - rawLen;
|
|
1060
|
+
const colored = col.color ? col.color(raw) : raw;
|
|
1061
|
+
if (col.align === "right") {
|
|
1062
|
+
return " ".repeat(Math.max(0, padding)) + colored;
|
|
1063
|
+
}
|
|
1064
|
+
return colored + " ".repeat(Math.max(0, padding));
|
|
1065
|
+
}).join(gap);
|
|
1066
|
+
console.log(`${indent}${line}`);
|
|
1067
|
+
}
|
|
1068
|
+
}
|
|
1069
|
+
function stripAnsi(str) {
|
|
1070
|
+
return str.replace(/\x1b\[[0-9;]*m/g, "");
|
|
1071
|
+
}
|
|
1072
|
+
|
|
1184
1073
|
// src/commands/connection.ts
|
|
1185
1074
|
async function connectionAddCommand(platformArg) {
|
|
1186
1075
|
if (isAgentMode()) {
|
|
@@ -2513,7 +2402,7 @@ function validateFlow(flow2) {
|
|
|
2513
2402
|
}
|
|
2514
2403
|
|
|
2515
2404
|
// src/commands/flow.ts
|
|
2516
|
-
import
|
|
2405
|
+
import fs4 from "fs";
|
|
2517
2406
|
function getConfig2() {
|
|
2518
2407
|
const apiKey = getApiKey();
|
|
2519
2408
|
if (!apiKey) {
|
|
@@ -2571,7 +2460,7 @@ async function flowCreateCommand(key, options) {
|
|
|
2571
2460
|
if (raw.startsWith("@")) {
|
|
2572
2461
|
const filePath = raw.slice(1);
|
|
2573
2462
|
try {
|
|
2574
|
-
raw =
|
|
2463
|
+
raw = fs4.readFileSync(filePath, "utf-8");
|
|
2575
2464
|
} catch (err) {
|
|
2576
2465
|
error(`Cannot read file "${filePath}": ${err.message}`);
|
|
2577
2466
|
}
|
|
@@ -2754,7 +2643,7 @@ async function flowValidateCommand(keyOrPath) {
|
|
|
2754
2643
|
let flowData;
|
|
2755
2644
|
try {
|
|
2756
2645
|
const flowPath = resolveFlowPath(keyOrPath);
|
|
2757
|
-
const content =
|
|
2646
|
+
const content = fs4.readFileSync(flowPath, "utf-8");
|
|
2758
2647
|
flowData = JSON.parse(content);
|
|
2759
2648
|
} catch (err) {
|
|
2760
2649
|
spinner5.stop("Validation failed");
|
|
@@ -3451,7 +3340,7 @@ Before using any feature, read its guide section first: \`one guide actions\`, \
|
|
|
3451
3340
|
|
|
3452
3341
|
## Features
|
|
3453
3342
|
|
|
3454
|
-
### 1. Actions \u2014 Execute API calls on
|
|
3343
|
+
### 1. Actions \u2014 Execute API calls on 250+ platforms
|
|
3455
3344
|
Search for actions, read their docs, and execute them. This is the core workflow.
|
|
3456
3345
|
|
|
3457
3346
|
**Quick start:**
|
|
@@ -3812,7 +3701,7 @@ function buildStep1() {
|
|
|
3812
3701
|
nextCommand: "one onboard --step 2",
|
|
3813
3702
|
message: `# One CLI \u2014 Agent Onboarding
|
|
3814
3703
|
|
|
3815
|
-
You now have access to the One CLI. It connects you to
|
|
3704
|
+
You now have access to the One CLI. It connects you to 250+ platforms
|
|
3816
3705
|
(Gmail, Slack, Stripe, Notion, etc.) \u2014 you'll learn the details shortly.
|
|
3817
3706
|
|
|
3818
3707
|
IMPORTANT: Your only task right now is to send the message below to the
|
|
@@ -3822,7 +3711,7 @@ Do not offer demos yet. Just send this message and wait for their reply:
|
|
|
3822
3711
|
---
|
|
3823
3712
|
|
|
3824
3713
|
I just got access to the One CLI \u2014 it connects me to your platforms like
|
|
3825
|
-
Gmail, Slack, Stripe, and
|
|
3714
|
+
Gmail, Slack, Stripe, and 250+ others so I can work with them directly.
|
|
3826
3715
|
I'll show you what I can do in a moment.
|
|
3827
3716
|
|
|
3828
3717
|
First, one quick setup step: right now only this conversation knows about
|
|
@@ -3851,7 +3740,7 @@ If they declined, skip this section.
|
|
|
3851
3740
|
## One CLI \u2014 Platform Integrations
|
|
3852
3741
|
|
|
3853
3742
|
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
|
|
3743
|
+
command-line tool that gives AI agents the ability to interact with 250+
|
|
3855
3744
|
third-party platforms (Gmail, Slack, Shopify, HubSpot, Stripe, GitHub,
|
|
3856
3745
|
Notion, Salesforce, etc.) through a single, unified interface.
|
|
3857
3746
|
|
|
@@ -3946,7 +3835,7 @@ function buildStep3(connections) {
|
|
|
3946
3835
|
The user can connect any of these popular platforms:
|
|
3947
3836
|
Gmail, Google Calendar, Slack, Notion, Shopify, Stripe, HubSpot, GitHub,
|
|
3948
3837
|
Salesforce, QuickBooks, Asana, Jira, Linear, Intercom, Zendesk, Twilio,
|
|
3949
|
-
and
|
|
3838
|
+
and 250+ more. Run \`one platforms\` for the full list.`);
|
|
3950
3839
|
sections.push("## Onboarding complete!\n\nYou're all set. Use `one --agent guide` any time you need the full reference.");
|
|
3951
3840
|
return {
|
|
3952
3841
|
step: 3,
|
|
@@ -3977,7 +3866,7 @@ platform before you can start using actions. Suggest they run:
|
|
|
3977
3866
|
one add slack
|
|
3978
3867
|
one add <any-platform>
|
|
3979
3868
|
|
|
3980
|
-
Run \`one platforms\` to see all
|
|
3869
|
+
Run \`one platforms\` to see all 250+ available platforms.`;
|
|
3981
3870
|
}
|
|
3982
3871
|
const header = `## Current State
|
|
3983
3872
|
|
|
@@ -4037,20 +3926,23 @@ function buildWorkflowIdeas(connections) {
|
|
|
4037
3926
|
|
|
4038
3927
|
// src/commands/update.ts
|
|
4039
3928
|
import { createRequire } from "module";
|
|
4040
|
-
import { spawn
|
|
3929
|
+
import { spawn } from "child_process";
|
|
4041
3930
|
import { readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
4042
3931
|
import { homedir } from "os";
|
|
4043
3932
|
import { join } from "path";
|
|
4044
3933
|
var require2 = createRequire(import.meta.url);
|
|
4045
3934
|
var { version: currentVersion } = require2("../package.json");
|
|
4046
3935
|
var CACHE_PATH = join(homedir(), ".one", "update-check.json");
|
|
4047
|
-
var CHECK_INTERVAL_MS =
|
|
4048
|
-
|
|
3936
|
+
var CHECK_INTERVAL_MS = 4 * 60 * 60 * 1e3;
|
|
3937
|
+
var AGE_GATE_MS = 30 * 60 * 1e3;
|
|
3938
|
+
async function fetchLatestVersionInfo() {
|
|
4049
3939
|
try {
|
|
4050
|
-
const res = await fetch("https://registry.npmjs.org/@withone/cli
|
|
3940
|
+
const res = await fetch("https://registry.npmjs.org/@withone/cli");
|
|
4051
3941
|
if (!res.ok) return null;
|
|
4052
3942
|
const data = await res.json();
|
|
4053
|
-
|
|
3943
|
+
const latest = data["dist-tags"]?.latest;
|
|
3944
|
+
if (!latest) return null;
|
|
3945
|
+
return { version: latest, publishedAt: data.time?.[latest] ?? null };
|
|
4054
3946
|
} catch {
|
|
4055
3947
|
return null;
|
|
4056
3948
|
}
|
|
@@ -4062,24 +3954,26 @@ function readCache() {
|
|
|
4062
3954
|
return null;
|
|
4063
3955
|
}
|
|
4064
3956
|
}
|
|
4065
|
-
function writeCache(latestVersion) {
|
|
3957
|
+
function writeCache(latestVersion, publishedAt) {
|
|
4066
3958
|
try {
|
|
4067
3959
|
mkdirSync(join(homedir(), ".one"), { recursive: true });
|
|
4068
|
-
writeFileSync(CACHE_PATH, JSON.stringify({ lastCheck: Date.now(), latestVersion }));
|
|
3960
|
+
writeFileSync(CACHE_PATH, JSON.stringify({ lastCheck: Date.now(), latestVersion, publishedAt }));
|
|
4069
3961
|
} catch {
|
|
4070
3962
|
}
|
|
4071
3963
|
}
|
|
4072
3964
|
async function checkLatestVersion() {
|
|
4073
|
-
const
|
|
4074
|
-
if (
|
|
4075
|
-
return
|
|
3965
|
+
const info = await fetchLatestVersionInfo();
|
|
3966
|
+
if (info) writeCache(info.version, info.publishedAt);
|
|
3967
|
+
return info?.version ?? null;
|
|
4076
3968
|
}
|
|
4077
3969
|
async function checkLatestVersionCached() {
|
|
4078
3970
|
const cache = readCache();
|
|
4079
3971
|
if (cache && Date.now() - cache.lastCheck < CHECK_INTERVAL_MS) {
|
|
4080
|
-
return cache.latestVersion;
|
|
3972
|
+
return { version: cache.latestVersion, publishedAt: cache.publishedAt ?? null };
|
|
4081
3973
|
}
|
|
4082
|
-
|
|
3974
|
+
const info = await fetchLatestVersionInfo();
|
|
3975
|
+
if (info) writeCache(info.version, info.publishedAt);
|
|
3976
|
+
return info;
|
|
4083
3977
|
}
|
|
4084
3978
|
function getCurrentVersion() {
|
|
4085
3979
|
return currentVersion;
|
|
@@ -4104,7 +3998,7 @@ async function updateCommand() {
|
|
|
4104
3998
|
s.stop(`Update available: v${currentVersion} \u2192 v${latestVersion}`);
|
|
4105
3999
|
console.log(`Updating @withone/cli: v${currentVersion} \u2192 v${latestVersion}...`);
|
|
4106
4000
|
const code = await new Promise((resolve) => {
|
|
4107
|
-
const child =
|
|
4001
|
+
const child = spawn("npm", ["install", "-g", "@withone/cli@latest", "--force"], {
|
|
4108
4002
|
stdio: isAgentMode() ? "pipe" : "inherit",
|
|
4109
4003
|
shell: true
|
|
4110
4004
|
});
|
|
@@ -4121,12 +4015,24 @@ async function updateCommand() {
|
|
|
4121
4015
|
error("Update failed \u2014 try running: npm install -g @withone/cli@latest");
|
|
4122
4016
|
}
|
|
4123
4017
|
}
|
|
4018
|
+
function autoUpdate(targetVersion, publishedAt) {
|
|
4019
|
+
if (publishedAt) {
|
|
4020
|
+
const age = Date.now() - new Date(publishedAt).getTime();
|
|
4021
|
+
if (age < AGE_GATE_MS) return;
|
|
4022
|
+
}
|
|
4023
|
+
const child = spawn("npm", ["install", "-g", `@withone/cli@${targetVersion}`], {
|
|
4024
|
+
detached: true,
|
|
4025
|
+
stdio: "ignore",
|
|
4026
|
+
shell: true
|
|
4027
|
+
});
|
|
4028
|
+
child.unref();
|
|
4029
|
+
}
|
|
4124
4030
|
|
|
4125
4031
|
// src/index.ts
|
|
4126
4032
|
var require3 = createRequire2(import.meta.url);
|
|
4127
4033
|
var { version } = require3("../package.json");
|
|
4128
4034
|
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
|
|
4035
|
+
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
4036
|
|
|
4131
4037
|
Setup:
|
|
4132
4038
|
one init Set up API key and install MCP server
|
|
@@ -4170,7 +4076,7 @@ program.name("one").option("--agent", "Machine-readable JSON output (no colors,
|
|
|
4170
4076
|
-d '{"to":"j@example.com","subject":"Hello","body":"Hi!","connectionKey":"live::gmail::default::abc123"}'
|
|
4171
4077
|
|
|
4172
4078
|
Platform names are always kebab-case (e.g. hub-spot, ship-station, google-calendar).
|
|
4173
|
-
Run 'one platforms' to browse all
|
|
4079
|
+
Run 'one platforms' to browse all 250+ available platforms.`).version(version);
|
|
4174
4080
|
var updateCheckPromise;
|
|
4175
4081
|
program.hook("preAction", (thisCommand) => {
|
|
4176
4082
|
const opts = program.opts();
|
|
@@ -4184,18 +4090,11 @@ program.hook("preAction", (thisCommand) => {
|
|
|
4184
4090
|
});
|
|
4185
4091
|
program.hook("postAction", async () => {
|
|
4186
4092
|
if (!updateCheckPromise) return;
|
|
4187
|
-
const
|
|
4188
|
-
if (!
|
|
4093
|
+
const info = await updateCheckPromise;
|
|
4094
|
+
if (!info) return;
|
|
4189
4095
|
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
|
-
}
|
|
4096
|
+
if (current === info.version) return;
|
|
4097
|
+
autoUpdate(info.version, info.publishedAt);
|
|
4199
4098
|
});
|
|
4200
4099
|
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
4100
|
await initCommand(options);
|