@tpmjs/cli 0.1.3 → 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 +75 -9
- package/dist/commands/agent/chat.js.map +1 -1
- package/dist/commands/agent/create.js +74 -8
- package/dist/commands/agent/create.js.map +1 -1
- package/dist/commands/agent/delete.js +77 -9
- package/dist/commands/agent/delete.js.map +1 -1
- package/dist/commands/agent/list.js +74 -8
- package/dist/commands/agent/list.js.map +1 -1
- package/dist/commands/agent/update.js +74 -8
- package/dist/commands/agent/update.js.map +1 -1
- package/dist/commands/auth/login.js +96 -19
- package/dist/commands/auth/login.js.map +1 -1
- package/dist/commands/auth/logout.js +20 -4
- package/dist/commands/auth/logout.js.map +1 -1
- package/dist/commands/auth/status.js +80 -11
- package/dist/commands/auth/status.js.map +1 -1
- package/dist/commands/auth/whoami.js +74 -8
- package/dist/commands/auth/whoami.js.map +1 -1
- package/dist/commands/collection/add.js +74 -8
- package/dist/commands/collection/add.js.map +1 -1
- package/dist/commands/collection/create.js +74 -8
- package/dist/commands/collection/create.js.map +1 -1
- package/dist/commands/collection/delete.js +75 -9
- package/dist/commands/collection/delete.js.map +1 -1
- package/dist/commands/collection/import.js +75 -9
- 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 +74 -8
- package/dist/commands/collection/list.js.map +1 -1
- package/dist/commands/collection/remove.js +75 -11
- package/dist/commands/collection/remove.js.map +1 -1
- package/dist/commands/collection/update.js +74 -8
- package/dist/commands/collection/update.js.map +1 -1
- package/dist/commands/doctor.js +75 -9
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/mcp/config.js +20 -4
- package/dist/commands/mcp/config.js.map +1 -1
- package/dist/commands/mcp/serve.js +75 -9
- package/dist/commands/mcp/serve.js.map +1 -1
- package/dist/commands/playground.js +75 -9
- package/dist/commands/playground.js.map +1 -1
- package/dist/commands/publish/check.js +79 -13
- package/dist/commands/publish/check.js.map +1 -1
- package/dist/commands/publish/preview.js +20 -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.d.ts +19 -0
- package/dist/commands/scenario/generate.js +633 -0
- package/dist/commands/scenario/generate.js.map +1 -0
- package/dist/commands/scenario/info.d.ts +18 -0
- package/dist/commands/scenario/info.js +636 -0
- package/dist/commands/scenario/info.js.map +1 -0
- package/dist/commands/scenario/list.d.ts +20 -0
- package/dist/commands/scenario/list.js +652 -0
- package/dist/commands/scenario/list.js.map +1 -0
- package/dist/commands/scenario/run.d.ts +18 -0
- package/dist/commands/scenario/run.js +663 -0
- package/dist/commands/scenario/run.js.map +1 -0
- package/dist/commands/scenario/test.d.ts +17 -0
- package/dist/commands/scenario/test.js +620 -0
- package/dist/commands/scenario/test.js.map +1 -0
- package/dist/commands/tool/execute.js +77 -9
- package/dist/commands/tool/execute.js.map +1 -1
- package/dist/commands/tool/info.js +84 -11
- package/dist/commands/tool/info.js.map +1 -1
- package/dist/commands/tool/init.js +23 -13
- package/dist/commands/tool/init.js.map +1 -1
- package/dist/commands/tool/search.js +75 -13
- package/dist/commands/tool/search.js.map +1 -1
- package/dist/commands/tool/trending.js +74 -8
- package/dist/commands/tool/trending.js.map +1 -1
- package/dist/commands/tool/validate.js +83 -11
- package/dist/commands/tool/validate.js.map +1 -1
- package/dist/commands/update.js +20 -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.d.ts +80 -0
- package/dist/index.js +74 -8
- package/dist/index.js.map +1 -1
- package/oclif.manifest.json +435 -1
- package/package.json +13 -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);
|
|
@@ -116,7 +116,9 @@ var TpmClient = class {
|
|
|
116
116
|
return this.request(endpoint);
|
|
117
117
|
}
|
|
118
118
|
async getTool(packageName, toolName) {
|
|
119
|
-
return this.request(
|
|
119
|
+
return this.request(
|
|
120
|
+
`/tools/${encodeURIComponent(packageName)}/${encodeURIComponent(toolName)}`
|
|
121
|
+
);
|
|
120
122
|
}
|
|
121
123
|
async getToolBySlug(slug) {
|
|
122
124
|
const searchResult = await this.searchTools({ query: slug, limit: 1 });
|
|
@@ -150,10 +152,10 @@ var TpmClient = class {
|
|
|
150
152
|
const url = `${this.baseUrl}/tools/${encodeURIComponent(slug)}/execute`;
|
|
151
153
|
const headers = {
|
|
152
154
|
"Content-Type": "application/json",
|
|
153
|
-
|
|
155
|
+
Accept: "text/event-stream"
|
|
154
156
|
};
|
|
155
157
|
if (this.apiKey) {
|
|
156
|
-
headers
|
|
158
|
+
headers.Authorization = `Bearer ${this.apiKey}`;
|
|
157
159
|
}
|
|
158
160
|
const response = await fetch(url, {
|
|
159
161
|
method: "POST",
|
|
@@ -278,6 +280,54 @@ var TpmClient = class {
|
|
|
278
280
|
async listApiKeys() {
|
|
279
281
|
return this.request("/user/tpmjs-api-keys");
|
|
280
282
|
}
|
|
283
|
+
// Scenarios
|
|
284
|
+
async listScenarios(options = {}) {
|
|
285
|
+
const params = new URLSearchParams();
|
|
286
|
+
if (options.limit) params.set("limit", String(options.limit));
|
|
287
|
+
if (options.offset) params.set("offset", String(options.offset));
|
|
288
|
+
if (options.collectionId) params.set("collectionId", options.collectionId);
|
|
289
|
+
if (options.tags) params.set("tags", options.tags);
|
|
290
|
+
if (options.sortBy) params.set("sortBy", options.sortBy);
|
|
291
|
+
const queryString = params.toString();
|
|
292
|
+
const endpoint = queryString ? `/scenarios?${queryString}` : "/scenarios";
|
|
293
|
+
return this.request(endpoint);
|
|
294
|
+
}
|
|
295
|
+
async listCollectionScenarios(collectionId, options = {}) {
|
|
296
|
+
const params = new URLSearchParams();
|
|
297
|
+
if (options.limit) params.set("limit", String(options.limit));
|
|
298
|
+
if (options.offset) params.set("offset", String(options.offset));
|
|
299
|
+
const queryString = params.toString();
|
|
300
|
+
const endpoint = queryString ? `/collections/${collectionId}/scenarios?${queryString}` : `/collections/${collectionId}/scenarios`;
|
|
301
|
+
return this.request(endpoint);
|
|
302
|
+
}
|
|
303
|
+
async getScenario(id) {
|
|
304
|
+
return this.request(`/scenarios/${id}`);
|
|
305
|
+
}
|
|
306
|
+
async createScenario(input) {
|
|
307
|
+
return this.request("/scenarios", {
|
|
308
|
+
method: "POST",
|
|
309
|
+
body: JSON.stringify(input)
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
async generateScenarios(collectionId, input = {}) {
|
|
313
|
+
return this.request(`/collections/${collectionId}/scenarios/generate`, {
|
|
314
|
+
method: "POST",
|
|
315
|
+
body: JSON.stringify(input)
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
async runScenario(scenarioId) {
|
|
319
|
+
return this.request(`/scenarios/${scenarioId}/run`, {
|
|
320
|
+
method: "POST"
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
async getScenarioRuns(scenarioId, options = {}) {
|
|
324
|
+
const params = new URLSearchParams();
|
|
325
|
+
if (options.limit) params.set("limit", String(options.limit));
|
|
326
|
+
if (options.offset) params.set("offset", String(options.offset));
|
|
327
|
+
const queryString = params.toString();
|
|
328
|
+
const endpoint = queryString ? `/scenarios/${scenarioId}/runs?${queryString}` : `/scenarios/${scenarioId}/runs`;
|
|
329
|
+
return this.request(endpoint);
|
|
330
|
+
}
|
|
281
331
|
// Check if authenticated
|
|
282
332
|
isAuthenticated() {
|
|
283
333
|
return !!this.apiKey;
|
|
@@ -379,12 +429,12 @@ var OutputFormatter = class {
|
|
|
379
429
|
// Key-value pair
|
|
380
430
|
keyValue(key, value) {
|
|
381
431
|
if (this.options.json) return;
|
|
382
|
-
console.log(`${pc.dim(key
|
|
432
|
+
console.log(`${pc.dim(`${key}:`)} ${value ?? pc.dim("(not set)")}`);
|
|
383
433
|
}
|
|
384
434
|
// List item
|
|
385
435
|
listItem(text, indent = 0) {
|
|
386
436
|
if (this.options.json) return;
|
|
387
|
-
const prefix = " ".repeat(indent)
|
|
437
|
+
const prefix = `${" ".repeat(indent)}\u2022`;
|
|
388
438
|
console.log(`${prefix} ${text}`);
|
|
389
439
|
}
|
|
390
440
|
// Spinner
|
|
@@ -414,7 +464,7 @@ var OutputFormatter = class {
|
|
|
414
464
|
this.json({ code: text, language });
|
|
415
465
|
return;
|
|
416
466
|
}
|
|
417
|
-
console.log(pc.dim(
|
|
467
|
+
console.log(pc.dim(`\`\`\`${language ?? ""}`));
|
|
418
468
|
console.log(text);
|
|
419
469
|
console.log(pc.dim("```"));
|
|
420
470
|
}
|
|
@@ -434,6 +484,22 @@ var OutputFormatter = class {
|
|
|
434
484
|
link(text, url) {
|
|
435
485
|
return `\x1B]8;;${url}\x07${pc.underline(pc.blue(text))}\x1B]8;;\x07`;
|
|
436
486
|
}
|
|
487
|
+
// Color helpers
|
|
488
|
+
green(text) {
|
|
489
|
+
return pc.green(text);
|
|
490
|
+
}
|
|
491
|
+
red(text) {
|
|
492
|
+
return pc.red(text);
|
|
493
|
+
}
|
|
494
|
+
yellow(text) {
|
|
495
|
+
return pc.yellow(text);
|
|
496
|
+
}
|
|
497
|
+
blue(text) {
|
|
498
|
+
return pc.blue(text);
|
|
499
|
+
}
|
|
500
|
+
cyan(text) {
|
|
501
|
+
return pc.cyan(text);
|
|
502
|
+
}
|
|
437
503
|
};
|
|
438
504
|
function createOutput(flags) {
|
|
439
505
|
return new OutputFormatter({
|