@tpmjs/cli 0.1.4 → 0.1.5
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 +21 -0
- package/README.md +18 -0
- package/bin/run.js +0 -0
- package/dist/commands/agent/chat.js +7 -7
- package/dist/commands/agent/chat.js.map +1 -1
- package/dist/commands/agent/create.js +6 -6
- package/dist/commands/agent/create.js.map +1 -1
- package/dist/commands/agent/delete.js +9 -7
- package/dist/commands/agent/delete.js.map +1 -1
- package/dist/commands/agent/list.js +6 -6
- package/dist/commands/agent/list.js.map +1 -1
- package/dist/commands/agent/update.js +6 -6
- package/dist/commands/agent/update.js.map +1 -1
- package/dist/commands/auth/login.js +6 -6
- package/dist/commands/auth/login.js.map +1 -1
- package/dist/commands/auth/logout.js +4 -4
- package/dist/commands/auth/logout.js.map +1 -1
- package/dist/commands/auth/status.js +12 -9
- package/dist/commands/auth/status.js.map +1 -1
- package/dist/commands/auth/whoami.js +6 -6
- package/dist/commands/auth/whoami.js.map +1 -1
- package/dist/commands/collection/add.js +6 -6
- package/dist/commands/collection/add.js.map +1 -1
- package/dist/commands/collection/create.js +6 -6
- package/dist/commands/collection/create.js.map +1 -1
- package/dist/commands/collection/delete.js +7 -7
- package/dist/commands/collection/delete.js.map +1 -1
- package/dist/commands/collection/import.js +7 -7
- package/dist/commands/collection/import.js.map +1 -1
- package/dist/commands/collection/info.d.ts +17 -0
- package/dist/commands/collection/info.js +358 -0
- package/dist/commands/collection/info.js.map +1 -0
- package/dist/commands/collection/list.js +6 -6
- package/dist/commands/collection/list.js.map +1 -1
- package/dist/commands/collection/remove.js +7 -9
- package/dist/commands/collection/remove.js.map +1 -1
- package/dist/commands/collection/update.js +6 -6
- package/dist/commands/collection/update.js.map +1 -1
- package/dist/commands/doctor.js +7 -7
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/mcp/config.js +4 -4
- package/dist/commands/mcp/config.js.map +1 -1
- package/dist/commands/mcp/serve.js +7 -7
- package/dist/commands/mcp/serve.js.map +1 -1
- package/dist/commands/playground.js +7 -7
- package/dist/commands/playground.js.map +1 -1
- package/dist/commands/publish/check.js +11 -11
- package/dist/commands/publish/check.js.map +1 -1
- package/dist/commands/publish/preview.js +4 -4
- package/dist/commands/publish/preview.js.map +1 -1
- package/dist/commands/run.d.ts +24 -0
- package/dist/commands/run.js +454 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/commands/scenario/generate.js +6 -6
- package/dist/commands/scenario/generate.js.map +1 -1
- package/dist/commands/scenario/info.js +6 -6
- package/dist/commands/scenario/info.js.map +1 -1
- package/dist/commands/scenario/list.js +11 -11
- package/dist/commands/scenario/list.js.map +1 -1
- package/dist/commands/scenario/run.js +7 -7
- package/dist/commands/scenario/run.js.map +1 -1
- package/dist/commands/scenario/test.js +8 -8
- package/dist/commands/scenario/test.js.map +1 -1
- package/dist/commands/tool/execute.js +9 -7
- package/dist/commands/tool/execute.js.map +1 -1
- package/dist/commands/tool/info.js +16 -9
- package/dist/commands/tool/info.js.map +1 -1
- package/dist/commands/tool/init.js +7 -13
- package/dist/commands/tool/init.js.map +1 -1
- package/dist/commands/tool/search.js +7 -11
- package/dist/commands/tool/search.js.map +1 -1
- package/dist/commands/tool/trending.js +6 -6
- package/dist/commands/tool/trending.js.map +1 -1
- package/dist/commands/tool/validate.js +15 -9
- package/dist/commands/tool/validate.js.map +1 -1
- package/dist/commands/update.js +4 -4
- package/dist/commands/update.js.map +1 -1
- package/dist/hooks/init.js +1 -1
- package/dist/hooks/init.js.map +1 -1
- package/dist/index.js +6 -6
- package/dist/index.js.map +1 -1
- package/oclif.manifest.json +146 -1
- package/package.json +10 -12
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import { Command, Args, Flags } from '@oclif/core';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as os from 'os';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
import Conf from 'conf';
|
|
6
|
+
import Table from 'cli-table3';
|
|
7
|
+
import ora from 'ora';
|
|
8
|
+
import pc from 'picocolors';
|
|
9
|
+
|
|
10
|
+
// src/commands/collection/info.ts
|
|
11
|
+
var CONFIG_DIR = path.join(os.homedir(), ".tpmjs");
|
|
12
|
+
var CREDENTIALS_FILE = path.join(CONFIG_DIR, "credentials.json");
|
|
13
|
+
path.join(CONFIG_DIR, "history");
|
|
14
|
+
function ensureConfigDir() {
|
|
15
|
+
if (!fs.existsSync(CONFIG_DIR)) {
|
|
16
|
+
fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
var configStore = new Conf({
|
|
20
|
+
projectName: "tpmjs",
|
|
21
|
+
cwd: CONFIG_DIR,
|
|
22
|
+
configName: "config",
|
|
23
|
+
defaults: {
|
|
24
|
+
apiUrl: "https://tpmjs.com/api",
|
|
25
|
+
defaultOutput: "human",
|
|
26
|
+
verbose: false,
|
|
27
|
+
analytics: false
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
function getConfigValue(key) {
|
|
31
|
+
return configStore.get(key);
|
|
32
|
+
}
|
|
33
|
+
function loadCredentials() {
|
|
34
|
+
ensureConfigDir();
|
|
35
|
+
if (!fs.existsSync(CREDENTIALS_FILE)) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const content = fs.readFileSync(CREDENTIALS_FILE, "utf-8");
|
|
40
|
+
return JSON.parse(content);
|
|
41
|
+
} catch {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
function getApiKey() {
|
|
46
|
+
if (process.env.TPMJS_API_KEY) {
|
|
47
|
+
return process.env.TPMJS_API_KEY;
|
|
48
|
+
}
|
|
49
|
+
const creds = loadCredentials();
|
|
50
|
+
if (creds?.apiKey) {
|
|
51
|
+
return creds.apiKey;
|
|
52
|
+
}
|
|
53
|
+
return void 0;
|
|
54
|
+
}
|
|
55
|
+
function getApiUrl() {
|
|
56
|
+
return process.env.TPMJS_API_URL ?? getConfigValue("apiUrl") ?? "https://tpmjs.com/api";
|
|
57
|
+
}
|
|
58
|
+
var OutputFormatter = class {
|
|
59
|
+
options;
|
|
60
|
+
constructor(options = {}) {
|
|
61
|
+
this.options = options;
|
|
62
|
+
}
|
|
63
|
+
// Output as JSON
|
|
64
|
+
json(data) {
|
|
65
|
+
console.log(JSON.stringify(data, null, 2));
|
|
66
|
+
}
|
|
67
|
+
// Output a table
|
|
68
|
+
table(data, columns) {
|
|
69
|
+
if (this.options.json) {
|
|
70
|
+
this.json(data);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const table = new Table({
|
|
74
|
+
head: columns.map((col) => pc.bold(col.header)),
|
|
75
|
+
colWidths: columns.map((col) => col.width ?? null),
|
|
76
|
+
style: {
|
|
77
|
+
head: [],
|
|
78
|
+
border: []
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
for (const row of data) {
|
|
82
|
+
table.push(columns.map((col) => String(row[col.key] ?? "")));
|
|
83
|
+
}
|
|
84
|
+
console.log(table.toString());
|
|
85
|
+
}
|
|
86
|
+
// Success message
|
|
87
|
+
success(message) {
|
|
88
|
+
if (this.options.json) return;
|
|
89
|
+
console.log(pc.green("\u2713"), message);
|
|
90
|
+
}
|
|
91
|
+
// Error message
|
|
92
|
+
error(message, details) {
|
|
93
|
+
if (this.options.json) {
|
|
94
|
+
this.json({ error: message, details });
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
console.error(pc.red("\u2717"), message);
|
|
98
|
+
if (details && this.options.verbose) {
|
|
99
|
+
console.error(pc.dim(details));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// Warning message
|
|
103
|
+
warning(message) {
|
|
104
|
+
if (this.options.json) return;
|
|
105
|
+
console.log(pc.yellow("\u26A0"), message);
|
|
106
|
+
}
|
|
107
|
+
// Info message
|
|
108
|
+
info(message) {
|
|
109
|
+
if (this.options.json) return;
|
|
110
|
+
console.log(pc.blue("\u2139"), message);
|
|
111
|
+
}
|
|
112
|
+
// Debug message (only in verbose mode)
|
|
113
|
+
debug(message) {
|
|
114
|
+
if (this.options.json) return;
|
|
115
|
+
if (this.options.verbose) {
|
|
116
|
+
console.log(pc.dim(`[debug] ${message}`));
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Plain text output
|
|
120
|
+
text(message) {
|
|
121
|
+
if (this.options.json) return;
|
|
122
|
+
console.log(message);
|
|
123
|
+
}
|
|
124
|
+
// Heading
|
|
125
|
+
heading(text) {
|
|
126
|
+
if (this.options.json) return;
|
|
127
|
+
console.log();
|
|
128
|
+
console.log(pc.bold(pc.underline(text)));
|
|
129
|
+
console.log();
|
|
130
|
+
}
|
|
131
|
+
// Subheading
|
|
132
|
+
subheading(text) {
|
|
133
|
+
if (this.options.json) return;
|
|
134
|
+
console.log(pc.bold(text));
|
|
135
|
+
}
|
|
136
|
+
// Key-value pair
|
|
137
|
+
keyValue(key, value) {
|
|
138
|
+
if (this.options.json) return;
|
|
139
|
+
console.log(`${pc.dim(`${key}:`)} ${value ?? pc.dim("(not set)")}`);
|
|
140
|
+
}
|
|
141
|
+
// List item
|
|
142
|
+
listItem(text, indent = 0) {
|
|
143
|
+
if (this.options.json) return;
|
|
144
|
+
const prefix = `${" ".repeat(indent)}\u2022`;
|
|
145
|
+
console.log(`${prefix} ${text}`);
|
|
146
|
+
}
|
|
147
|
+
// Spinner
|
|
148
|
+
spinner(message) {
|
|
149
|
+
return ora({
|
|
150
|
+
text: message,
|
|
151
|
+
isSilent: this.options.json
|
|
152
|
+
}).start();
|
|
153
|
+
}
|
|
154
|
+
// Blank line
|
|
155
|
+
newLine() {
|
|
156
|
+
if (this.options.json) return;
|
|
157
|
+
console.log();
|
|
158
|
+
}
|
|
159
|
+
// Horizontal rule
|
|
160
|
+
hr() {
|
|
161
|
+
if (this.options.json) return;
|
|
162
|
+
console.log(pc.dim("\u2500".repeat(50)));
|
|
163
|
+
}
|
|
164
|
+
// Alias for hr
|
|
165
|
+
divider() {
|
|
166
|
+
this.hr();
|
|
167
|
+
}
|
|
168
|
+
// Code block
|
|
169
|
+
code(text, language) {
|
|
170
|
+
if (this.options.json) {
|
|
171
|
+
this.json({ code: text, language });
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
console.log(pc.dim(`\`\`\`${language ?? ""}`));
|
|
175
|
+
console.log(text);
|
|
176
|
+
console.log(pc.dim("```"));
|
|
177
|
+
}
|
|
178
|
+
// Highlight text
|
|
179
|
+
highlight(text) {
|
|
180
|
+
return pc.cyan(text);
|
|
181
|
+
}
|
|
182
|
+
// Dim text
|
|
183
|
+
dim(text) {
|
|
184
|
+
return pc.dim(text);
|
|
185
|
+
}
|
|
186
|
+
// Bold text
|
|
187
|
+
bold(text) {
|
|
188
|
+
return pc.bold(text);
|
|
189
|
+
}
|
|
190
|
+
// Link (just returns text in terminal)
|
|
191
|
+
link(text, url) {
|
|
192
|
+
return `\x1B]8;;${url}\x07${pc.underline(pc.blue(text))}\x1B]8;;\x07`;
|
|
193
|
+
}
|
|
194
|
+
// Color helpers
|
|
195
|
+
green(text) {
|
|
196
|
+
return pc.green(text);
|
|
197
|
+
}
|
|
198
|
+
red(text) {
|
|
199
|
+
return pc.red(text);
|
|
200
|
+
}
|
|
201
|
+
yellow(text) {
|
|
202
|
+
return pc.yellow(text);
|
|
203
|
+
}
|
|
204
|
+
blue(text) {
|
|
205
|
+
return pc.blue(text);
|
|
206
|
+
}
|
|
207
|
+
cyan(text) {
|
|
208
|
+
return pc.cyan(text);
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
function createOutput(flags) {
|
|
212
|
+
return new OutputFormatter({
|
|
213
|
+
json: flags.json,
|
|
214
|
+
verbose: flags.verbose
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// src/commands/collection/info.ts
|
|
219
|
+
var CollectionInfo = class _CollectionInfo extends Command {
|
|
220
|
+
static description = "Show collection details and list all available tools";
|
|
221
|
+
static examples = [
|
|
222
|
+
"<%= config.bin %> collection info ajax/unsandbox",
|
|
223
|
+
"<%= config.bin %> collection info ajax/unsandbox --json",
|
|
224
|
+
"<%= config.bin %> collection info ajax/unsandbox --verbose"
|
|
225
|
+
];
|
|
226
|
+
static args = {
|
|
227
|
+
collection: Args.string({
|
|
228
|
+
description: "Collection identifier (username/slug)",
|
|
229
|
+
required: true
|
|
230
|
+
})
|
|
231
|
+
};
|
|
232
|
+
static flags = {
|
|
233
|
+
json: Flags.boolean({
|
|
234
|
+
description: "Output in JSON format",
|
|
235
|
+
default: false
|
|
236
|
+
}),
|
|
237
|
+
verbose: Flags.boolean({
|
|
238
|
+
char: "v",
|
|
239
|
+
description: "Show tool input schemas",
|
|
240
|
+
default: false
|
|
241
|
+
})
|
|
242
|
+
};
|
|
243
|
+
async run() {
|
|
244
|
+
const { args, flags } = await this.parse(_CollectionInfo);
|
|
245
|
+
const output = createOutput(flags);
|
|
246
|
+
const parts = args.collection.split("/");
|
|
247
|
+
if (parts.length !== 2) {
|
|
248
|
+
output.error("Invalid collection format. Use: username/slug");
|
|
249
|
+
return;
|
|
250
|
+
}
|
|
251
|
+
const [username, slug] = parts;
|
|
252
|
+
const baseUrl = getApiUrl().replace(/\/api$/, "");
|
|
253
|
+
const mcpUrl = `${baseUrl}/api/mcp/${username}/${slug}/http`;
|
|
254
|
+
const spinner = output.spinner(`Fetching tools from ${args.collection}...`);
|
|
255
|
+
try {
|
|
256
|
+
const apiKey = getApiKey();
|
|
257
|
+
const headers = {
|
|
258
|
+
"Content-Type": "application/json"
|
|
259
|
+
};
|
|
260
|
+
if (apiKey) {
|
|
261
|
+
headers["Authorization"] = `Bearer ${apiKey}`;
|
|
262
|
+
}
|
|
263
|
+
const response = await fetch(mcpUrl, {
|
|
264
|
+
method: "POST",
|
|
265
|
+
headers,
|
|
266
|
+
body: JSON.stringify({
|
|
267
|
+
jsonrpc: "2.0",
|
|
268
|
+
id: 1,
|
|
269
|
+
method: "tools/list"
|
|
270
|
+
})
|
|
271
|
+
});
|
|
272
|
+
if (!response.ok) {
|
|
273
|
+
spinner.fail("Failed to fetch collection");
|
|
274
|
+
output.error(`HTTP ${response.status}: ${await response.text()}`);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
const data = await response.json();
|
|
278
|
+
if (data.error) {
|
|
279
|
+
spinner.fail("Failed to fetch tools");
|
|
280
|
+
output.error(data.error.message);
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
const tools = data.result?.tools || [];
|
|
284
|
+
spinner.stop();
|
|
285
|
+
if (flags.json) {
|
|
286
|
+
output.json({
|
|
287
|
+
collection: args.collection,
|
|
288
|
+
mcpUrl,
|
|
289
|
+
toolCount: tools.length,
|
|
290
|
+
tools: tools.map((t) => ({
|
|
291
|
+
name: t.name,
|
|
292
|
+
description: t.description,
|
|
293
|
+
...flags.verbose ? { inputSchema: t.inputSchema } : {}
|
|
294
|
+
}))
|
|
295
|
+
});
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
output.success(`Collection: ${args.collection}`);
|
|
299
|
+
output.text(`MCP URL: ${mcpUrl}`);
|
|
300
|
+
output.text(`Tools: ${tools.length}`);
|
|
301
|
+
output.divider();
|
|
302
|
+
if (tools.length === 0) {
|
|
303
|
+
output.info("No tools in this collection");
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
output.table(
|
|
307
|
+
tools.map((tool) => ({
|
|
308
|
+
name: tool.name,
|
|
309
|
+
description: truncate(tool.description, 60)
|
|
310
|
+
})),
|
|
311
|
+
[
|
|
312
|
+
{ key: "name", header: "Tool Name", width: 40 },
|
|
313
|
+
{ key: "description", header: "Description", width: 60 }
|
|
314
|
+
]
|
|
315
|
+
);
|
|
316
|
+
if (flags.verbose) {
|
|
317
|
+
output.newLine();
|
|
318
|
+
output.divider();
|
|
319
|
+
output.text("Tool Details:");
|
|
320
|
+
output.newLine();
|
|
321
|
+
for (const tool of tools) {
|
|
322
|
+
output.text(`${output.bold(tool.name)}`);
|
|
323
|
+
output.text(` ${tool.description}`);
|
|
324
|
+
if (tool.inputSchema?.properties) {
|
|
325
|
+
const props = tool.inputSchema.properties;
|
|
326
|
+
const required = tool.inputSchema.required || [];
|
|
327
|
+
output.text(" Parameters:");
|
|
328
|
+
for (const [name, schema] of Object.entries(props)) {
|
|
329
|
+
const req = required.includes(name) ? " (required)" : "";
|
|
330
|
+
output.text(` - ${name}: ${schema.type}${req}`);
|
|
331
|
+
if (schema.description) {
|
|
332
|
+
output.text(` ${output.dim(schema.description)}`);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
output.newLine();
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
output.newLine();
|
|
340
|
+
output.text(output.dim("Usage example:"));
|
|
341
|
+
const exampleTool = tools[0]?.name || "toolName";
|
|
342
|
+
output.text(
|
|
343
|
+
output.dim(` tpm run -c ${args.collection} -t ${exampleTool} --args '{}'`)
|
|
344
|
+
);
|
|
345
|
+
} catch (error) {
|
|
346
|
+
spinner.fail("Failed to fetch collection");
|
|
347
|
+
output.error(error instanceof Error ? error.message : "Unknown error");
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
};
|
|
351
|
+
function truncate(str, maxLen) {
|
|
352
|
+
if (str.length <= maxLen) return str;
|
|
353
|
+
return str.slice(0, maxLen - 3) + "...";
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
export { CollectionInfo as default };
|
|
357
|
+
//# sourceMappingURL=info.js.map
|
|
358
|
+
//# sourceMappingURL=info.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/lib/config.ts","../../../src/lib/output.ts","../../../src/commands/collection/info.ts"],"names":[],"mappings":"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","file":"info.js","sourcesContent":["import * as fs from 'node:fs';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport Conf from 'conf';\n\nexport interface TpmConfig {\n apiUrl?: string;\n defaultOutput?: 'human' | 'json';\n verbose?: boolean;\n analytics?: boolean;\n env?: Record<string, string>;\n}\n\nexport interface TpmCredentials {\n apiKey?: string;\n refreshToken?: string;\n expiresAt?: string;\n}\n\nconst CONFIG_DIR = path.join(os.homedir(), '.tpmjs');\nconst CREDENTIALS_FILE = path.join(CONFIG_DIR, 'credentials.json');\nconst HISTORY_DIR = path.join(CONFIG_DIR, 'history');\n\n// Ensure config directory exists\nfunction ensureConfigDir(): void {\n if (!fs.existsSync(CONFIG_DIR)) {\n fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });\n }\n}\n\n// Config store using Conf\nconst configStore = new Conf<TpmConfig>({\n projectName: 'tpmjs',\n cwd: CONFIG_DIR,\n configName: 'config',\n defaults: {\n apiUrl: 'https://tpmjs.com/api',\n defaultOutput: 'human',\n verbose: false,\n analytics: false,\n },\n});\n\nexport function getConfig(): TpmConfig {\n return configStore.store;\n}\n\nexport function setConfig(config: Partial<TpmConfig>): void {\n for (const [key, value] of Object.entries(config)) {\n if (value !== undefined) {\n configStore.set(key, value);\n }\n }\n}\n\nexport function getConfigValue<K extends keyof TpmConfig>(key: K): TpmConfig[K] {\n return configStore.get(key);\n}\n\nexport function setConfigValue<K extends keyof TpmConfig>(key: K, value: TpmConfig[K]): void {\n configStore.set(key, value);\n}\n\nexport function resetConfig(): void {\n configStore.clear();\n}\n\n// Credentials management with secure file permissions\nexport function loadCredentials(): TpmCredentials | null {\n ensureConfigDir();\n\n if (!fs.existsSync(CREDENTIALS_FILE)) {\n return null;\n }\n\n try {\n const content = fs.readFileSync(CREDENTIALS_FILE, 'utf-8');\n return JSON.parse(content) as TpmCredentials;\n } catch {\n return null;\n }\n}\n\nexport function saveCredentials(credentials: TpmCredentials): void {\n ensureConfigDir();\n\n const content = JSON.stringify(credentials, null, 2);\n fs.writeFileSync(CREDENTIALS_FILE, content, { mode: 0o600 });\n}\n\nexport function deleteCredentials(): void {\n if (fs.existsSync(CREDENTIALS_FILE)) {\n fs.unlinkSync(CREDENTIALS_FILE);\n }\n}\n\nexport function hasCredentials(): boolean {\n const creds = loadCredentials();\n return creds !== null && !!creds.apiKey;\n}\n\n// Get API key from multiple sources (priority order)\nexport function getApiKey(): string | undefined {\n // 1. Environment variable\n if (process.env.TPMJS_API_KEY) {\n return process.env.TPMJS_API_KEY;\n }\n\n // 2. Credentials file\n const creds = loadCredentials();\n if (creds?.apiKey) {\n return creds.apiKey;\n }\n\n return undefined;\n}\n\n// Get API URL\nexport function getApiUrl(): string {\n return process.env.TPMJS_API_URL ?? getConfigValue('apiUrl') ?? 'https://tpmjs.com/api';\n}\n\n// History directory for conversation caching\nexport function getHistoryDir(): string {\n if (!fs.existsSync(HISTORY_DIR)) {\n fs.mkdirSync(HISTORY_DIR, { recursive: true, mode: 0o700 });\n }\n return HISTORY_DIR;\n}\n\n// Config directory path\nexport function getConfigDir(): string {\n ensureConfigDir();\n return CONFIG_DIR;\n}\n","import Table from 'cli-table3';\nimport ora, { type Ora } from 'ora';\nimport pc from 'picocolors';\n\nexport interface OutputOptions {\n json?: boolean;\n verbose?: boolean;\n noColor?: boolean;\n}\n\nexport class OutputFormatter {\n private options: OutputOptions;\n\n constructor(options: OutputOptions = {}) {\n this.options = options;\n }\n\n // Output as JSON\n json(data: unknown): void {\n console.log(JSON.stringify(data, null, 2));\n }\n\n // Output a table\n table<T extends Record<string, unknown>>(\n data: T[],\n columns: { key: keyof T; header: string; width?: number }[]\n ): void {\n if (this.options.json) {\n this.json(data);\n return;\n }\n\n const table = new Table({\n head: columns.map((col) => pc.bold(col.header)),\n colWidths: columns.map((col) => col.width ?? null),\n style: {\n head: [],\n border: [],\n },\n });\n\n for (const row of data) {\n table.push(columns.map((col) => String(row[col.key] ?? '')));\n }\n\n console.log(table.toString());\n }\n\n // Success message\n success(message: string): void {\n if (this.options.json) return;\n console.log(pc.green('✓'), message);\n }\n\n // Error message\n error(message: string, details?: string): void {\n if (this.options.json) {\n this.json({ error: message, details });\n return;\n }\n console.error(pc.red('✗'), message);\n if (details && this.options.verbose) {\n console.error(pc.dim(details));\n }\n }\n\n // Warning message\n warning(message: string): void {\n if (this.options.json) return;\n console.log(pc.yellow('⚠'), message);\n }\n\n // Info message\n info(message: string): void {\n if (this.options.json) return;\n console.log(pc.blue('ℹ'), message);\n }\n\n // Debug message (only in verbose mode)\n debug(message: string): void {\n if (this.options.json) return;\n if (this.options.verbose) {\n console.log(pc.dim(`[debug] ${message}`));\n }\n }\n\n // Plain text output\n text(message: string): void {\n if (this.options.json) return;\n console.log(message);\n }\n\n // Heading\n heading(text: string): void {\n if (this.options.json) return;\n console.log();\n console.log(pc.bold(pc.underline(text)));\n console.log();\n }\n\n // Subheading\n subheading(text: string): void {\n if (this.options.json) return;\n console.log(pc.bold(text));\n }\n\n // Key-value pair\n keyValue(key: string, value: string | number | boolean | undefined): void {\n if (this.options.json) return;\n console.log(`${pc.dim(`${key}:`)} ${value ?? pc.dim('(not set)')}`);\n }\n\n // List item\n listItem(text: string, indent = 0): void {\n if (this.options.json) return;\n const prefix = `${' '.repeat(indent)}•`;\n console.log(`${prefix} ${text}`);\n }\n\n // Spinner\n spinner(message: string): Ora {\n return ora({\n text: message,\n isSilent: this.options.json,\n }).start();\n }\n\n // Blank line\n newLine(): void {\n if (this.options.json) return;\n console.log();\n }\n\n // Horizontal rule\n hr(): void {\n if (this.options.json) return;\n console.log(pc.dim('─'.repeat(50)));\n }\n\n // Alias for hr\n divider(): void {\n this.hr();\n }\n\n // Code block\n code(text: string, language?: string): void {\n if (this.options.json) {\n this.json({ code: text, language });\n return;\n }\n console.log(pc.dim(`\\`\\`\\`${language ?? ''}`));\n console.log(text);\n console.log(pc.dim('```'));\n }\n\n // Highlight text\n highlight(text: string): string {\n return pc.cyan(text);\n }\n\n // Dim text\n dim(text: string): string {\n return pc.dim(text);\n }\n\n // Bold text\n bold(text: string): string {\n return pc.bold(text);\n }\n\n // Link (just returns text in terminal)\n link(text: string, url: string): string {\n // OSC 8 hyperlink support for modern terminals\n return `\\x1b]8;;${url}\\x07${pc.underline(pc.blue(text))}\\x1b]8;;\\x07`;\n }\n\n // Color helpers\n green(text: string): string {\n return pc.green(text);\n }\n\n red(text: string): string {\n return pc.red(text);\n }\n\n yellow(text: string): string {\n return pc.yellow(text);\n }\n\n blue(text: string): string {\n return pc.blue(text);\n }\n\n cyan(text: string): string {\n return pc.cyan(text);\n }\n}\n\n// Convenience function to create formatter from command flags\nexport function createOutput(flags: { json?: boolean; verbose?: boolean }): OutputFormatter {\n return new OutputFormatter({\n json: flags.json,\n verbose: flags.verbose,\n });\n}\n","import { Args, Command, Flags } from '@oclif/core';\n\nimport { getApiKey, getApiUrl } from '../../lib/config.js';\nimport { createOutput } from '../../lib/output.js';\n\ninterface McpTool {\n name: string;\n description: string;\n inputSchema?: {\n type: string;\n required?: string[];\n properties?: Record<string, { type: string; description?: string }>;\n };\n}\n\ninterface McpListToolsResponse {\n jsonrpc: '2.0';\n id: number;\n result?: {\n tools: McpTool[];\n };\n error?: {\n code: number;\n message: string;\n };\n}\n\nexport default class CollectionInfo extends Command {\n static description = 'Show collection details and list all available tools';\n\n static examples = [\n '<%= config.bin %> collection info ajax/unsandbox',\n '<%= config.bin %> collection info ajax/unsandbox --json',\n '<%= config.bin %> collection info ajax/unsandbox --verbose',\n ];\n\n static args = {\n collection: Args.string({\n description: 'Collection identifier (username/slug)',\n required: true,\n }),\n };\n\n static flags = {\n json: Flags.boolean({\n description: 'Output in JSON format',\n default: false,\n }),\n verbose: Flags.boolean({\n char: 'v',\n description: 'Show tool input schemas',\n default: false,\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(CollectionInfo);\n const output = createOutput(flags);\n\n // Parse collection identifier\n const parts = args.collection.split('/');\n if (parts.length !== 2) {\n output.error('Invalid collection format. Use: username/slug');\n return;\n }\n\n const [username, slug] = parts;\n const baseUrl = getApiUrl().replace(/\\/api$/, '');\n const mcpUrl = `${baseUrl}/api/mcp/${username}/${slug}/http`;\n\n const spinner = output.spinner(`Fetching tools from ${args.collection}...`);\n\n try {\n // Get API key for authentication\n const apiKey = getApiKey();\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (apiKey) {\n headers['Authorization'] = `Bearer ${apiKey}`;\n }\n\n // Call MCP tools/list to get all tools\n const response = await fetch(mcpUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify({\n jsonrpc: '2.0',\n id: 1,\n method: 'tools/list',\n }),\n });\n\n if (!response.ok) {\n spinner.fail('Failed to fetch collection');\n output.error(`HTTP ${response.status}: ${await response.text()}`);\n return;\n }\n\n const data = (await response.json()) as McpListToolsResponse;\n\n if (data.error) {\n spinner.fail('Failed to fetch tools');\n output.error(data.error.message);\n return;\n }\n\n const tools = data.result?.tools || [];\n spinner.stop();\n\n if (flags.json) {\n output.json({\n collection: args.collection,\n mcpUrl,\n toolCount: tools.length,\n tools: tools.map((t) => ({\n name: t.name,\n description: t.description,\n ...(flags.verbose ? { inputSchema: t.inputSchema } : {}),\n })),\n });\n return;\n }\n\n // Display collection info\n output.success(`Collection: ${args.collection}`);\n output.text(`MCP URL: ${mcpUrl}`);\n output.text(`Tools: ${tools.length}`);\n output.divider();\n\n if (tools.length === 0) {\n output.info('No tools in this collection');\n return;\n }\n\n // Display tools table\n output.table(\n tools.map((tool) => ({\n name: tool.name,\n description: truncate(tool.description, 60),\n })),\n [\n { key: 'name', header: 'Tool Name', width: 40 },\n { key: 'description', header: 'Description', width: 60 },\n ]\n );\n\n // Show verbose tool details\n if (flags.verbose) {\n output.newLine();\n output.divider();\n output.text('Tool Details:');\n output.newLine();\n\n for (const tool of tools) {\n output.text(`${output.bold(tool.name)}`);\n output.text(` ${tool.description}`);\n\n if (tool.inputSchema?.properties) {\n const props = tool.inputSchema.properties;\n const required = tool.inputSchema.required || [];\n output.text(' Parameters:');\n for (const [name, schema] of Object.entries(props)) {\n const req = required.includes(name) ? ' (required)' : '';\n output.text(` - ${name}: ${schema.type}${req}`);\n if (schema.description) {\n output.text(` ${output.dim(schema.description)}`);\n }\n }\n }\n output.newLine();\n }\n }\n\n // Usage hints\n output.newLine();\n output.text(output.dim('Usage example:'));\n const exampleTool = tools[0]?.name || 'toolName';\n output.text(\n output.dim(` tpm run -c ${args.collection} -t ${exampleTool} --args '{}'`)\n );\n } catch (error) {\n spinner.fail('Failed to fetch collection');\n output.error(error instanceof Error ? error.message : 'Unknown error');\n }\n }\n}\n\nfunction truncate(str: string, maxLen: number): string {\n if (str.length <= maxLen) return str;\n return str.slice(0, maxLen - 3) + '...';\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { Command, Flags } from '@oclif/core';
|
|
2
|
-
import Conf from 'conf';
|
|
3
2
|
import * as fs from 'fs';
|
|
4
3
|
import * as os from 'os';
|
|
5
4
|
import * as path from 'path';
|
|
5
|
+
import Conf from 'conf';
|
|
6
6
|
import Table from 'cli-table3';
|
|
7
7
|
import ora from 'ora';
|
|
8
8
|
import pc from 'picocolors';
|
|
@@ -73,7 +73,7 @@ var TpmClient = class {
|
|
|
73
73
|
...options.headers
|
|
74
74
|
};
|
|
75
75
|
if (this.apiKey) {
|
|
76
|
-
headers
|
|
76
|
+
headers.Authorization = `Bearer ${this.apiKey}`;
|
|
77
77
|
}
|
|
78
78
|
const controller = new AbortController();
|
|
79
79
|
const timeoutId = setTimeout(() => controller.abort(), this.timeout);
|
|
@@ -155,7 +155,7 @@ var TpmClient = class {
|
|
|
155
155
|
Accept: "text/event-stream"
|
|
156
156
|
};
|
|
157
157
|
if (this.apiKey) {
|
|
158
|
-
headers
|
|
158
|
+
headers.Authorization = `Bearer ${this.apiKey}`;
|
|
159
159
|
}
|
|
160
160
|
const response = await fetch(url, {
|
|
161
161
|
method: "POST",
|
|
@@ -429,12 +429,12 @@ var OutputFormatter = class {
|
|
|
429
429
|
// Key-value pair
|
|
430
430
|
keyValue(key, value) {
|
|
431
431
|
if (this.options.json) return;
|
|
432
|
-
console.log(`${pc.dim(key
|
|
432
|
+
console.log(`${pc.dim(`${key}:`)} ${value ?? pc.dim("(not set)")}`);
|
|
433
433
|
}
|
|
434
434
|
// List item
|
|
435
435
|
listItem(text, indent = 0) {
|
|
436
436
|
if (this.options.json) return;
|
|
437
|
-
const prefix = " ".repeat(indent)
|
|
437
|
+
const prefix = `${" ".repeat(indent)}\u2022`;
|
|
438
438
|
console.log(`${prefix} ${text}`);
|
|
439
439
|
}
|
|
440
440
|
// Spinner
|
|
@@ -464,7 +464,7 @@ var OutputFormatter = class {
|
|
|
464
464
|
this.json({ code: text, language });
|
|
465
465
|
return;
|
|
466
466
|
}
|
|
467
|
-
console.log(pc.dim(
|
|
467
|
+
console.log(pc.dim(`\`\`\`${language ?? ""}`));
|
|
468
468
|
console.log(text);
|
|
469
469
|
console.log(pc.dim("```"));
|
|
470
470
|
}
|