@mycompbox/compbox-cli 1.13.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/.tsbuildinfo +1 -0
- package/commands/configure.d.ts +24 -0
- package/commands/configure.d.ts.map +1 -0
- package/commands/configure.js +170 -0
- package/commands/configure.js.map +1 -0
- package/commands/doctor.d.ts +136 -0
- package/commands/doctor.d.ts.map +1 -0
- package/commands/doctor.js +606 -0
- package/commands/doctor.js.map +1 -0
- package/commands/install.d.ts +3 -0
- package/commands/install.d.ts.map +1 -0
- package/commands/install.js +88 -0
- package/commands/install.js.map +1 -0
- package/commands/list.d.ts +3 -0
- package/commands/list.d.ts.map +1 -0
- package/commands/list.js +141 -0
- package/commands/list.js.map +1 -0
- package/commands/login.d.ts +15 -0
- package/commands/login.d.ts.map +1 -0
- package/commands/login.js +102 -0
- package/commands/login.js.map +1 -0
- package/commands/publish.d.ts +3 -0
- package/commands/publish.d.ts.map +1 -0
- package/commands/publish.js +102 -0
- package/commands/publish.js.map +1 -0
- package/commands/run.d.ts +76 -0
- package/commands/run.d.ts.map +1 -0
- package/commands/run.js +417 -0
- package/commands/run.js.map +1 -0
- package/commands/service.d.ts +29 -0
- package/commands/service.d.ts.map +1 -0
- package/commands/service.js +142 -0
- package/commands/service.js.map +1 -0
- package/commands/update.d.ts +3 -0
- package/commands/update.d.ts.map +1 -0
- package/commands/update.js +141 -0
- package/commands/update.js.map +1 -0
- package/index.d.ts +3 -0
- package/index.d.ts.map +1 -0
- package/index.js +8508 -0
- package/index.js.map +1 -0
- package/package.json +30 -0
- package/utils/agent-invoker.d.ts +393 -0
- package/utils/agent-invoker.d.ts.map +1 -0
- package/utils/agent-invoker.js +1632 -0
- package/utils/agent-invoker.js.map +1 -0
- package/utils/api-client.d.ts +54 -0
- package/utils/api-client.d.ts.map +1 -0
- package/utils/api-client.js +214 -0
- package/utils/api-client.js.map +1 -0
- package/utils/auth-client.d.ts +61 -0
- package/utils/auth-client.d.ts.map +1 -0
- package/utils/auth-client.js +135 -0
- package/utils/auth-client.js.map +1 -0
- package/utils/claude-runtime.d.ts +116 -0
- package/utils/claude-runtime.d.ts.map +1 -0
- package/utils/claude-runtime.js +291 -0
- package/utils/claude-runtime.js.map +1 -0
- package/utils/config-store.d.ts +128 -0
- package/utils/config-store.d.ts.map +1 -0
- package/utils/config-store.js +137 -0
- package/utils/config-store.js.map +1 -0
- package/utils/file-manager.d.ts +32 -0
- package/utils/file-manager.d.ts.map +1 -0
- package/utils/file-manager.js +208 -0
- package/utils/file-manager.js.map +1 -0
- package/utils/keychain.d.ts +46 -0
- package/utils/keychain.d.ts.map +1 -0
- package/utils/keychain.js +167 -0
- package/utils/keychain.js.map +1 -0
- package/utils/loopback.d.ts +45 -0
- package/utils/loopback.d.ts.map +1 -0
- package/utils/loopback.js +95 -0
- package/utils/loopback.js.map +1 -0
- package/utils/mailbox-client.d.ts +98 -0
- package/utils/mailbox-client.d.ts.map +1 -0
- package/utils/mailbox-client.js +178 -0
- package/utils/mailbox-client.js.map +1 -0
- package/utils/mcp-config-writer.d.ts +133 -0
- package/utils/mcp-config-writer.d.ts.map +1 -0
- package/utils/mcp-config-writer.js +184 -0
- package/utils/mcp-config-writer.js.map +1 -0
- package/utils/pack-bundler.d.ts +30 -0
- package/utils/pack-bundler.d.ts.map +1 -0
- package/utils/pack-bundler.js +141 -0
- package/utils/pack-bundler.js.map +1 -0
- package/utils/prompt.d.ts +31 -0
- package/utils/prompt.d.ts.map +1 -0
- package/utils/prompt.js +86 -0
- package/utils/prompt.js.map +1 -0
- package/utils/table-formatter.d.ts +42 -0
- package/utils/table-formatter.d.ts.map +1 -0
- package/utils/table-formatter.js +125 -0
- package/utils/table-formatter.js.map +1 -0
- package/utils/version-resolver.d.ts +31 -0
- package/utils/version-resolver.d.ts.map +1 -0
- package/utils/version-resolver.js +75 -0
- package/utils/version-resolver.js.map +1 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
// ADR-0003: write-through — API_BASE_URL written here selects the central DB (docs/adr/0003-write-through-sync-architecture.md).
|
|
2
|
+
/**
|
|
3
|
+
* Generate / patch a local MCP config so Claude Code points at central CompBox.
|
|
4
|
+
*
|
|
5
|
+
* Claude Code (and compatible MCP hosts) read a JSON file with an `mcpServers`
|
|
6
|
+
* map: `{ "mcpServers": { "<name>": { command, args, env } } }`. This writer
|
|
7
|
+
* inserts/updates ONLY the CompBox server entry, preserving every other server
|
|
8
|
+
* entry and every unrelated top-level key. Existing configuration for other
|
|
9
|
+
* tools is never clobbered.
|
|
10
|
+
*
|
|
11
|
+
* The CompBox entry prefers the brew-installed MCP server bundle when present
|
|
12
|
+
* (`node <prefix>/opt/compbox/libexec/compbox-mcp.cjs`, installed by the
|
|
13
|
+
* Homebrew formula — see deploy/homebrew-tap/compbox.rb), and falls back to
|
|
14
|
+
* launching the published package via `npx` on first use. Either way the
|
|
15
|
+
* per-employee token and central base URL are supplied through its `env`.
|
|
16
|
+
*/
|
|
17
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'fs';
|
|
18
|
+
import { dirname, join } from 'path';
|
|
19
|
+
/** Default Claude Code project-level MCP config file name. */
|
|
20
|
+
export const DEFAULT_MCP_CONFIG_FILENAME = '.mcp.json';
|
|
21
|
+
/** Default server key used for the CompBox MCP entry. */
|
|
22
|
+
export const DEFAULT_SERVER_KEY = 'compbox';
|
|
23
|
+
/** The published MCP server package launched by the generated entry. */
|
|
24
|
+
export const MCP_SERVER_PACKAGE = '@mycompbox/compbox-mcp';
|
|
25
|
+
/**
|
|
26
|
+
* Locate the brew-installed MCP server bundle, if any.
|
|
27
|
+
*
|
|
28
|
+
* Candidate prefixes, in order: an explicit `opts.prefix` (e.g. from
|
|
29
|
+
* `brew --prefix`), `$HOMEBREW_PREFIX`, `/opt/homebrew` (Apple Silicon
|
|
30
|
+
* default), `/usr/local` (Intel default). Each is checked for the formula's
|
|
31
|
+
* keg-relative bundle path `opt/compbox/libexec/compbox-mcp.cjs`.
|
|
32
|
+
*
|
|
33
|
+
* `opts.exists` is injectable so tests never need a real brew install.
|
|
34
|
+
*/
|
|
35
|
+
export function resolveInstalledMcpBundle(opts) {
|
|
36
|
+
const exists = opts?.exists ?? existsSync;
|
|
37
|
+
const prefixes = [];
|
|
38
|
+
if (opts?.prefix)
|
|
39
|
+
prefixes.push(opts.prefix);
|
|
40
|
+
if (process.env.HOMEBREW_PREFIX)
|
|
41
|
+
prefixes.push(process.env.HOMEBREW_PREFIX);
|
|
42
|
+
prefixes.push('/opt/homebrew', '/usr/local');
|
|
43
|
+
const seen = new Set();
|
|
44
|
+
for (const prefix of prefixes) {
|
|
45
|
+
if (seen.has(prefix))
|
|
46
|
+
continue;
|
|
47
|
+
seen.add(prefix);
|
|
48
|
+
const candidate = join(prefix, 'opt', 'compbox', 'libexec', 'compbox-mcp.cjs');
|
|
49
|
+
if (exists(candidate))
|
|
50
|
+
return candidate;
|
|
51
|
+
}
|
|
52
|
+
return undefined;
|
|
53
|
+
}
|
|
54
|
+
/** Default absolute path to the project MCP config in the given directory. */
|
|
55
|
+
export function defaultMcpConfigPath(projectRoot = process.cwd()) {
|
|
56
|
+
return join(projectRoot, DEFAULT_MCP_CONFIG_FILENAME);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Build the CompBox MCP server entry from a spec. Exposed for testing and reuse.
|
|
60
|
+
*
|
|
61
|
+
* Launch-target selection (when neither `command` nor `args` is explicitly
|
|
62
|
+
* overridden): prefer `node <installed bundle>` when the brew-installed
|
|
63
|
+
* compbox-mcp.cjs resolves, else fall back to `npx -y ${MCP_SERVER_PACKAGE}`
|
|
64
|
+
* (fetched from the public npm registry on first use). An explicit `command`
|
|
65
|
+
* or `args` override always wins and disables detection.
|
|
66
|
+
*/
|
|
67
|
+
export function buildCompboxServerEntry(spec) {
|
|
68
|
+
const env = {
|
|
69
|
+
API_BASE_URL: spec.apiBaseUrl,
|
|
70
|
+
API_TOKEN: spec.apiToken,
|
|
71
|
+
};
|
|
72
|
+
const explicitLaunch = spec.command !== undefined || spec.args !== undefined;
|
|
73
|
+
if (!explicitLaunch) {
|
|
74
|
+
const bundlePath = (spec.resolveInstalledBundle ?? resolveInstalledMcpBundle)();
|
|
75
|
+
if (bundlePath !== undefined) {
|
|
76
|
+
return { command: 'node', args: [bundlePath], env };
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
command: spec.command ?? 'npx',
|
|
81
|
+
args: spec.args ?? ['-y', MCP_SERVER_PACKAGE],
|
|
82
|
+
env,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
function readExistingConfig(configPath) {
|
|
86
|
+
if (!existsSync(configPath)) {
|
|
87
|
+
return { config: {}, existed: false };
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
const parsed = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
91
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
92
|
+
return { config: parsed, existed: true };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// Corrupt/unreadable JSON: treat as absent but report the file as existing
|
|
97
|
+
// so we don't silently overwrite without the caller realizing.
|
|
98
|
+
}
|
|
99
|
+
return { config: {}, existed: existsSync(configPath) };
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Inspect a config file for the CompBox MCP server entry WITHOUT modifying it.
|
|
103
|
+
*
|
|
104
|
+
* Used by `compbox doctor` to verify that `configure` already wrote the entry
|
|
105
|
+
* to the expected path. This verifies the WRITTEN config file and surfaces the
|
|
106
|
+
* configured launch target (command + args) read-only, so doctor can further
|
|
107
|
+
* check that a `node <bundle>` target actually exists on disk (the entry may
|
|
108
|
+
* instead be `npx`, which fetches the published package on first use).
|
|
109
|
+
*/
|
|
110
|
+
export function inspectMcpConfig(configPath, serverKey = DEFAULT_SERVER_KEY) {
|
|
111
|
+
const { config, existed } = readExistingConfig(configPath);
|
|
112
|
+
const servers = config.mcpServers;
|
|
113
|
+
const entryPresent = servers !== undefined &&
|
|
114
|
+
typeof servers === 'object' &&
|
|
115
|
+
!Array.isArray(servers) &&
|
|
116
|
+
serverKey in servers;
|
|
117
|
+
// Surface the entry's central target (env.API_BASE_URL) read-only, so doctor
|
|
118
|
+
// can warn about localhost/mismatched centrals. Never expose API_TOKEN.
|
|
119
|
+
// Also surface the configured launch target (command + args) read-only, so
|
|
120
|
+
// doctor can verify a `node <bundle>` target actually exists (ENG-141).
|
|
121
|
+
let apiBaseUrl;
|
|
122
|
+
let command;
|
|
123
|
+
let args;
|
|
124
|
+
if (entryPresent) {
|
|
125
|
+
// `entryPresent` already narrows `servers` to a defined object.
|
|
126
|
+
const entry = servers[serverKey];
|
|
127
|
+
if (entry && typeof entry === 'object' && !Array.isArray(entry)) {
|
|
128
|
+
const env = entry.env;
|
|
129
|
+
if (env && typeof env === 'object' && !Array.isArray(env)) {
|
|
130
|
+
const value = env.API_BASE_URL;
|
|
131
|
+
if (typeof value === 'string' && value.length > 0) {
|
|
132
|
+
apiBaseUrl = value;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
const rawCommand = entry.command;
|
|
136
|
+
if (typeof rawCommand === 'string' && rawCommand.length > 0) {
|
|
137
|
+
command = rawCommand;
|
|
138
|
+
}
|
|
139
|
+
const rawArgs = entry.args;
|
|
140
|
+
if (Array.isArray(rawArgs) && rawArgs.every((a) => typeof a === 'string')) {
|
|
141
|
+
args = rawArgs;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
configPath,
|
|
147
|
+
fileExists: existed,
|
|
148
|
+
entryPresent,
|
|
149
|
+
...(apiBaseUrl !== undefined ? { apiBaseUrl } : {}),
|
|
150
|
+
...(command !== undefined ? { command } : {}),
|
|
151
|
+
...(args !== undefined ? { args } : {}),
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Patch (or create) the MCP config at `configPath`, writing the CompBox server
|
|
156
|
+
* entry while preserving all other content.
|
|
157
|
+
*/
|
|
158
|
+
export function patchMcpConfig(configPath, spec) {
|
|
159
|
+
const serverKey = spec.serverKey ?? DEFAULT_SERVER_KEY;
|
|
160
|
+
const { config, existed } = readExistingConfig(configPath);
|
|
161
|
+
const existingServersRaw = config.mcpServers;
|
|
162
|
+
const existingServers = existingServersRaw && typeof existingServersRaw === 'object' && !Array.isArray(existingServersRaw)
|
|
163
|
+
? { ...existingServersRaw }
|
|
164
|
+
: {};
|
|
165
|
+
const entryCreated = !(serverKey in existingServers);
|
|
166
|
+
const preservedServers = Object.keys(existingServers).filter((key) => key !== serverKey);
|
|
167
|
+
const entry = buildCompboxServerEntry(spec);
|
|
168
|
+
existingServers[serverKey] = entry;
|
|
169
|
+
const nextConfig = {
|
|
170
|
+
...config,
|
|
171
|
+
mcpServers: existingServers,
|
|
172
|
+
};
|
|
173
|
+
const dir = dirname(configPath);
|
|
174
|
+
mkdirSync(dir, { recursive: true });
|
|
175
|
+
writeFileSync(configPath, `${JSON.stringify(nextConfig, null, 2)}\n`, 'utf-8');
|
|
176
|
+
return {
|
|
177
|
+
fileCreated: !existed,
|
|
178
|
+
entryCreated,
|
|
179
|
+
preservedServers,
|
|
180
|
+
configPath,
|
|
181
|
+
entry,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
//# sourceMappingURL=mcp-config-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-config-writer.js","sourceRoot":"","sources":["../../src/utils/mcp-config-writer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export interface PackManifest {
|
|
2
|
+
name: string;
|
|
3
|
+
version: string;
|
|
4
|
+
description: string;
|
|
5
|
+
author?: string;
|
|
6
|
+
files: {
|
|
7
|
+
agents?: string[];
|
|
8
|
+
skills?: string[];
|
|
9
|
+
instructions?: string[];
|
|
10
|
+
presets?: string[];
|
|
11
|
+
mcpConfig?: string;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export interface BundledPack {
|
|
15
|
+
manifest: PackManifest;
|
|
16
|
+
files: Record<string, string>;
|
|
17
|
+
}
|
|
18
|
+
export declare class PackBundler {
|
|
19
|
+
private packRoot;
|
|
20
|
+
constructor(packRoot?: string);
|
|
21
|
+
readPackManifest(): Promise<PackManifest>;
|
|
22
|
+
bundlePack(): Promise<BundledPack>;
|
|
23
|
+
validatePack(_dryRun?: boolean): Promise<{
|
|
24
|
+
valid: boolean;
|
|
25
|
+
errors: string[];
|
|
26
|
+
warnings: string[];
|
|
27
|
+
fileCount: number;
|
|
28
|
+
}>;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=pack-bundler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pack-bundler.d.ts","sourceRoot":"","sources":["../../src/utils/pack-bundler.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE;QACL,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAClB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;QAClB,YAAY,CAAC,EAAE,MAAM,EAAE,CAAC;QACxB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;QACnB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC;CACH;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAS;gBAEb,QAAQ,CAAC,EAAE,MAAM;IAIvB,gBAAgB,IAAI,OAAO,CAAC,YAAY,CAAC;IA2BzC,UAAU,IAAI,OAAO,CAAC,WAAW,CAAC;IAsElC,YAAY,CAAC,OAAO,UAAQ,GAAG,OAAO,CAAC;QAC3C,KAAK,EAAE,OAAO,CAAC;QACf,MAAM,EAAE,MAAM,EAAE,CAAC;QACjB,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;KACnB,CAAC;CA0DH"}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import * as fs from 'fs/promises';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { existsSync } from 'fs';
|
|
4
|
+
export class PackBundler {
|
|
5
|
+
packRoot;
|
|
6
|
+
constructor(packRoot) {
|
|
7
|
+
this.packRoot = packRoot ?? process.cwd();
|
|
8
|
+
}
|
|
9
|
+
async readPackManifest() {
|
|
10
|
+
const manifestPath = path.join(this.packRoot, '.compbox', 'pack.json');
|
|
11
|
+
if (!existsSync(manifestPath)) {
|
|
12
|
+
throw new Error('Pack manifest not found at .compbox/pack.json');
|
|
13
|
+
}
|
|
14
|
+
const content = await fs.readFile(manifestPath, 'utf-8');
|
|
15
|
+
const manifest = JSON.parse(content);
|
|
16
|
+
// Validate required fields
|
|
17
|
+
if (!manifest.name || !manifest.version || !manifest.description) {
|
|
18
|
+
throw new Error('Invalid pack manifest: name, version, and description are required');
|
|
19
|
+
}
|
|
20
|
+
// Validate version format (basic semver check)
|
|
21
|
+
if (!/^\d+\.\d+\.\d+/.test(manifest.version)) {
|
|
22
|
+
throw new Error(`Invalid version format: ${manifest.version}. Expected semver format (e.g., 1.0.0)`);
|
|
23
|
+
}
|
|
24
|
+
return manifest;
|
|
25
|
+
}
|
|
26
|
+
async bundlePack() {
|
|
27
|
+
const manifest = await this.readPackManifest();
|
|
28
|
+
const files = {};
|
|
29
|
+
const githubDir = path.join(this.packRoot, '.github');
|
|
30
|
+
// Collect agent files
|
|
31
|
+
if (manifest.files.agents) {
|
|
32
|
+
for (const agentFile of manifest.files.agents) {
|
|
33
|
+
const fullPath = path.join(githubDir, 'agents', agentFile);
|
|
34
|
+
if (!existsSync(fullPath)) {
|
|
35
|
+
throw new Error(`Agent file not found: ${agentFile}`);
|
|
36
|
+
}
|
|
37
|
+
const content = await fs.readFile(fullPath, 'utf-8');
|
|
38
|
+
files[`.github/agents/${agentFile}`] = content;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Collect skill files
|
|
42
|
+
if (manifest.files.skills) {
|
|
43
|
+
for (const skillFile of manifest.files.skills) {
|
|
44
|
+
const fullPath = path.join(githubDir, 'skills', skillFile);
|
|
45
|
+
if (!existsSync(fullPath)) {
|
|
46
|
+
throw new Error(`Skill file not found: ${skillFile}`);
|
|
47
|
+
}
|
|
48
|
+
const content = await fs.readFile(fullPath, 'utf-8');
|
|
49
|
+
files[`.github/skills/${skillFile}`] = content;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Collect instruction files
|
|
53
|
+
if (manifest.files.instructions) {
|
|
54
|
+
for (const instructionFile of manifest.files.instructions) {
|
|
55
|
+
const fullPath = path.join(githubDir, 'instructions', instructionFile);
|
|
56
|
+
if (!existsSync(fullPath)) {
|
|
57
|
+
throw new Error(`Instruction file not found: ${instructionFile}`);
|
|
58
|
+
}
|
|
59
|
+
const content = await fs.readFile(fullPath, 'utf-8');
|
|
60
|
+
files[`.github/instructions/${instructionFile}`] = content;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Collect preset files
|
|
64
|
+
if (manifest.files.presets) {
|
|
65
|
+
for (const presetFile of manifest.files.presets) {
|
|
66
|
+
const fullPath = path.join(githubDir, 'presets', presetFile);
|
|
67
|
+
if (!existsSync(fullPath)) {
|
|
68
|
+
throw new Error(`Preset file not found: ${presetFile}`);
|
|
69
|
+
}
|
|
70
|
+
const content = await fs.readFile(fullPath, 'utf-8');
|
|
71
|
+
files[`.github/presets/${presetFile}`] = content;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Collect MCP config if specified
|
|
75
|
+
if (manifest.files.mcpConfig) {
|
|
76
|
+
const fullPath = path.join(githubDir, manifest.files.mcpConfig);
|
|
77
|
+
if (!existsSync(fullPath)) {
|
|
78
|
+
throw new Error(`MCP config file not found: ${manifest.files.mcpConfig}`);
|
|
79
|
+
}
|
|
80
|
+
const content = await fs.readFile(fullPath, 'utf-8');
|
|
81
|
+
files[`.github/${manifest.files.mcpConfig}`] = content;
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
manifest,
|
|
85
|
+
files,
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
async validatePack(_dryRun = false) {
|
|
89
|
+
const errors = [];
|
|
90
|
+
const warnings = [];
|
|
91
|
+
let fileCount = 0;
|
|
92
|
+
try {
|
|
93
|
+
const manifest = await this.readPackManifest();
|
|
94
|
+
const githubDir = path.join(this.packRoot, '.github');
|
|
95
|
+
// Check if .github directory exists
|
|
96
|
+
if (!existsSync(githubDir)) {
|
|
97
|
+
errors.push('.github directory not found');
|
|
98
|
+
return { valid: false, errors, warnings, fileCount };
|
|
99
|
+
}
|
|
100
|
+
// Validate each file exists
|
|
101
|
+
const allFiles = [
|
|
102
|
+
...(manifest.files.agents?.map((f) => `agents/${f}`) ?? []),
|
|
103
|
+
...(manifest.files.skills?.map((f) => `skills/${f}`) ?? []),
|
|
104
|
+
...(manifest.files.instructions?.map((f) => `instructions/${f}`) ?? []),
|
|
105
|
+
...(manifest.files.presets?.map((f) => `presets/${f}`) ?? []),
|
|
106
|
+
];
|
|
107
|
+
if (manifest.files.mcpConfig) {
|
|
108
|
+
allFiles.push(manifest.files.mcpConfig);
|
|
109
|
+
}
|
|
110
|
+
for (const file of allFiles) {
|
|
111
|
+
const fullPath = path.join(githubDir, file);
|
|
112
|
+
if (!existsSync(fullPath)) {
|
|
113
|
+
errors.push(`File not found: ${file}`);
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
fileCount++;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Warnings
|
|
120
|
+
if (fileCount === 0) {
|
|
121
|
+
warnings.push('No files to publish');
|
|
122
|
+
}
|
|
123
|
+
if (!manifest.author) {
|
|
124
|
+
warnings.push('No author specified in manifest');
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
valid: errors.length === 0,
|
|
128
|
+
errors,
|
|
129
|
+
warnings,
|
|
130
|
+
fileCount,
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
if (error instanceof Error) {
|
|
135
|
+
errors.push(error.message);
|
|
136
|
+
}
|
|
137
|
+
return { valid: false, errors, warnings, fileCount: 0 };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=pack-bundler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pack-bundler.js","sourceRoot":"","sources":["../../src/utils/pack-bundler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal interactive prompt helpers built on Node's `readline`.
|
|
3
|
+
*
|
|
4
|
+
* We deliberately avoid adding an interactive-prompt dependency (inquirer,
|
|
5
|
+
* prompts, etc.) to keep the CLI dependency surface small. These helpers cover
|
|
6
|
+
* the three interactions the setup wizard needs: free text, masked secret
|
|
7
|
+
* entry, and a numbered single-select.
|
|
8
|
+
*
|
|
9
|
+
* All helpers degrade gracefully when stdin is not a TTY (piped input): they
|
|
10
|
+
* read a line normally (masking is a no-op in that case).
|
|
11
|
+
*/
|
|
12
|
+
/** Prompt for a line of free text. Returns the trimmed answer. */
|
|
13
|
+
export declare function promptText(question: string): Promise<string>;
|
|
14
|
+
/**
|
|
15
|
+
* Prompt for a secret without echoing keystrokes to the terminal.
|
|
16
|
+
* The prompt label is printed, but typed characters are suppressed.
|
|
17
|
+
*/
|
|
18
|
+
export declare function promptSecret(question: string): Promise<string>;
|
|
19
|
+
/** A selectable option for {@link promptSelect}. */
|
|
20
|
+
export interface SelectChoice {
|
|
21
|
+
label: string;
|
|
22
|
+
value: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Present a numbered list and return the `value` of the chosen option.
|
|
26
|
+
* Re-prompts until a valid selection is entered.
|
|
27
|
+
*/
|
|
28
|
+
export declare function promptSelect(question: string, choices: SelectChoice[]): Promise<string>;
|
|
29
|
+
/** Prompt a yes/no confirmation. Returns true for yes. */
|
|
30
|
+
export declare function promptConfirm(question: string, defaultYes?: boolean): Promise<boolean>;
|
|
31
|
+
//# sourceMappingURL=prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/utils/prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAKH,kEAAkE;AAClE,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAUlE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAqB9D;AAED,oDAAoD;AACpD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,YAAY,EAAE,GACtB,OAAO,CAAC,MAAM,CAAC,CAsBjB;AAED,0DAA0D;AAC1D,wBAAsB,aAAa,CACjC,QAAQ,EAAE,MAAM,EAChB,UAAU,UAAO,GAChB,OAAO,CAAC,OAAO,CAAC,CAOlB"}
|
package/utils/prompt.js
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Minimal interactive prompt helpers built on Node's `readline`.
|
|
3
|
+
*
|
|
4
|
+
* We deliberately avoid adding an interactive-prompt dependency (inquirer,
|
|
5
|
+
* prompts, etc.) to keep the CLI dependency surface small. These helpers cover
|
|
6
|
+
* the three interactions the setup wizard needs: free text, masked secret
|
|
7
|
+
* entry, and a numbered single-select.
|
|
8
|
+
*
|
|
9
|
+
* All helpers degrade gracefully when stdin is not a TTY (piped input): they
|
|
10
|
+
* read a line normally (masking is a no-op in that case).
|
|
11
|
+
*/
|
|
12
|
+
import * as readline from 'node:readline';
|
|
13
|
+
import { stdin, stdout } from 'node:process';
|
|
14
|
+
/** Prompt for a line of free text. Returns the trimmed answer. */
|
|
15
|
+
export async function promptText(question) {
|
|
16
|
+
const rl = readline.createInterface({ input: stdin, output: stdout });
|
|
17
|
+
try {
|
|
18
|
+
const answer = await new Promise((resolve) => {
|
|
19
|
+
rl.question(question, resolve);
|
|
20
|
+
});
|
|
21
|
+
return answer.trim();
|
|
22
|
+
}
|
|
23
|
+
finally {
|
|
24
|
+
rl.close();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Prompt for a secret without echoing keystrokes to the terminal.
|
|
29
|
+
* The prompt label is printed, but typed characters are suppressed.
|
|
30
|
+
*/
|
|
31
|
+
export function promptSecret(question) {
|
|
32
|
+
return new Promise((resolve) => {
|
|
33
|
+
const rl = readline.createInterface({
|
|
34
|
+
input: stdin,
|
|
35
|
+
output: stdout,
|
|
36
|
+
terminal: true,
|
|
37
|
+
});
|
|
38
|
+
// Print the prompt ourselves, then suppress readline's echo of typed chars.
|
|
39
|
+
stdout.write(question);
|
|
40
|
+
// `_writeToOutput` is an internal hook used to render typed input; overriding
|
|
41
|
+
// it with a no-op masks the secret. Typed as a mutable shape via cast.
|
|
42
|
+
rl._writeToOutput =
|
|
43
|
+
() => {
|
|
44
|
+
/* suppress echo of the secret */
|
|
45
|
+
};
|
|
46
|
+
rl.question('', (answer) => {
|
|
47
|
+
rl.close();
|
|
48
|
+
stdout.write('\n');
|
|
49
|
+
resolve(answer.trim());
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Present a numbered list and return the `value` of the chosen option.
|
|
55
|
+
* Re-prompts until a valid selection is entered.
|
|
56
|
+
*/
|
|
57
|
+
export async function promptSelect(question, choices) {
|
|
58
|
+
if (choices.length === 0) {
|
|
59
|
+
throw new Error('promptSelect requires at least one choice');
|
|
60
|
+
}
|
|
61
|
+
stdout.write(`${question}\n`);
|
|
62
|
+
choices.forEach((choice, index) => {
|
|
63
|
+
stdout.write(` ${String(index + 1)}) ${choice.label}\n`);
|
|
64
|
+
});
|
|
65
|
+
for (;;) {
|
|
66
|
+
const answer = await promptText(`Enter choice [1-${String(choices.length)}]: `);
|
|
67
|
+
const selected = Number.parseInt(answer, 10);
|
|
68
|
+
if (Number.isInteger(selected) && selected >= 1 && selected <= choices.length) {
|
|
69
|
+
const choice = choices[selected - 1];
|
|
70
|
+
if (choice) {
|
|
71
|
+
return choice.value;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
stdout.write('Invalid selection. Please try again.\n');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/** Prompt a yes/no confirmation. Returns true for yes. */
|
|
78
|
+
export async function promptConfirm(question, defaultYes = true) {
|
|
79
|
+
const suffix = defaultYes ? ' [Y/n] ' : ' [y/N] ';
|
|
80
|
+
const answer = (await promptText(question + suffix)).toLowerCase();
|
|
81
|
+
if (answer === '') {
|
|
82
|
+
return defaultYes;
|
|
83
|
+
}
|
|
84
|
+
return answer === 'y' || answer === 'yes';
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/utils/prompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE7C,kEAAkE;AAClE,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAgB;IAC/C,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IACtE,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;YACnD,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QACH,OAAO,MAAM,CAAC,IAAI,EAAE,CAAC;IACvB,CAAC;YAAS,CAAC;QACT,EAAE,CAAC,KAAK,EAAE,CAAC;IACb,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,QAAgB;IAC3C,OAAO,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE;QACrC,MAAM,EAAE,GAAG,QAAQ,CAAC,eAAe,CAAC;YAClC,KAAK,EAAE,KAAK;YACZ,MAAM,EAAE,MAAM;YACd,QAAQ,EAAE,IAAI;SACf,CAAC,CAAC;QACH,4EAA4E;QAC5E,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACvB,8EAA8E;QAC9E,uEAAuE;QACtE,EAAyD,CAAC,cAAc;YACvE,GAAG,EAAE;gBACH,iCAAiC;YACnC,CAAC,CAAC;QACJ,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC,MAAM,EAAE,EAAE;YACzB,EAAE,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACnB,OAAO,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACzB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAQD;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAAgB,EAChB,OAAuB;IAEvB,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,2CAA2C,CAAC,CAAC;IAC/D,CAAC;IACD,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,IAAI,CAAC,CAAC;IAC9B,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,EAAE;QAChC,MAAM,CAAC,KAAK,CAAC,KAAK,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC;QACR,MAAM,MAAM,GAAG,MAAM,UAAU,CAC7B,mBAAmB,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAC/C,CAAC;QACF,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QAC7C,IAAI,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,QAAQ,IAAI,CAAC,IAAI,QAAQ,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;YAC9E,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;YACrC,IAAI,MAAM,EAAE,CAAC;gBACX,OAAO,MAAM,CAAC,KAAK,CAAC;YACtB,CAAC;QACH,CAAC;QACD,MAAM,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;IACzD,CAAC;AACH,CAAC;AAED,0DAA0D;AAC1D,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,QAAgB,EAChB,UAAU,GAAG,IAAI;IAEjB,MAAM,MAAM,GAAG,UAAU,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IAClD,MAAM,MAAM,GAAG,CAAC,MAAM,UAAU,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACnE,IAAI,MAAM,KAAK,EAAE,EAAE,CAAC;QAClB,OAAO,UAAU,CAAC;IACpB,CAAC;IACD,OAAO,MAAM,KAAK,GAAG,IAAI,MAAM,KAAK,KAAK,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export interface PackRow {
|
|
2
|
+
name: string;
|
|
3
|
+
version: string;
|
|
4
|
+
description?: string;
|
|
5
|
+
installedVersion?: string;
|
|
6
|
+
updateAvailable?: string | undefined;
|
|
7
|
+
}
|
|
8
|
+
export declare class TableFormatter {
|
|
9
|
+
/**
|
|
10
|
+
* Format installed packs table
|
|
11
|
+
*/
|
|
12
|
+
static formatInstalledPacks(packs: PackRow[]): string;
|
|
13
|
+
/**
|
|
14
|
+
* Format available packs table
|
|
15
|
+
*/
|
|
16
|
+
static formatAvailablePacks(packs: PackRow[]): string;
|
|
17
|
+
/**
|
|
18
|
+
* Format combined packs table (installed + available)
|
|
19
|
+
*/
|
|
20
|
+
static formatCombinedPacks(packs: PackRow[]): string;
|
|
21
|
+
/**
|
|
22
|
+
* Format a simple list
|
|
23
|
+
*/
|
|
24
|
+
static formatList(items: string[]): string;
|
|
25
|
+
/**
|
|
26
|
+
* Format success message
|
|
27
|
+
*/
|
|
28
|
+
static success(message: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* Format error message
|
|
31
|
+
*/
|
|
32
|
+
static error(message: string): string;
|
|
33
|
+
/**
|
|
34
|
+
* Format warning message
|
|
35
|
+
*/
|
|
36
|
+
static warning(message: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Format info message
|
|
39
|
+
*/
|
|
40
|
+
static info(message: string): string;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=table-formatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"table-formatter.d.ts","sourceRoot":"","sources":["../../src/utils/table-formatter.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACtC;AAGD,qBAAa,cAAc;IACzB;;OAEG;IACH,MAAM,CAAC,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM;IA+BrD;;OAEG;IACH,MAAM,CAAC,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM;IAyBrD;;OAEG;IACH,MAAM,CAAC,mBAAmB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,MAAM;IAoCpD;;OAEG;IACH,MAAM,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM;IAI1C;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAIvC;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAIrC;;OAEG;IACH,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;IAIvC;;OAEG;IACH,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM;CAGrC"}
|