@fargowealth/fargo-ai-cli 0.1.0 → 0.2.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/README.md +1 -0
- package/package.json +1 -1
- package/src/cli.mjs +33 -14
- package/src/constants.mjs +1 -1
- package/src/workbuddy-install.mjs +73 -0
package/README.md
CHANGED
package/package.json
CHANGED
package/src/cli.mjs
CHANGED
|
@@ -2,6 +2,7 @@ import { createCredentialStore } from "./credential-store.mjs";
|
|
|
2
2
|
import { currentCredential, openBrowser, pollDeviceAuthorization, startDeviceAuthorization } from "./auth.mjs";
|
|
3
3
|
import { CLI_VERSION } from "./constants.mjs";
|
|
4
4
|
import { runMcpProxy } from "./mcp-proxy.mjs";
|
|
5
|
+
import { installWorkBuddyMcp } from "./workbuddy-install.mjs";
|
|
5
6
|
|
|
6
7
|
export async function runCli(args, options = {}) {
|
|
7
8
|
const stdout = options.stdout ?? process.stdout;
|
|
@@ -13,19 +14,7 @@ export async function runCli(args, options = {}) {
|
|
|
13
14
|
return;
|
|
14
15
|
}
|
|
15
16
|
if (args[0] === "auth" && args[1] === "device") {
|
|
16
|
-
|
|
17
|
-
stdout.write(`${JSON.stringify({
|
|
18
|
-
type: "device_authorization",
|
|
19
|
-
user_code: device.user_code,
|
|
20
|
-
verification_uri: device.verification_uri,
|
|
21
|
-
verification_uri_complete: device.verification_uri_complete,
|
|
22
|
-
expires_in: device.expires_in,
|
|
23
|
-
interval: device.interval
|
|
24
|
-
})}\n`);
|
|
25
|
-
const browserMode = optionValue(args, "--open-browser") ?? "auto";
|
|
26
|
-
if (browserMode !== "never" && options.openBrowser !== false) (options.browserOpener ?? openBrowser)(device.verification_uri_complete || device.verification_uri);
|
|
27
|
-
await pollDeviceAuthorization(device, store, options);
|
|
28
|
-
stdout.write(`${JSON.stringify({ type: "authorization_complete", logged_in: true, method: "oauth" })}\n`);
|
|
17
|
+
await authorizeDevice(args, stdout, store, options);
|
|
29
18
|
return;
|
|
30
19
|
}
|
|
31
20
|
if (args[0] === "auth" && args[1] === "status") {
|
|
@@ -43,7 +32,21 @@ export async function runCli(args, options = {}) {
|
|
|
43
32
|
await runMcpProxy(store, options);
|
|
44
33
|
return;
|
|
45
34
|
}
|
|
46
|
-
|
|
35
|
+
if (args[0] === "workbuddy" && args[1] === "install") {
|
|
36
|
+
let credential = await store.load();
|
|
37
|
+
if (credential) {
|
|
38
|
+
try {
|
|
39
|
+
credential = await currentCredential(store, options);
|
|
40
|
+
} catch {
|
|
41
|
+
await store.clear();
|
|
42
|
+
credential = undefined;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (!credential?.refresh_token) await authorizeDevice(args, stdout, store, options);
|
|
46
|
+
stdout.write(`${JSON.stringify(await installWorkBuddyMcp(options))}\n`);
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
throw new Error("Usage: fargo auth device|status|logout | fargo workbuddy install | fargo mcp serve | fargo version");
|
|
47
50
|
} catch (error) {
|
|
48
51
|
stderr.write(`fargo: ${error instanceof Error ? error.message : "unknown error"}\n`);
|
|
49
52
|
if (options.throwOnError) throw error;
|
|
@@ -51,6 +54,22 @@ export async function runCli(args, options = {}) {
|
|
|
51
54
|
}
|
|
52
55
|
}
|
|
53
56
|
|
|
57
|
+
async function authorizeDevice(args, stdout, store, options) {
|
|
58
|
+
const device = await startDeviceAuthorization(options);
|
|
59
|
+
stdout.write(`${JSON.stringify({
|
|
60
|
+
type: "device_authorization",
|
|
61
|
+
user_code: device.user_code,
|
|
62
|
+
verification_uri: device.verification_uri,
|
|
63
|
+
verification_uri_complete: device.verification_uri_complete,
|
|
64
|
+
expires_in: device.expires_in,
|
|
65
|
+
interval: device.interval
|
|
66
|
+
})}\n`);
|
|
67
|
+
const browserMode = optionValue(args, "--open-browser") ?? "auto";
|
|
68
|
+
if (browserMode !== "never" && options.openBrowser !== false) (options.browserOpener ?? openBrowser)(device.verification_uri_complete || device.verification_uri);
|
|
69
|
+
await pollDeviceAuthorization(device, store, options);
|
|
70
|
+
stdout.write(`${JSON.stringify({ type: "authorization_complete", logged_in: true, method: "oauth" })}\n`);
|
|
71
|
+
}
|
|
72
|
+
|
|
54
73
|
function optionValue(args, name) {
|
|
55
74
|
const inline = args.find((value) => value.startsWith(`${name}=`));
|
|
56
75
|
if (inline) return inline.slice(name.length + 1);
|
package/src/constants.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export const CLI_VERSION = "0.1
|
|
1
|
+
export const CLI_VERSION = "0.2.1";
|
|
2
2
|
export const DEVICE_CODE_GRANT_TYPE = "urn:ietf:params:oauth:grant-type:device_code";
|
|
3
3
|
export const DEFAULT_AUTH_URL = "https://auth.fargowealth.app";
|
|
4
4
|
export const DEFAULT_MCP_URL = "https://mcp.fargowealth.app/mcp";
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { mkdir, readFile, rename, writeFile } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { CLI_VERSION } from "./constants.mjs";
|
|
5
|
+
|
|
6
|
+
const PACKAGE_NAME = "@fargowealth/fargo-ai-cli";
|
|
7
|
+
|
|
8
|
+
export async function installWorkBuddyMcp(options = {}) {
|
|
9
|
+
const configPath = options.configPath
|
|
10
|
+
?? process.env.FARGO_WORKBUDDY_MCP_CONFIG
|
|
11
|
+
?? defaultWorkBuddyConfigPath();
|
|
12
|
+
const packageSpec = `${PACKAGE_NAME}@${options.packageVersion ?? CLI_VERSION}`;
|
|
13
|
+
const config = await readConfig(configPath);
|
|
14
|
+
const nextServer = {
|
|
15
|
+
type: "stdio",
|
|
16
|
+
command: "npx",
|
|
17
|
+
args: ["-y", packageSpec, "mcp", "serve"],
|
|
18
|
+
timeout: 60000
|
|
19
|
+
};
|
|
20
|
+
const previousServer = config.mcpServers?.["fargo-ai"];
|
|
21
|
+
const changed = JSON.stringify(previousServer) !== JSON.stringify(nextServer);
|
|
22
|
+
|
|
23
|
+
if (changed) {
|
|
24
|
+
config.mcpServers = { ...(config.mcpServers ?? {}), "fargo-ai": nextServer };
|
|
25
|
+
await writeConfig(configPath, config);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return {
|
|
29
|
+
type: "workbuddy_installation_complete",
|
|
30
|
+
installed: true,
|
|
31
|
+
changed,
|
|
32
|
+
config_path: configPath,
|
|
33
|
+
server_name: "fargo-ai",
|
|
34
|
+
package: packageSpec,
|
|
35
|
+
trust_required: true,
|
|
36
|
+
next_action: "Open WorkBuddy MCP management, trust and enable fargo-ai, then reload MCP or start a new task."
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function defaultWorkBuddyConfigPath(homeDirectory = homedir()) {
|
|
41
|
+
return join(homeDirectory, ".workbuddy-ai", "mcp.json");
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function readConfig(configPath) {
|
|
45
|
+
let text;
|
|
46
|
+
try {
|
|
47
|
+
text = await readFile(configPath, "utf8");
|
|
48
|
+
} catch (error) {
|
|
49
|
+
if (error?.code === "ENOENT") return {};
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
if (!text.trim()) return {};
|
|
53
|
+
let parsed;
|
|
54
|
+
try {
|
|
55
|
+
parsed = JSON.parse(text);
|
|
56
|
+
} catch {
|
|
57
|
+
throw new Error(`WorkBuddy MCP config is not valid JSON: ${configPath}`);
|
|
58
|
+
}
|
|
59
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
60
|
+
throw new Error(`WorkBuddy MCP config must contain a JSON object: ${configPath}`);
|
|
61
|
+
}
|
|
62
|
+
if (parsed.mcpServers !== undefined && (!parsed.mcpServers || typeof parsed.mcpServers !== "object" || Array.isArray(parsed.mcpServers))) {
|
|
63
|
+
throw new Error(`WorkBuddy mcpServers must be a JSON object: ${configPath}`);
|
|
64
|
+
}
|
|
65
|
+
return parsed;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function writeConfig(configPath, config) {
|
|
69
|
+
await mkdir(dirname(configPath), { recursive: true });
|
|
70
|
+
const temporaryPath = `${configPath}.${process.pid}.${Date.now()}.tmp`;
|
|
71
|
+
await writeFile(temporaryPath, `${JSON.stringify(config, null, 2)}\n`, { encoding: "utf8", mode: 0o600, flag: "wx" });
|
|
72
|
+
await rename(temporaryPath, configPath);
|
|
73
|
+
}
|