@spilno/herald-mcp 1.33.0 → 1.34.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 +13 -0
- package/dist/cli/config.d.ts +18 -0
- package/dist/cli/config.d.ts.map +1 -0
- package/dist/cli/config.js +150 -0
- package/dist/cli/config.js.map +1 -0
- package/dist/cli/login.d.ts +24 -0
- package/dist/cli/login.d.ts.map +1 -0
- package/dist/cli/login.js +175 -0
- package/dist/cli/login.js.map +1 -0
- package/dist/cli/logout.d.ts +14 -0
- package/dist/cli/logout.d.ts.map +1 -0
- package/dist/cli/logout.js +67 -0
- package/dist/cli/logout.js.map +1 -0
- package/dist/cli/upgrade.d.ts +15 -0
- package/dist/cli/upgrade.d.ts.map +1 -0
- package/dist/cli/upgrade.js +136 -0
- package/dist/cli/upgrade.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +2822 -0
- package/dist/cli.js.map +1 -0
- package/dist/command-extensions.spec.js +1 -1
- package/dist/command-extensions.spec.js.map +1 -1
- package/dist/index.js +46 -20
- package/dist/index.js.map +1 -1
- package/dist/sdk.d.ts +6 -0
- package/dist/sdk.d.ts.map +1 -0
- package/dist/sdk.js +23 -0
- package/dist/sdk.js.map +1 -0
- package/dist/session-tools.spec.js +1 -1
- package/dist/session-tools.spec.js.map +1 -1
- package/package.json +11 -6
- package/scripts/postinstall.js +21 -0
package/README.md
CHANGED
|
@@ -15,6 +15,19 @@ AI agents start fresh each session. Herald gives them memory:
|
|
|
15
15
|
| Generic responses | Context-aware predictions |
|
|
16
16
|
| No learning curve | Knowledge compounds |
|
|
17
17
|
|
|
18
|
+
## SDK Usage
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm i @spilno/herald-mcp
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
import { herald } from '@spilno/herald-mcp';
|
|
26
|
+
|
|
27
|
+
herald.learned('What worked');
|
|
28
|
+
herald.gotStuck('What failed');
|
|
29
|
+
```
|
|
30
|
+
|
|
18
31
|
## Quick Start
|
|
19
32
|
|
|
20
33
|
```bash
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Herald Config CLI
|
|
4
|
+
*
|
|
5
|
+
* Outputs MCP configuration JSON for any MCP-compatible client.
|
|
6
|
+
* Works with: Claude Code, Cursor, Windsurf, Cline, etc.
|
|
7
|
+
*
|
|
8
|
+
* Usage: npx @spilno/herald-mcp config [--client cursor]
|
|
9
|
+
*/
|
|
10
|
+
export interface ConfigOptions {
|
|
11
|
+
help?: boolean;
|
|
12
|
+
client?: string;
|
|
13
|
+
project?: string;
|
|
14
|
+
json?: boolean;
|
|
15
|
+
}
|
|
16
|
+
export declare function parseConfigArgs(args: string[]): ConfigOptions;
|
|
17
|
+
export declare function runConfig(args?: string[]): Promise<void>;
|
|
18
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/cli/config.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AAuBH,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,CAiB7D;AAwFD,wBAAsB,SAAS,CAAC,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CA4ClE"}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Herald Config CLI
|
|
4
|
+
*
|
|
5
|
+
* Outputs MCP configuration JSON for any MCP-compatible client.
|
|
6
|
+
* Works with: Claude Code, Cursor, Windsurf, Cline, etc.
|
|
7
|
+
*
|
|
8
|
+
* Usage: npx @spilno/herald-mcp config [--client cursor]
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, readFileSync } from "fs";
|
|
11
|
+
import { homedir } from "os";
|
|
12
|
+
import { join, basename } from "path";
|
|
13
|
+
const CONFIG_DIR = join(homedir(), ".herald");
|
|
14
|
+
const TOKEN_FILE = join(CONFIG_DIR, "token.json");
|
|
15
|
+
function getStoredAuth() {
|
|
16
|
+
if (!existsSync(TOKEN_FILE))
|
|
17
|
+
return null;
|
|
18
|
+
try {
|
|
19
|
+
return JSON.parse(readFileSync(TOKEN_FILE, "utf-8"));
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export function parseConfigArgs(args) {
|
|
26
|
+
const options = {};
|
|
27
|
+
for (let i = 0; i < args.length; i++) {
|
|
28
|
+
const arg = args[i];
|
|
29
|
+
if (arg === "--help" || arg === "-h") {
|
|
30
|
+
options.help = true;
|
|
31
|
+
}
|
|
32
|
+
else if (arg === "--client" || arg === "-c") {
|
|
33
|
+
options.client = args[++i];
|
|
34
|
+
}
|
|
35
|
+
else if (arg === "--project" || arg === "-p") {
|
|
36
|
+
options.project = args[++i];
|
|
37
|
+
}
|
|
38
|
+
else if (arg === "--json") {
|
|
39
|
+
options.json = true;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return options;
|
|
43
|
+
}
|
|
44
|
+
function printConfigHelp() {
|
|
45
|
+
console.log(`
|
|
46
|
+
Herald Config - Output MCP configuration for your AI coding assistant
|
|
47
|
+
|
|
48
|
+
Usage:
|
|
49
|
+
npx @spilno/herald-mcp config [options]
|
|
50
|
+
|
|
51
|
+
Options:
|
|
52
|
+
--client, -c Target client: claude, cursor, windsurf, generic (default: generic)
|
|
53
|
+
--project, -p Project name override (default: current folder)
|
|
54
|
+
--json Output raw JSON only (for piping)
|
|
55
|
+
--help, -h Show this help
|
|
56
|
+
|
|
57
|
+
Examples:
|
|
58
|
+
npx @spilno/herald-mcp config # Generic MCP config
|
|
59
|
+
npx @spilno/herald-mcp config --client cursor # For Cursor
|
|
60
|
+
npx @spilno/herald-mcp config --json | pbcopy # Copy JSON to clipboard
|
|
61
|
+
|
|
62
|
+
The config uses your logged-in identity. Run 'herald login' first.
|
|
63
|
+
`);
|
|
64
|
+
}
|
|
65
|
+
function buildConfig(auth, project) {
|
|
66
|
+
const env = {
|
|
67
|
+
CEDA_URL: "https://getceda.com",
|
|
68
|
+
};
|
|
69
|
+
// Add token if authenticated
|
|
70
|
+
if (auth?.token) {
|
|
71
|
+
env.CEDA_TOKEN = auth.token;
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
mcpServers: {
|
|
75
|
+
herald: {
|
|
76
|
+
command: "npx",
|
|
77
|
+
args: ["@spilno/herald-mcp@latest"],
|
|
78
|
+
env
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function getClientInstructions(client) {
|
|
84
|
+
switch (client.toLowerCase()) {
|
|
85
|
+
case "claude":
|
|
86
|
+
return `
|
|
87
|
+
Add to your Claude Code settings or .mcp.json:`;
|
|
88
|
+
case "cursor":
|
|
89
|
+
return `
|
|
90
|
+
Add to your Cursor MCP settings (Settings > MCP):`;
|
|
91
|
+
case "windsurf":
|
|
92
|
+
return `
|
|
93
|
+
Add to your Windsurf MCP configuration:`;
|
|
94
|
+
default:
|
|
95
|
+
return `
|
|
96
|
+
Add this to your MCP client configuration:`;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
function getClientConfigPath(client) {
|
|
100
|
+
switch (client.toLowerCase()) {
|
|
101
|
+
case "claude":
|
|
102
|
+
return "~/.claude.json or .mcp.json in your project";
|
|
103
|
+
case "cursor":
|
|
104
|
+
return "Settings > Features > MCP";
|
|
105
|
+
case "windsurf":
|
|
106
|
+
return "~/.windsurf/mcp.json";
|
|
107
|
+
default:
|
|
108
|
+
return "your MCP client's configuration file";
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
export async function runConfig(args = []) {
|
|
112
|
+
const options = parseConfigArgs(args);
|
|
113
|
+
if (options.help) {
|
|
114
|
+
printConfigHelp();
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const auth = getStoredAuth();
|
|
118
|
+
const project = options.project || basename(process.cwd());
|
|
119
|
+
const client = options.client || "generic";
|
|
120
|
+
const config = buildConfig(auth, project);
|
|
121
|
+
// Raw JSON output mode
|
|
122
|
+
if (options.json) {
|
|
123
|
+
console.log(JSON.stringify(config, null, 2));
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
// Pretty output with instructions
|
|
127
|
+
if (!auth) {
|
|
128
|
+
console.log(`
|
|
129
|
+
Note: Not logged in. Config will work but patterns won't persist to your account.
|
|
130
|
+
Run 'npx @spilno/herald-mcp login' to authenticate.
|
|
131
|
+
`);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
console.log(`
|
|
135
|
+
Logged in as: ${auth.user.login}
|
|
136
|
+
`);
|
|
137
|
+
}
|
|
138
|
+
console.log(getClientInstructions(client));
|
|
139
|
+
console.log();
|
|
140
|
+
console.log(JSON.stringify(config, null, 2));
|
|
141
|
+
console.log();
|
|
142
|
+
console.log(`Config location: ${getClientConfigPath(client)}`);
|
|
143
|
+
if (auth) {
|
|
144
|
+
console.log(`
|
|
145
|
+
Your patterns will sync to CEDA under your GitHub identity.
|
|
146
|
+
Herald auto-detects context from git when you're working in a repo.
|
|
147
|
+
`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/cli/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Herald Login CLI
|
|
4
|
+
*
|
|
5
|
+
* Authenticates user via GitHub OAuth.
|
|
6
|
+
* Opens browser → User authorizes → Token stored locally.
|
|
7
|
+
*
|
|
8
|
+
* Usage: npx @spilno/herald-mcp login
|
|
9
|
+
*/
|
|
10
|
+
export interface AuthConfig {
|
|
11
|
+
token: string;
|
|
12
|
+
expiresAt: string;
|
|
13
|
+
user: {
|
|
14
|
+
login: string;
|
|
15
|
+
email?: string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export interface LoginOptions {
|
|
19
|
+
help?: boolean;
|
|
20
|
+
force?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare function parseLoginArgs(args: string[]): LoginOptions;
|
|
23
|
+
export declare function runLogin(args?: string[]): Promise<void>;
|
|
24
|
+
//# sourceMappingURL=login.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/cli/login.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AAYH,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE;QACJ,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;KAChB,CAAC;CACH;AA0CD,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,YAAY,CAY3D;AAuBD,wBAAsB,QAAQ,CAAC,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAoGjE"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Herald Login CLI
|
|
4
|
+
*
|
|
5
|
+
* Authenticates user via GitHub OAuth.
|
|
6
|
+
* Opens browser → User authorizes → Token stored locally.
|
|
7
|
+
*
|
|
8
|
+
* Usage: npx @spilno/herald-mcp login
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync } from "fs";
|
|
11
|
+
import { homedir } from "os";
|
|
12
|
+
import { join } from "path";
|
|
13
|
+
import { createServer } from "http";
|
|
14
|
+
import { exec } from "child_process";
|
|
15
|
+
const CEDA_URL = process.env.CEDA_URL || "https://getceda.com";
|
|
16
|
+
const CONFIG_DIR = join(homedir(), ".herald");
|
|
17
|
+
const TOKEN_FILE = join(CONFIG_DIR, "token.json");
|
|
18
|
+
function getStoredAuth() {
|
|
19
|
+
if (!existsSync(TOKEN_FILE))
|
|
20
|
+
return null;
|
|
21
|
+
try {
|
|
22
|
+
const data = JSON.parse(readFileSync(TOKEN_FILE, "utf-8"));
|
|
23
|
+
// Check if expired
|
|
24
|
+
if (new Date(data.expiresAt) < new Date()) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
return data;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function storeAuth(auth) {
|
|
34
|
+
if (!existsSync(CONFIG_DIR)) {
|
|
35
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
36
|
+
}
|
|
37
|
+
writeFileSync(TOKEN_FILE, JSON.stringify(auth, null, 2), "utf-8");
|
|
38
|
+
}
|
|
39
|
+
function openBrowser(url) {
|
|
40
|
+
const platform = process.platform;
|
|
41
|
+
let cmd;
|
|
42
|
+
if (platform === "darwin") {
|
|
43
|
+
cmd = `open "${url}"`;
|
|
44
|
+
}
|
|
45
|
+
else if (platform === "win32") {
|
|
46
|
+
cmd = `start "${url}"`;
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
cmd = `xdg-open "${url}"`;
|
|
50
|
+
}
|
|
51
|
+
exec(cmd, (err) => {
|
|
52
|
+
if (err) {
|
|
53
|
+
console.log(`\nCould not open browser. Please visit:\n${url}\n`);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
export function parseLoginArgs(args) {
|
|
58
|
+
const options = {};
|
|
59
|
+
for (const arg of args) {
|
|
60
|
+
if (arg === "--help" || arg === "-h") {
|
|
61
|
+
options.help = true;
|
|
62
|
+
}
|
|
63
|
+
else if (arg === "--force" || arg === "-f") {
|
|
64
|
+
options.force = true;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return options;
|
|
68
|
+
}
|
|
69
|
+
function printLoginHelp() {
|
|
70
|
+
console.log(`
|
|
71
|
+
Herald Login - Authenticate with CEDA via GitHub
|
|
72
|
+
|
|
73
|
+
Usage:
|
|
74
|
+
npx @spilno/herald-mcp login [options]
|
|
75
|
+
|
|
76
|
+
Options:
|
|
77
|
+
--force, -f Re-authenticate even if already logged in
|
|
78
|
+
--help, -h Show this help
|
|
79
|
+
|
|
80
|
+
This opens your browser for GitHub OAuth. After authorization,
|
|
81
|
+
your token is stored in ~/.herald/token.json
|
|
82
|
+
|
|
83
|
+
Your GitHub identity becomes your CEDA identity:
|
|
84
|
+
- Your orgs = your pattern contexts
|
|
85
|
+
- Your repos = your pattern sources
|
|
86
|
+
- Git-verified trust = patterns propagate
|
|
87
|
+
`);
|
|
88
|
+
}
|
|
89
|
+
export async function runLogin(args = []) {
|
|
90
|
+
const options = parseLoginArgs(args);
|
|
91
|
+
if (options.help) {
|
|
92
|
+
printLoginHelp();
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
// Check if already logged in
|
|
96
|
+
const existingAuth = getStoredAuth();
|
|
97
|
+
if (existingAuth && !options.force) {
|
|
98
|
+
console.log(`
|
|
99
|
+
Already logged in as ${existingAuth.user.login}
|
|
100
|
+
|
|
101
|
+
To re-authenticate:
|
|
102
|
+
npx @spilno/herald-mcp login --force
|
|
103
|
+
|
|
104
|
+
To logout:
|
|
105
|
+
npx @spilno/herald-mcp logout
|
|
106
|
+
`);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
console.log("Starting GitHub OAuth flow...\n");
|
|
110
|
+
// Start local server to receive callback
|
|
111
|
+
const PORT = 9876;
|
|
112
|
+
const CALLBACK_PATH = "/callback";
|
|
113
|
+
const server = createServer(async (req, res) => {
|
|
114
|
+
const url = new URL(req.url || "", `http://localhost:${PORT}`);
|
|
115
|
+
if (url.pathname === CALLBACK_PATH) {
|
|
116
|
+
const token = url.searchParams.get("token");
|
|
117
|
+
const login = url.searchParams.get("login");
|
|
118
|
+
const email = url.searchParams.get("email");
|
|
119
|
+
const error = url.searchParams.get("error");
|
|
120
|
+
if (error) {
|
|
121
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
122
|
+
res.end(`
|
|
123
|
+
<html>
|
|
124
|
+
<body style="font-family: system-ui; padding: 2rem; text-align: center;">
|
|
125
|
+
<h1>Authentication Failed</h1>
|
|
126
|
+
<p>${error}</p>
|
|
127
|
+
<p>You can close this window.</p>
|
|
128
|
+
</body>
|
|
129
|
+
</html>
|
|
130
|
+
`);
|
|
131
|
+
server.close();
|
|
132
|
+
console.log(`\nAuthentication failed: ${error}`);
|
|
133
|
+
process.exit(1);
|
|
134
|
+
}
|
|
135
|
+
if (token && login) {
|
|
136
|
+
// Store the token
|
|
137
|
+
const auth = {
|
|
138
|
+
token,
|
|
139
|
+
expiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString(), // 30 days
|
|
140
|
+
user: { login, email: email || undefined }
|
|
141
|
+
};
|
|
142
|
+
storeAuth(auth);
|
|
143
|
+
res.writeHead(200, { "Content-Type": "text/html" });
|
|
144
|
+
res.end(`
|
|
145
|
+
<html>
|
|
146
|
+
<body style="font-family: system-ui; padding: 2rem; text-align: center;">
|
|
147
|
+
<h1>Logged in as ${login}</h1>
|
|
148
|
+
<p>You can close this window and return to the terminal.</p>
|
|
149
|
+
</body>
|
|
150
|
+
</html>
|
|
151
|
+
`);
|
|
152
|
+
server.close();
|
|
153
|
+
console.log(`\nLogged in as ${login}`);
|
|
154
|
+
console.log(`Token stored in ~/.herald/token.json`);
|
|
155
|
+
console.log(`\nNext: Run 'npx @spilno/herald-mcp config' to get your MCP configuration.`);
|
|
156
|
+
process.exit(0);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
res.writeHead(404);
|
|
160
|
+
res.end("Not found");
|
|
161
|
+
});
|
|
162
|
+
server.listen(PORT, () => {
|
|
163
|
+
const authUrl = `${CEDA_URL}/api/auth/github?cli_callback=http://localhost:${PORT}${CALLBACK_PATH}`;
|
|
164
|
+
console.log(`Opening browser for GitHub authorization...`);
|
|
165
|
+
console.log(`\nIf browser doesn't open, visit:\n${authUrl}\n`);
|
|
166
|
+
openBrowser(authUrl);
|
|
167
|
+
});
|
|
168
|
+
// Timeout after 5 minutes
|
|
169
|
+
setTimeout(() => {
|
|
170
|
+
console.log("\nTimeout waiting for authentication. Please try again.");
|
|
171
|
+
server.close();
|
|
172
|
+
process.exit(1);
|
|
173
|
+
}, 5 * 60 * 1000);
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/cli/login.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Herald Logout CLI
|
|
4
|
+
*
|
|
5
|
+
* Clears stored authentication token.
|
|
6
|
+
*
|
|
7
|
+
* Usage: npx @spilno/herald-mcp logout
|
|
8
|
+
*/
|
|
9
|
+
export interface LogoutOptions {
|
|
10
|
+
help?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare function parseLogoutArgs(args: string[]): LogoutOptions;
|
|
13
|
+
export declare function runLogout(args?: string[]): Promise<void>;
|
|
14
|
+
//# sourceMappingURL=logout.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/cli/logout.ts"],"names":[],"mappings":";AACA;;;;;;GAMG;AASH,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,CAU7D;AAiBD,wBAAsB,SAAS,CAAC,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAgClE"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Herald Logout CLI
|
|
4
|
+
*
|
|
5
|
+
* Clears stored authentication token.
|
|
6
|
+
*
|
|
7
|
+
* Usage: npx @spilno/herald-mcp logout
|
|
8
|
+
*/
|
|
9
|
+
import { existsSync, unlinkSync, readFileSync } from "fs";
|
|
10
|
+
import { homedir } from "os";
|
|
11
|
+
import { join } from "path";
|
|
12
|
+
const CONFIG_DIR = join(homedir(), ".herald");
|
|
13
|
+
const TOKEN_FILE = join(CONFIG_DIR, "token.json");
|
|
14
|
+
export function parseLogoutArgs(args) {
|
|
15
|
+
const options = {};
|
|
16
|
+
for (const arg of args) {
|
|
17
|
+
if (arg === "--help" || arg === "-h") {
|
|
18
|
+
options.help = true;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return options;
|
|
22
|
+
}
|
|
23
|
+
function printLogoutHelp() {
|
|
24
|
+
console.log(`
|
|
25
|
+
Herald Logout - Clear stored authentication
|
|
26
|
+
|
|
27
|
+
Usage:
|
|
28
|
+
npx @spilno/herald-mcp logout [options]
|
|
29
|
+
|
|
30
|
+
Options:
|
|
31
|
+
--help, -h Show this help
|
|
32
|
+
|
|
33
|
+
This removes ~/.herald/token.json
|
|
34
|
+
Herald will continue to work but patterns won't sync to your account.
|
|
35
|
+
`);
|
|
36
|
+
}
|
|
37
|
+
export async function runLogout(args = []) {
|
|
38
|
+
const options = parseLogoutArgs(args);
|
|
39
|
+
if (options.help) {
|
|
40
|
+
printLogoutHelp();
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
if (!existsSync(TOKEN_FILE)) {
|
|
44
|
+
console.log("Not logged in. Nothing to do.");
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
// Show who we're logging out
|
|
48
|
+
try {
|
|
49
|
+
const data = JSON.parse(readFileSync(TOKEN_FILE, "utf-8"));
|
|
50
|
+
const login = data.user?.login || "unknown";
|
|
51
|
+
unlinkSync(TOKEN_FILE);
|
|
52
|
+
console.log(`Logged out ${login}`);
|
|
53
|
+
console.log(`\nToken removed from ~/.herald/token.json`);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
unlinkSync(TOKEN_FILE);
|
|
57
|
+
console.log("Logged out. Token file removed.");
|
|
58
|
+
}
|
|
59
|
+
console.log(`
|
|
60
|
+
Herald will continue to work locally.
|
|
61
|
+
Patterns captured will use path-based context (low trust, no propagation).
|
|
62
|
+
|
|
63
|
+
To login again:
|
|
64
|
+
npx @spilno/herald-mcp login
|
|
65
|
+
`);
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=logout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/cli/logout.ts"],"names":[],"mappings":";AACA;;;;;;GAMG;AAEH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;AAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,EAAE,YAAY,CAAC,CAAC;AAMlD,MAAM,UAAU,eAAe,CAAC,IAAc;IAC5C,MAAM,OAAO,GAAkB,EAAE,CAAC;IAElC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,IAAI,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;YACrC,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,eAAe;IACtB,OAAO,CAAC,GAAG,CAAC;;;;;;;;;;;CAWb,CAAC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAiB,EAAE;IACjD,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAEtC,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,eAAe,EAAE,CAAC;QAClB,OAAO;IACT,CAAC;IAED,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC5B,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;QAC7C,OAAO;IACT,CAAC;IAED,6BAA6B;IAC7B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC;QAC3D,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,SAAS,CAAC;QAC5C,UAAU,CAAC,UAAU,CAAC,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,EAAE,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,UAAU,CAAC,UAAU,CAAC,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IACjD,CAAC;IAED,OAAO,CAAC,GAAG,CAAC;;;;;;CAMb,CAAC,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Herald Upgrade CLI
|
|
4
|
+
*
|
|
5
|
+
* Opens billing page to upgrade plan.
|
|
6
|
+
* Shows current usage stats first.
|
|
7
|
+
*
|
|
8
|
+
* Usage: npx @spilno/herald-mcp upgrade
|
|
9
|
+
*/
|
|
10
|
+
export interface UpgradeOptions {
|
|
11
|
+
help?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function parseUpgradeArgs(args: string[]): UpgradeOptions;
|
|
14
|
+
export declare function runUpgrade(args?: string[]): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=upgrade.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upgrade.d.ts","sourceRoot":"","sources":["../../src/cli/upgrade.ts"],"names":[],"mappings":";AACA;;;;;;;GAOG;AA4CH,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,cAAc,CAU/D;AAuDD,wBAAsB,UAAU,CAAC,IAAI,GAAE,MAAM,EAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAiDnE"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Herald Upgrade CLI
|
|
4
|
+
*
|
|
5
|
+
* Opens billing page to upgrade plan.
|
|
6
|
+
* Shows current usage stats first.
|
|
7
|
+
*
|
|
8
|
+
* Usage: npx @spilno/herald-mcp upgrade
|
|
9
|
+
*/
|
|
10
|
+
import { existsSync, readFileSync } from "fs";
|
|
11
|
+
import { homedir } from "os";
|
|
12
|
+
import { join } from "path";
|
|
13
|
+
import { exec } from "child_process";
|
|
14
|
+
const CEDA_URL = process.env.CEDA_URL || "https://getceda.com";
|
|
15
|
+
const CONFIG_DIR = join(homedir(), ".herald");
|
|
16
|
+
const TOKEN_FILE = join(CONFIG_DIR, "token.json");
|
|
17
|
+
function getStoredAuth() {
|
|
18
|
+
if (!existsSync(TOKEN_FILE))
|
|
19
|
+
return null;
|
|
20
|
+
try {
|
|
21
|
+
return JSON.parse(readFileSync(TOKEN_FILE, "utf-8"));
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
function openBrowser(url) {
|
|
28
|
+
const platform = process.platform;
|
|
29
|
+
let cmd;
|
|
30
|
+
if (platform === "darwin") {
|
|
31
|
+
cmd = `open "${url}"`;
|
|
32
|
+
}
|
|
33
|
+
else if (platform === "win32") {
|
|
34
|
+
cmd = `start "${url}"`;
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
cmd = `xdg-open "${url}"`;
|
|
38
|
+
}
|
|
39
|
+
exec(cmd, (err) => {
|
|
40
|
+
if (err) {
|
|
41
|
+
console.log(`\nCould not open browser. Please visit:\n${url}\n`);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
export function parseUpgradeArgs(args) {
|
|
46
|
+
const options = {};
|
|
47
|
+
for (const arg of args) {
|
|
48
|
+
if (arg === "--help" || arg === "-h") {
|
|
49
|
+
options.help = true;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return options;
|
|
53
|
+
}
|
|
54
|
+
function printUpgradeHelp() {
|
|
55
|
+
console.log(`
|
|
56
|
+
Herald Upgrade - Manage your CEDA subscription
|
|
57
|
+
|
|
58
|
+
Usage:
|
|
59
|
+
npx @spilno/herald-mcp upgrade [options]
|
|
60
|
+
|
|
61
|
+
Options:
|
|
62
|
+
--help, -h Show this help
|
|
63
|
+
|
|
64
|
+
Plans:
|
|
65
|
+
Free $0/mo 1 project, 100 patterns, 1K queries/mo
|
|
66
|
+
Pro $9/mo Unlimited projects, 10K patterns, unlimited queries
|
|
67
|
+
Team $29/seat/mo Org sharing, cross-project propagation
|
|
68
|
+
|
|
69
|
+
This opens the CEDA billing portal in your browser.
|
|
70
|
+
`);
|
|
71
|
+
}
|
|
72
|
+
async function fetchUsage(auth) {
|
|
73
|
+
try {
|
|
74
|
+
const response = await fetch(`${CEDA_URL}/api/usage`, {
|
|
75
|
+
headers: {
|
|
76
|
+
Authorization: `Bearer ${auth.token}`,
|
|
77
|
+
},
|
|
78
|
+
});
|
|
79
|
+
if (!response.ok)
|
|
80
|
+
return null;
|
|
81
|
+
return await response.json();
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function formatUsage(used, limit) {
|
|
88
|
+
const percentage = limit > 0 ? Math.round((used / limit) * 100) : 0;
|
|
89
|
+
const bar = "=".repeat(Math.min(20, Math.round(percentage / 5))) + " ".repeat(20 - Math.round(percentage / 5));
|
|
90
|
+
if (limit === -1) {
|
|
91
|
+
return `${used} (unlimited)`;
|
|
92
|
+
}
|
|
93
|
+
const warning = percentage >= 80 ? " !" : "";
|
|
94
|
+
return `${used}/${limit} [${bar}] ${percentage}%${warning}`;
|
|
95
|
+
}
|
|
96
|
+
export async function runUpgrade(args = []) {
|
|
97
|
+
const options = parseUpgradeArgs(args);
|
|
98
|
+
if (options.help) {
|
|
99
|
+
printUpgradeHelp();
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
const auth = getStoredAuth();
|
|
103
|
+
if (!auth) {
|
|
104
|
+
console.log(`
|
|
105
|
+
Not logged in. Login first to manage your subscription:
|
|
106
|
+
|
|
107
|
+
npx @spilno/herald-mcp login
|
|
108
|
+
npx @spilno/herald-mcp upgrade
|
|
109
|
+
`);
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
console.log(`Fetching usage for ${auth.user.login}...\n`);
|
|
113
|
+
const usage = await fetchUsage(auth);
|
|
114
|
+
if (usage) {
|
|
115
|
+
console.log(`Current Plan: ${usage.plan.toUpperCase()}`);
|
|
116
|
+
console.log();
|
|
117
|
+
console.log(`Patterns: ${formatUsage(usage.patterns.used, usage.patterns.limit)}`);
|
|
118
|
+
console.log(`Queries: ${formatUsage(usage.queries.used, usage.queries.limit)}`);
|
|
119
|
+
console.log(`Projects: ${formatUsage(usage.projects.used, usage.projects.limit)}`);
|
|
120
|
+
console.log();
|
|
121
|
+
// Check if near limits
|
|
122
|
+
const patternsPercent = usage.patterns.limit > 0 ? (usage.patterns.used / usage.patterns.limit) * 100 : 0;
|
|
123
|
+
const queriesPercent = usage.queries.limit > 0 ? (usage.queries.used / usage.queries.limit) * 100 : 0;
|
|
124
|
+
if (patternsPercent >= 80 || queriesPercent >= 80) {
|
|
125
|
+
console.log("You're approaching your plan limits. Consider upgrading.\n");
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
console.log("Could not fetch usage stats.\n");
|
|
130
|
+
}
|
|
131
|
+
const billingUrl = `${CEDA_URL}/billing?user=${auth.user.login}`;
|
|
132
|
+
console.log("Opening billing portal...\n");
|
|
133
|
+
openBrowser(billingUrl);
|
|
134
|
+
console.log(`If browser doesn't open, visit:\n${billingUrl}`);
|
|
135
|
+
}
|
|
136
|
+
//# sourceMappingURL=upgrade.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"upgrade.js","sourceRoot":"","sources":["../../src/cli/upgrade.ts"],"names":[],"mappings":"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"}
|
package/dist/cli.d.ts
ADDED