@cg3/equip 0.2.22 → 0.4.0
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/LICENSE +1 -1
- package/README.md +26 -10
- package/bin/equip.js +159 -68
- package/demo/README.md +1 -1
- package/dist/index.d.ts +74 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +175 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/cli.d.ts +22 -0
- package/dist/lib/cli.d.ts.map +1 -0
- package/dist/lib/cli.js +148 -0
- package/dist/lib/cli.js.map +1 -0
- package/dist/lib/commands/doctor.d.ts +2 -0
- package/dist/lib/commands/doctor.d.ts.map +1 -0
- package/dist/lib/commands/doctor.js +162 -0
- package/dist/lib/commands/doctor.js.map +1 -0
- package/dist/lib/commands/status.d.ts +2 -0
- package/dist/lib/commands/status.d.ts.map +1 -0
- package/dist/lib/commands/status.js +134 -0
- package/dist/lib/commands/status.js.map +1 -0
- package/dist/lib/commands/update.d.ts +2 -0
- package/dist/lib/commands/update.d.ts.map +1 -0
- package/dist/lib/commands/update.js +93 -0
- package/dist/lib/commands/update.js.map +1 -0
- package/dist/lib/detect.d.ts +12 -0
- package/dist/lib/detect.d.ts.map +1 -0
- package/dist/lib/detect.js +109 -0
- package/dist/lib/detect.js.map +1 -0
- package/dist/lib/hooks.d.ts +40 -0
- package/dist/lib/hooks.d.ts.map +1 -0
- package/dist/lib/hooks.js +226 -0
- package/dist/lib/hooks.js.map +1 -0
- package/dist/lib/mcp.d.ts +73 -0
- package/dist/lib/mcp.d.ts.map +1 -0
- package/dist/lib/mcp.js +418 -0
- package/dist/lib/mcp.js.map +1 -0
- package/dist/lib/platforms.d.ts +67 -0
- package/dist/lib/platforms.d.ts.map +1 -0
- package/dist/lib/platforms.js +353 -0
- package/dist/lib/platforms.js.map +1 -0
- package/dist/lib/rules.d.ts +35 -0
- package/dist/lib/rules.d.ts.map +1 -0
- package/dist/lib/rules.js +161 -0
- package/dist/lib/rules.js.map +1 -0
- package/dist/lib/state.d.ts +33 -0
- package/dist/lib/state.d.ts.map +1 -0
- package/dist/lib/state.js +130 -0
- package/dist/lib/state.js.map +1 -0
- package/package.json +19 -13
- package/registry.json +9 -0
- package/index.js +0 -244
- package/lib/cli.js +0 -99
- package/lib/detect.js +0 -242
- package/lib/hooks.js +0 -238
- package/lib/mcp.js +0 -503
- package/lib/platforms.js +0 -184
- package/lib/rules.js +0 -170
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// State management — tracks what equip has installed across platforms.
|
|
3
|
+
// State file: ~/.equip/state.json
|
|
4
|
+
// Zero dependencies.
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.getEquipDir = getEquipDir;
|
|
40
|
+
exports.getStatePath = getStatePath;
|
|
41
|
+
exports.readState = readState;
|
|
42
|
+
exports.writeState = writeState;
|
|
43
|
+
exports.trackInstall = trackInstall;
|
|
44
|
+
exports.trackUninstall = trackUninstall;
|
|
45
|
+
exports.markUpdated = markUpdated;
|
|
46
|
+
const fs = __importStar(require("fs"));
|
|
47
|
+
const path = __importStar(require("path"));
|
|
48
|
+
const os = __importStar(require("os"));
|
|
49
|
+
// ─── Paths ──────────────────────────────────────────────────
|
|
50
|
+
const EQUIP_DIR = path.join(os.homedir(), ".equip");
|
|
51
|
+
const STATE_PATH = path.join(EQUIP_DIR, "state.json");
|
|
52
|
+
function getEquipDir() { return EQUIP_DIR; }
|
|
53
|
+
function getStatePath() { return STATE_PATH; }
|
|
54
|
+
// ─── Read / Write ───────────────────────────────────────────
|
|
55
|
+
function readState() {
|
|
56
|
+
try {
|
|
57
|
+
const raw = fs.readFileSync(STATE_PATH, "utf-8");
|
|
58
|
+
return JSON.parse(raw);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return {
|
|
62
|
+
equipVersion: "",
|
|
63
|
+
lastUpdated: "",
|
|
64
|
+
tools: {},
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
function writeState(state) {
|
|
69
|
+
fs.mkdirSync(EQUIP_DIR, { recursive: true });
|
|
70
|
+
const tmp = STATE_PATH + ".tmp";
|
|
71
|
+
fs.writeFileSync(tmp, JSON.stringify(state, null, 2) + "\n");
|
|
72
|
+
fs.renameSync(tmp, STATE_PATH);
|
|
73
|
+
}
|
|
74
|
+
// ─── Tool Tracking ──────────────────────────────────────────
|
|
75
|
+
/**
|
|
76
|
+
* Record that a tool was installed on a platform.
|
|
77
|
+
*/
|
|
78
|
+
function trackInstall(toolName, pkg, platformId, record) {
|
|
79
|
+
const state = readState();
|
|
80
|
+
const version = getEquipVersion();
|
|
81
|
+
if (!state.tools[toolName]) {
|
|
82
|
+
state.tools[toolName] = {
|
|
83
|
+
package: pkg,
|
|
84
|
+
installedAt: new Date().toISOString(),
|
|
85
|
+
platforms: {},
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
state.tools[toolName].platforms[platformId] = record;
|
|
89
|
+
state.tools[toolName].updatedAt = new Date().toISOString();
|
|
90
|
+
state.equipVersion = version;
|
|
91
|
+
writeState(state);
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Remove a tool's platform record from state.
|
|
95
|
+
*/
|
|
96
|
+
function trackUninstall(toolName, platformId) {
|
|
97
|
+
const state = readState();
|
|
98
|
+
if (!state.tools[toolName])
|
|
99
|
+
return;
|
|
100
|
+
if (platformId) {
|
|
101
|
+
delete state.tools[toolName].platforms[platformId];
|
|
102
|
+
if (Object.keys(state.tools[toolName].platforms).length === 0) {
|
|
103
|
+
delete state.tools[toolName];
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
delete state.tools[toolName];
|
|
108
|
+
}
|
|
109
|
+
writeState(state);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Mark equip as freshly updated.
|
|
113
|
+
*/
|
|
114
|
+
function markUpdated() {
|
|
115
|
+
const state = readState();
|
|
116
|
+
state.equipVersion = getEquipVersion();
|
|
117
|
+
state.lastUpdated = new Date().toISOString();
|
|
118
|
+
writeState(state);
|
|
119
|
+
}
|
|
120
|
+
// ─── Helpers ────────────────────────────────────────────────
|
|
121
|
+
function getEquipVersion() {
|
|
122
|
+
try {
|
|
123
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, "..", "..", "package.json"), "utf-8"));
|
|
124
|
+
return pkg.version;
|
|
125
|
+
}
|
|
126
|
+
catch {
|
|
127
|
+
return "unknown";
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.js","sourceRoot":"","sources":["../../src/lib/state.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cg3/equip",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Universal MCP + behavioral rules installer for AI coding agents",
|
|
5
|
-
"main": "index.js",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
6
7
|
"bin": {
|
|
7
8
|
"equip": "bin/equip.js"
|
|
8
9
|
},
|
|
9
10
|
"exports": {
|
|
10
|
-
".": "./index.js",
|
|
11
|
-
"./
|
|
12
|
-
"./mcp": "./lib/mcp.js",
|
|
13
|
-
"./rules": "./lib/rules.js",
|
|
14
|
-
"./platforms": "./lib/platforms.js",
|
|
15
|
-
"./cli": "./lib/cli.js",
|
|
11
|
+
".": { "types": "./dist/index.d.ts", "require": "./dist/index.js" },
|
|
12
|
+
"./dist/*": "./dist/*",
|
|
16
13
|
"./package.json": "./package.json"
|
|
17
14
|
},
|
|
18
15
|
"files": [
|
|
19
|
-
"
|
|
16
|
+
"dist/",
|
|
20
17
|
"bin/",
|
|
21
|
-
"
|
|
22
|
-
"
|
|
18
|
+
"demo/",
|
|
19
|
+
"registry.json"
|
|
23
20
|
],
|
|
21
|
+
"scripts": {
|
|
22
|
+
"build": "tsc",
|
|
23
|
+
"test": "tsc && node --test test/equip.test.js",
|
|
24
|
+
"prepublishOnly": "npm run build"
|
|
25
|
+
},
|
|
24
26
|
"keywords": [
|
|
25
27
|
"mcp",
|
|
26
28
|
"ai",
|
|
@@ -35,13 +37,17 @@
|
|
|
35
37
|
"codex",
|
|
36
38
|
"gemini"
|
|
37
39
|
],
|
|
38
|
-
"author": "
|
|
40
|
+
"author": "Charles Mulic",
|
|
39
41
|
"license": "MIT",
|
|
40
42
|
"repository": {
|
|
41
43
|
"type": "git",
|
|
42
|
-
"url": "https://github.com/
|
|
44
|
+
"url": "https://github.com/CharlesMulic/equip"
|
|
43
45
|
},
|
|
44
46
|
"engines": {
|
|
45
47
|
"node": ">=18"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/node": "^25.5.0",
|
|
51
|
+
"typescript": "^6.0.2"
|
|
46
52
|
}
|
|
47
53
|
}
|
package/registry.json
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$comment": "Tool registry for npx @cg3/equip <shorthand>. Submit a PR to add your tool.",
|
|
4
|
+
"prior": {
|
|
5
|
+
"package": "@cg3/prior-node",
|
|
6
|
+
"command": "setup",
|
|
7
|
+
"description": "Prior — agent-centric shared knowledge base"
|
|
8
|
+
}
|
|
9
|
+
}
|
package/index.js
DELETED
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
// @cg3/equip — Universal MCP + behavioral rules installer for AI coding agents.
|
|
2
|
-
// Zero dependencies. Works with Claude Code, Cursor, Windsurf, VS Code, Cline, Roo Code, Codex, Gemini CLI.
|
|
3
|
-
|
|
4
|
-
"use strict";
|
|
5
|
-
|
|
6
|
-
const path = require("path");
|
|
7
|
-
const os = require("os");
|
|
8
|
-
|
|
9
|
-
const { detectPlatforms, whichSync, dirExists, fileExists } = require("./lib/detect");
|
|
10
|
-
const { readMcpEntry, buildHttpConfig, buildHttpConfigWithAuth, buildStdioConfig, installMcp, installMcpJson, installMcpToml, uninstallMcp, updateMcpKey, parseTomlServerEntry, parseTomlSubTables, buildTomlEntry, removeTomlEntry } = require("./lib/mcp");
|
|
11
|
-
const { parseRulesVersion, installRules, uninstallRules, markerPatterns } = require("./lib/rules");
|
|
12
|
-
const { getHookCapabilities, installHooks, uninstallHooks, hasHooks, buildHooksConfig } = require("./lib/hooks");
|
|
13
|
-
const { createManualPlatform, platformName, KNOWN_PLATFORMS } = require("./lib/platforms");
|
|
14
|
-
const cli = require("./lib/cli");
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
* Equip — configure AI coding tools with your MCP server and behavioral rules.
|
|
18
|
-
*
|
|
19
|
-
* @example
|
|
20
|
-
* const equip = new Equip({
|
|
21
|
-
* name: "prior",
|
|
22
|
-
* serverUrl: "https://api.cg3.io/mcp",
|
|
23
|
-
* rules: { content: "...", version: "0.5.3", marker: "prior" },
|
|
24
|
-
* });
|
|
25
|
-
* const platforms = equip.detect();
|
|
26
|
-
* await equip.install(platforms, { apiKey: "ask_xxx" });
|
|
27
|
-
*/
|
|
28
|
-
class Equip {
|
|
29
|
-
/**
|
|
30
|
-
* @param {object} config
|
|
31
|
-
* @param {string} config.name - Server name in MCP configs (e.g., "prior")
|
|
32
|
-
* @param {string} config.serverUrl - Remote MCP server URL
|
|
33
|
-
* @param {object} [config.rules] - Behavioral rules config
|
|
34
|
-
* @param {string} config.rules.content - Rules markdown content (with markers)
|
|
35
|
-
* @param {string} config.rules.version - Version string for marker tracking
|
|
36
|
-
* @param {string} config.rules.marker - Marker name (e.g., "prior")
|
|
37
|
-
* @param {string} [config.rules.fileName] - Standalone file name for file-based platforms (e.g., "prior.md")
|
|
38
|
-
* @param {string[]} [config.rules.clipboardPlatforms] - Platforms using clipboard (default: ["cursor", "vscode"])
|
|
39
|
-
* @param {object} [config.stdio] - Stdio transport config (alternative to HTTP)
|
|
40
|
-
* @param {string} config.stdio.command - Command to run
|
|
41
|
-
* @param {string[]} config.stdio.args - Command arguments
|
|
42
|
-
* @param {string} config.stdio.envKey - Env var name for API key
|
|
43
|
-
* @param {Array} [config.hooks] - Lifecycle hook definitions
|
|
44
|
-
* @param {string} config.hooks[].event - Hook event name (e.g., "PostToolUseFailure")
|
|
45
|
-
* @param {string} [config.hooks[].matcher] - Regex matcher for event filtering (e.g., "Bash")
|
|
46
|
-
* @param {string} config.hooks[].script - Hook script content (Node.js)
|
|
47
|
-
* @param {string} config.hooks[].name - Script filename (without .js extension)
|
|
48
|
-
* @param {string} [config.hookDir] - Directory for hook scripts (default: ~/.${name}/hooks)
|
|
49
|
-
*/
|
|
50
|
-
constructor(config) {
|
|
51
|
-
if (!config.name) throw new Error("Equip: name is required");
|
|
52
|
-
if (!config.serverUrl && !config.stdio) throw new Error("Equip: serverUrl or stdio is required");
|
|
53
|
-
|
|
54
|
-
this.name = config.name;
|
|
55
|
-
this.serverUrl = config.serverUrl;
|
|
56
|
-
this.rules = config.rules || null;
|
|
57
|
-
this.stdio = config.stdio || null;
|
|
58
|
-
this.hookDefs = config.hooks || null;
|
|
59
|
-
this.hookDir = config.hookDir || path.join(os.homedir(), `.${config.name}`, "hooks");
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Detect installed AI coding platforms.
|
|
64
|
-
* @returns {Array<object>} Platform objects
|
|
65
|
-
*/
|
|
66
|
-
detect() {
|
|
67
|
-
return detectPlatforms(this.name);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Build MCP config for a platform.
|
|
72
|
-
* @param {string} platformId - Platform id
|
|
73
|
-
* @param {string} apiKey - API key
|
|
74
|
-
* @param {string} [transport="http"] - "http" or "stdio"
|
|
75
|
-
* @returns {object} MCP config object
|
|
76
|
-
*/
|
|
77
|
-
buildConfig(platformId, apiKey, transport = "http") {
|
|
78
|
-
if (transport === "stdio" && this.stdio) {
|
|
79
|
-
const env = { [this.stdio.envKey]: apiKey };
|
|
80
|
-
return buildStdioConfig(this.stdio.command, this.stdio.args, env);
|
|
81
|
-
}
|
|
82
|
-
return buildHttpConfigWithAuth(this.serverUrl, apiKey, platformId);
|
|
83
|
-
}
|
|
84
|
-
|
|
85
|
-
/**
|
|
86
|
-
* Install MCP config on a platform.
|
|
87
|
-
* @param {object} platform - Platform object from detect()
|
|
88
|
-
* @param {string} apiKey - API key
|
|
89
|
-
* @param {object} [options] - { transport, dryRun }
|
|
90
|
-
* @returns {{ success: boolean, method: string }}
|
|
91
|
-
*/
|
|
92
|
-
installMcp(platform, apiKey, options = {}) {
|
|
93
|
-
const { transport = "http", dryRun = false } = options;
|
|
94
|
-
const config = this.buildConfig(platform.platform, apiKey, transport);
|
|
95
|
-
return installMcp(platform, this.name, config, { dryRun, serverUrl: this.serverUrl });
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
/**
|
|
99
|
-
* Uninstall MCP config from a platform.
|
|
100
|
-
* @param {object} platform - Platform object
|
|
101
|
-
* @param {boolean} [dryRun=false]
|
|
102
|
-
* @returns {boolean}
|
|
103
|
-
*/
|
|
104
|
-
uninstallMcp(platform, dryRun = false) {
|
|
105
|
-
return uninstallMcp(platform, this.name, dryRun);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
/**
|
|
109
|
-
* Update API key in MCP config.
|
|
110
|
-
* @param {object} platform - Platform object
|
|
111
|
-
* @param {string} apiKey - New API key
|
|
112
|
-
* @param {string} [transport="http"]
|
|
113
|
-
* @returns {{ success: boolean, method: string }}
|
|
114
|
-
*/
|
|
115
|
-
updateMcpKey(platform, apiKey, transport = "http") {
|
|
116
|
-
const config = this.buildConfig(platform.platform, apiKey, transport);
|
|
117
|
-
return updateMcpKey(platform, this.name, config);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
/**
|
|
121
|
-
* Install behavioral rules on a platform.
|
|
122
|
-
* @param {object} platform - Platform object
|
|
123
|
-
* @param {object} [options] - { dryRun }
|
|
124
|
-
* @returns {{ action: string }}
|
|
125
|
-
*/
|
|
126
|
-
installRules(platform, options = {}) {
|
|
127
|
-
if (!this.rules) return { action: "skipped" };
|
|
128
|
-
return installRules(platform, {
|
|
129
|
-
content: this.rules.content,
|
|
130
|
-
version: this.rules.version,
|
|
131
|
-
marker: this.rules.marker,
|
|
132
|
-
fileName: this.rules.fileName,
|
|
133
|
-
clipboardPlatforms: this.rules.clipboardPlatforms,
|
|
134
|
-
dryRun: options.dryRun || false,
|
|
135
|
-
copyToClipboard: cli.copyToClipboard,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
/**
|
|
140
|
-
* Uninstall behavioral rules from a platform.
|
|
141
|
-
* @param {object} platform - Platform object
|
|
142
|
-
* @param {boolean} [dryRun=false]
|
|
143
|
-
* @returns {boolean}
|
|
144
|
-
*/
|
|
145
|
-
uninstallRules(platform, dryRun = false) {
|
|
146
|
-
if (!this.rules) return false;
|
|
147
|
-
return uninstallRules(platform, {
|
|
148
|
-
marker: this.rules.marker,
|
|
149
|
-
fileName: this.rules.fileName,
|
|
150
|
-
dryRun,
|
|
151
|
-
});
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Check if MCP is configured on a platform.
|
|
156
|
-
* @param {object} platform - Platform object
|
|
157
|
-
* @returns {object|null} Existing MCP config or null
|
|
158
|
-
*/
|
|
159
|
-
readMcp(platform) {
|
|
160
|
-
return readMcpEntry(platform.configPath, platform.rootKey, this.name, platform.configFormat || "json");
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
/**
|
|
164
|
-
* Install lifecycle hooks on a platform (if supported).
|
|
165
|
-
* Uses hook definitions from constructor config.
|
|
166
|
-
* @param {object} platform - Platform object from detect()
|
|
167
|
-
* @param {object} [options] - { hookDir, dryRun }
|
|
168
|
-
* @returns {{ installed: boolean, scripts: string[], hookDir: string } | null}
|
|
169
|
-
*/
|
|
170
|
-
installHooks(platform, options = {}) {
|
|
171
|
-
if (!this.hookDefs) return null;
|
|
172
|
-
const opts = { ...options };
|
|
173
|
-
if (this.hookDir && !opts.hookDir) opts.hookDir = this.hookDir;
|
|
174
|
-
return installHooks(platform, this.hookDefs, opts);
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
/**
|
|
178
|
-
* Uninstall hooks from a platform.
|
|
179
|
-
* @param {object} platform - Platform object
|
|
180
|
-
* @param {object} [options] - { hookDir, dryRun }
|
|
181
|
-
* @returns {boolean}
|
|
182
|
-
*/
|
|
183
|
-
uninstallHooks(platform, options = {}) {
|
|
184
|
-
if (!this.hookDefs) return false;
|
|
185
|
-
const opts = { ...options };
|
|
186
|
-
if (this.hookDir && !opts.hookDir) opts.hookDir = this.hookDir;
|
|
187
|
-
return uninstallHooks(platform, this.hookDefs, opts);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* Check if hooks are installed on a platform.
|
|
192
|
-
* @param {object} platform - Platform object
|
|
193
|
-
* @param {object} [options] - { hookDir }
|
|
194
|
-
* @returns {boolean}
|
|
195
|
-
*/
|
|
196
|
-
hasHooks(platform, options = {}) {
|
|
197
|
-
if (!this.hookDefs) return false;
|
|
198
|
-
const opts = { ...options };
|
|
199
|
-
if (this.hookDir && !opts.hookDir) opts.hookDir = this.hookDir;
|
|
200
|
-
return hasHooks(platform, this.hookDefs, opts);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
/**
|
|
204
|
-
* Check if a platform supports hooks and this instance has hook definitions.
|
|
205
|
-
* @param {object} platform - Platform object
|
|
206
|
-
* @returns {boolean}
|
|
207
|
-
*/
|
|
208
|
-
supportsHooks(platform) {
|
|
209
|
-
return !!this.hookDefs && this.hookDefs.length > 0 && !!getHookCapabilities(platform.platform);
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
module.exports = {
|
|
214
|
-
Equip,
|
|
215
|
-
// Re-export primitives for advanced usage
|
|
216
|
-
detectPlatforms,
|
|
217
|
-
readMcpEntry,
|
|
218
|
-
buildHttpConfig,
|
|
219
|
-
buildHttpConfigWithAuth,
|
|
220
|
-
buildStdioConfig,
|
|
221
|
-
installMcp,
|
|
222
|
-
installMcpJson,
|
|
223
|
-
installMcpToml,
|
|
224
|
-
uninstallMcp,
|
|
225
|
-
updateMcpKey,
|
|
226
|
-
parseTomlServerEntry,
|
|
227
|
-
parseTomlSubTables,
|
|
228
|
-
buildTomlEntry,
|
|
229
|
-
removeTomlEntry,
|
|
230
|
-
installRules,
|
|
231
|
-
uninstallRules,
|
|
232
|
-
parseRulesVersion,
|
|
233
|
-
markerPatterns,
|
|
234
|
-
createManualPlatform,
|
|
235
|
-
platformName,
|
|
236
|
-
KNOWN_PLATFORMS,
|
|
237
|
-
// Hooks
|
|
238
|
-
getHookCapabilities,
|
|
239
|
-
installHooks,
|
|
240
|
-
uninstallHooks,
|
|
241
|
-
hasHooks,
|
|
242
|
-
buildHooksConfig,
|
|
243
|
-
cli,
|
|
244
|
-
};
|
package/lib/cli.js
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
// CLI output helpers, prompts, and clipboard.
|
|
2
|
-
// Zero dependencies.
|
|
3
|
-
|
|
4
|
-
"use strict";
|
|
5
|
-
|
|
6
|
-
const os = require("os");
|
|
7
|
-
const readline = require("readline");
|
|
8
|
-
|
|
9
|
-
// ─── Colors ──────────────────────────────────────────────────
|
|
10
|
-
|
|
11
|
-
const GREEN = "\x1b[32m";
|
|
12
|
-
const RED = "\x1b[31m";
|
|
13
|
-
const YELLOW = "\x1b[33m";
|
|
14
|
-
const CYAN = "\x1b[36m";
|
|
15
|
-
const BOLD = "\x1b[1m";
|
|
16
|
-
const DIM = "\x1b[2m";
|
|
17
|
-
const RESET = "\x1b[0m";
|
|
18
|
-
|
|
19
|
-
// ─── Output ──────────────────────────────────────────────────
|
|
20
|
-
|
|
21
|
-
function log(msg = "") { process.stderr.write(msg + "\n"); }
|
|
22
|
-
function ok(msg) { log(` ${GREEN}✓${RESET} ${msg}`); }
|
|
23
|
-
function fail(msg) { log(` ${RED}✗${RESET} ${msg}`); }
|
|
24
|
-
function warn(msg) { log(` ${YELLOW}⚠${RESET} ${msg}`); }
|
|
25
|
-
function info(msg) { log(` ${CYAN}ⓘ${RESET} ${msg}`); }
|
|
26
|
-
function step(n, total, title) { log(`\n${BOLD}[${n}/${total}] ${title}${RESET}`); }
|
|
27
|
-
|
|
28
|
-
// ─── Prompts ─────────────────────────────────────────────────
|
|
29
|
-
|
|
30
|
-
function prompt(question) {
|
|
31
|
-
return new Promise((resolve) => {
|
|
32
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
33
|
-
rl.question(question, (answer) => { rl.close(); resolve(answer.trim()); });
|
|
34
|
-
});
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Prompt that resolves on Enter (true) or Esc (false).
|
|
39
|
-
* Falls back to readline if stdin isn't a TTY.
|
|
40
|
-
*/
|
|
41
|
-
function promptEnterOrEsc(question) {
|
|
42
|
-
return new Promise((resolve) => {
|
|
43
|
-
process.stderr.write(question);
|
|
44
|
-
if (!process.stdin.isTTY) {
|
|
45
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
46
|
-
rl.question("", (answer) => { rl.close(); resolve(answer.toLowerCase() !== "n"); });
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
process.stdin.setRawMode(true);
|
|
50
|
-
process.stdin.resume();
|
|
51
|
-
process.stdin.setEncoding("utf-8");
|
|
52
|
-
const onData = (key) => {
|
|
53
|
-
if (key === "\x1b") {
|
|
54
|
-
process.stdin.setRawMode(false); process.stdin.pause(); process.stdin.removeListener("data", onData);
|
|
55
|
-
process.stderr.write("\n"); resolve(false);
|
|
56
|
-
} else if (key === "\r" || key === "\n") {
|
|
57
|
-
process.stdin.setRawMode(false); process.stdin.pause(); process.stdin.removeListener("data", onData);
|
|
58
|
-
process.stderr.write("\n"); resolve(true);
|
|
59
|
-
} else if (key === "\x03") {
|
|
60
|
-
process.stdin.setRawMode(false); process.stdin.pause(); process.stdin.removeListener("data", onData);
|
|
61
|
-
process.stderr.write("\n"); process.exit(0);
|
|
62
|
-
}
|
|
63
|
-
// else: ignore unrecognized keys, keep listening
|
|
64
|
-
};
|
|
65
|
-
process.stdin.on("data", onData);
|
|
66
|
-
});
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// ─── Clipboard ───────────────────────────────────────────────
|
|
70
|
-
|
|
71
|
-
function copyToClipboard(text) {
|
|
72
|
-
try {
|
|
73
|
-
const cp = require("child_process");
|
|
74
|
-
if (process.platform === "darwin") {
|
|
75
|
-
cp.execSync("pbcopy", { input: text, timeout: 3000 });
|
|
76
|
-
} else if (process.platform === "win32") {
|
|
77
|
-
cp.execSync("clip", { input: text, timeout: 3000 });
|
|
78
|
-
} else {
|
|
79
|
-
try { cp.execSync("xclip -selection clipboard", { input: text, timeout: 3000 }); }
|
|
80
|
-
catch { try { cp.execSync("xsel --clipboard --input", { input: text, timeout: 3000 }); }
|
|
81
|
-
catch { cp.execSync("wl-copy", { input: text, timeout: 3000 }); } }
|
|
82
|
-
}
|
|
83
|
-
return true;
|
|
84
|
-
} catch { return false; }
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// ─── Utilities ───────────────────────────────────────────────
|
|
88
|
-
|
|
89
|
-
function sanitizeError(msg) {
|
|
90
|
-
return msg.replace(os.homedir(), "~");
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
module.exports = {
|
|
94
|
-
GREEN, RED, YELLOW, CYAN, BOLD, DIM, RESET,
|
|
95
|
-
log, ok, fail, warn, info, step,
|
|
96
|
-
prompt, promptEnterOrEsc,
|
|
97
|
-
copyToClipboard,
|
|
98
|
-
sanitizeError,
|
|
99
|
-
};
|