tiny-tool-submitter 1.0.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.
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,450 @@
1
+ #!/usr/bin/env node
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ import { execSync } from "child_process";
5
+ import { CopilotClient } from "@github/copilot-sdk";
6
+ import { select, confirm, input } from "@inquirer/prompts";
7
+ import { findReadme, detectGitHubUrl, detectLicense, detectLanguage, detectGitUserName, detectGitHubUsername, } from "./repo-detector.js";
8
+ import { generateMetadata } from "./metadata-generator.js";
9
+ import { buildIssueUrl } from "./issue-url-builder.js";
10
+ // --- Parse CLI flags ---
11
+ const args = process.argv.slice(2);
12
+ const flagArgs = args.filter((a) => a.startsWith("-"));
13
+ const positionalArgs = args.filter((a) => !a.startsWith("-"));
14
+ const headless = flagArgs.includes("--headless");
15
+ const verbose = flagArgs.includes("--verbose");
16
+ function getFlagValue(flag) {
17
+ const idx = args.indexOf(flag);
18
+ return idx >= 0 && idx < args.length - 1 ? args[idx + 1] : undefined;
19
+ }
20
+ const flagReadmePath = getFlagValue("--readme");
21
+ const flagModelName = getFlagValue("--model");
22
+ const flagCliPath = getFlagValue("--cli-path");
23
+ console.log("\x1b[36m╔══════════════════════════════════════════════════════════════╗");
24
+ console.log("║ Tiny Tool Town — Submission Helper 🏘️📋 ║");
25
+ console.log("║ Powered by GitHub Copilot SDK (Node.js) ║");
26
+ console.log("╚══════════════════════════════════════════════════════════════╝\x1b[0m");
27
+ console.log();
28
+ // Resolve the repo directory
29
+ const repoDir = positionalArgs.length > 0
30
+ ? path.resolve(positionalArgs[0])
31
+ : process.cwd();
32
+ if (!fs.existsSync(repoDir) || !fs.statSync(repoDir).isDirectory()) {
33
+ console.error(`\x1b[31m❌ Directory not found: ${repoDir}\x1b[0m`);
34
+ process.exit(1);
35
+ }
36
+ console.log(`📂 Repository: ${repoDir}`);
37
+ // --- Step 1: Find README ---
38
+ let readmePath;
39
+ if (flagReadmePath) {
40
+ readmePath = path.resolve(flagReadmePath);
41
+ }
42
+ else {
43
+ const detected = findReadme(repoDir);
44
+ if (detected) {
45
+ console.log(`\x1b[32m📄 Found README: ${path.relative(repoDir, detected)}\x1b[0m`);
46
+ if (headless) {
47
+ readmePath = detected;
48
+ }
49
+ else {
50
+ const useDetected = await confirm({ message: "Use this README?", default: true });
51
+ readmePath = useDetected ? detected : await promptForReadmePath(repoDir);
52
+ }
53
+ }
54
+ else if (!headless) {
55
+ console.log("\x1b[33m📄 No README found automatically. Let's pick one.\x1b[0m");
56
+ readmePath = await promptForReadmePath(repoDir);
57
+ }
58
+ else {
59
+ console.error("\x1b[31m❌ No README found and running in headless mode. Use --readme <path>.\x1b[0m");
60
+ process.exit(1);
61
+ }
62
+ }
63
+ if (!fs.existsSync(readmePath)) {
64
+ console.error(`\x1b[31m❌ README not found: ${readmePath}\x1b[0m`);
65
+ process.exit(1);
66
+ }
67
+ let readmeContent = fs.readFileSync(readmePath, "utf-8");
68
+ if (readmeContent.length > 4000) {
69
+ readmeContent = readmeContent.slice(0, 4000) + "\n\n[truncated]";
70
+ }
71
+ console.log(`📏 README length: ${readmeContent.length} chars`);
72
+ // --- Step 2: Detect repo metadata ---
73
+ console.log("\n🔍 Detecting repository metadata...");
74
+ const githubUrl = detectGitHubUrl(repoDir);
75
+ const license = detectLicense(repoDir);
76
+ const language = detectLanguage(repoDir);
77
+ const authorName = detectGitUserName(repoDir);
78
+ const authorGitHub = detectGitHubUsername(githubUrl);
79
+ let repoName;
80
+ if (githubUrl) {
81
+ try {
82
+ const url = new URL(githubUrl);
83
+ const segments = url.pathname.replace(/^\//, "").split("/");
84
+ repoName = segments[segments.length - 1] || path.basename(repoDir);
85
+ }
86
+ catch {
87
+ repoName = path.basename(repoDir);
88
+ }
89
+ }
90
+ else {
91
+ repoName = path.basename(repoDir);
92
+ }
93
+ console.log("\x1b[90m");
94
+ if (githubUrl)
95
+ console.log(` GitHub URL: ${githubUrl}`);
96
+ if (license)
97
+ console.log(` License: ${license}`);
98
+ if (language)
99
+ console.log(` Language: ${language}`);
100
+ if (authorName)
101
+ console.log(` Author: ${authorName}`);
102
+ if (authorGitHub)
103
+ console.log(` Username: ${authorGitHub}`);
104
+ console.log("\x1b[0m");
105
+ // --- Step 3: Use Copilot to generate metadata ---
106
+ console.log("🤖 Starting Copilot to analyze your README...");
107
+ let client = null;
108
+ try {
109
+ const cliPath = flagCliPath || resolveCliPath();
110
+ if (verbose) {
111
+ console.log(`\x1b[90m Copilot CLI path: ${cliPath}\x1b[0m`);
112
+ }
113
+ // Check CLI availability
114
+ try {
115
+ execSync(`${cliPath} --version`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
116
+ }
117
+ catch {
118
+ console.error(`\x1b[31m❌ Failed to execute GitHub Copilot CLI at '${cliPath}'.\x1b[0m`);
119
+ console.log(" Install Copilot CLI and ensure `copilot` is available on your PATH.");
120
+ process.exit(1);
121
+ }
122
+ client = new CopilotClient({
123
+ cliPath,
124
+ autoStart: false,
125
+ });
126
+ try {
127
+ await client.start();
128
+ }
129
+ catch (ex) {
130
+ const msg = ex instanceof Error ? ex.message : String(ex);
131
+ if (msg.includes("not found") || msg.includes("No such file")) {
132
+ console.error(`\x1b[31m❌ GitHub Copilot CLI was not found at '${cliPath}'.\x1b[0m`);
133
+ console.log(" Install Copilot CLI and ensure `copilot` is available on your PATH.");
134
+ }
135
+ else {
136
+ console.error(`\x1b[31m❌ Could not connect to GitHub Copilot CLI.\x1b[0m`);
137
+ console.log(" Try: `copilot --version` and `copilot auth status`.");
138
+ if (verbose)
139
+ console.log(` Error: ${msg}`);
140
+ }
141
+ process.exit(1);
142
+ }
143
+ console.log("\x1b[32m✅ Copilot client started\x1b[0m");
144
+ // Model selection
145
+ let selectedModel;
146
+ if (flagModelName) {
147
+ selectedModel = flagModelName;
148
+ }
149
+ else if (headless) {
150
+ selectedModel = "gpt-4.1";
151
+ }
152
+ else {
153
+ console.log("\x1b[90m Fetching available models...\x1b[0m");
154
+ try {
155
+ const models = await client.listModels();
156
+ if (models && models.length > 0) {
157
+ const defaultModel = models.find((m) => m.id.toLowerCase() === "gpt-4.1") || models[0];
158
+ const choices = models.map((m) => ({
159
+ name: m.id === defaultModel.id ? `${m.name} (recommended)` : m.name,
160
+ value: m.id,
161
+ }));
162
+ // Move recommended to top
163
+ choices.sort((a, b) => a.name.includes("(recommended)") ? -1 : b.name.includes("(recommended)") ? 1 : 0);
164
+ selectedModel = await select({
165
+ message: "🤖 Select a model",
166
+ choices,
167
+ });
168
+ }
169
+ else {
170
+ selectedModel = "gpt-4.1";
171
+ }
172
+ }
173
+ catch {
174
+ selectedModel = "gpt-4.1";
175
+ }
176
+ }
177
+ console.log(`🤖 Using model: ${selectedModel}\n`);
178
+ const session = await client.createSession({
179
+ model: selectedModel,
180
+ streaming: true,
181
+ infiniteSessions: { enabled: false },
182
+ });
183
+ console.log("\x1b[90m Analyzing README with AI...\x1b[0m");
184
+ const metadata = await generateMetadata(session, readmeContent, repoName);
185
+ if (!metadata) {
186
+ console.error("\x1b[31m❌ Failed to generate metadata from README.\x1b[0m");
187
+ process.exit(1);
188
+ }
189
+ // Fill in detected values
190
+ metadata.githubUrl = githubUrl ?? "";
191
+ metadata.language = language ?? undefined;
192
+ metadata.license = license ?? undefined;
193
+ metadata.author = authorName ?? "";
194
+ metadata.authorGitHub = authorGitHub ?? "";
195
+ // --- Step 4: Review metadata ---
196
+ console.log("\n\x1b[36m📋 Generated Submission Metadata\x1b[0m");
197
+ printMetadataTable(metadata);
198
+ if (!headless) {
199
+ let editing = true;
200
+ while (editing) {
201
+ const fieldChoice = await select({
202
+ message: "✏️ Edit metadata fields (choose Done to continue)",
203
+ choices: [
204
+ { name: "Done", value: "done" },
205
+ { name: "name", value: "name" },
206
+ { name: "tagline", value: "tagline" },
207
+ { name: "description", value: "description" },
208
+ { name: "github_url", value: "github_url" },
209
+ { name: "website", value: "website" },
210
+ { name: "author", value: "author" },
211
+ { name: "author_github", value: "author_github" },
212
+ { name: "tags", value: "tags" },
213
+ { name: "language", value: "language" },
214
+ { name: "license", value: "license" },
215
+ ],
216
+ });
217
+ if (fieldChoice === "done") {
218
+ editing = false;
219
+ break;
220
+ }
221
+ const currentValue = getFieldValue(metadata, fieldChoice);
222
+ const newValue = await input({
223
+ message: `New value for ${fieldChoice}`,
224
+ default: currentValue,
225
+ });
226
+ setFieldValue(metadata, fieldChoice, newValue.trim());
227
+ console.log(`\x1b[32m✅ Updated ${fieldChoice}\x1b[0m`);
228
+ printMetadataTable(metadata);
229
+ }
230
+ }
231
+ // --- Step 5: Build and open the URL ---
232
+ const issueUrl = buildIssueUrl(metadata);
233
+ console.log("\n\x1b[36m═══════════════════════════════════════════════");
234
+ console.log(" 🚀 Ready to Submit!");
235
+ console.log("═══════════════════════════════════════════════\x1b[0m");
236
+ console.log("\n📋 Open this URL to submit your tool to Tiny Tool Town:\n");
237
+ console.log(`\x1b[32m${issueUrl}\x1b[0m`);
238
+ // Try to open the URL in the default browser
239
+ if (!headless) {
240
+ const openInBrowser = await confirm({ message: "🌐 Open in browser?", default: true });
241
+ if (openInBrowser) {
242
+ openUrl(issueUrl);
243
+ console.log("\x1b[32m✅ Opened in browser!\x1b[0m");
244
+ }
245
+ }
246
+ else {
247
+ openUrl(issueUrl);
248
+ }
249
+ console.log("\n🏘️ Thanks for submitting to Tiny Tool Town!");
250
+ await session.destroy();
251
+ await client.stop();
252
+ process.exit(0);
253
+ }
254
+ catch (ex) {
255
+ if (ex instanceof Error && ex.message.includes("cancelled")) {
256
+ console.log("\n\x1b[33m⚠️ Cancelled by user.\x1b[0m");
257
+ process.exit(0);
258
+ }
259
+ const msg = ex instanceof Error ? ex.message : String(ex);
260
+ console.error(`\n\x1b[31m❌ Fatal error: ${msg}\x1b[0m`);
261
+ process.exit(1);
262
+ }
263
+ finally {
264
+ if (client) {
265
+ try {
266
+ await client.stop();
267
+ }
268
+ catch {
269
+ // ignore
270
+ }
271
+ }
272
+ console.log("\n🛑 Done.");
273
+ }
274
+ // --- Helpers ---
275
+ function printMetadataTable(metadata) {
276
+ const rows = [
277
+ ["Tool Name", metadata.name],
278
+ ["Tagline", metadata.tagline],
279
+ ["Description", metadata.description],
280
+ ["GitHub URL", metadata.githubUrl],
281
+ ["Website", metadata.websiteUrl ?? "(none)"],
282
+ ["Author", metadata.author],
283
+ ["GitHub User", metadata.authorGitHub],
284
+ ["Tags", metadata.tags],
285
+ ["Language", metadata.language ?? "(not detected)"],
286
+ ["License", metadata.license ?? "(not detected)"],
287
+ ];
288
+ console.log("┌──────────────┬──────────────────────────────────────────────────┐");
289
+ for (const [field, value] of rows) {
290
+ const paddedField = field.padEnd(12);
291
+ const truncatedValue = value.length > 48 ? value.slice(0, 45) + "..." : value;
292
+ const paddedValue = truncatedValue.padEnd(48);
293
+ console.log(`│ \x1b[33m${paddedField}\x1b[0m │ ${paddedValue} │`);
294
+ }
295
+ console.log("└──────────────┴──────────────────────────────────────────────────┘");
296
+ }
297
+ function openUrl(url) {
298
+ try {
299
+ const platform = process.platform;
300
+ if (platform === "darwin") {
301
+ execSync(`open "${url}"`, { stdio: "ignore" });
302
+ }
303
+ else if (platform === "win32") {
304
+ execSync(`cmd /c start "" "${url}"`, { stdio: "ignore" });
305
+ }
306
+ else {
307
+ execSync(`xdg-open "${url}"`, { stdio: "ignore" });
308
+ }
309
+ }
310
+ catch {
311
+ // Silently fail — URL is already printed
312
+ }
313
+ }
314
+ async function promptForReadmePath(repoDir) {
315
+ let currentDir = repoDir;
316
+ while (true) {
317
+ const relativeCurrentDir = path.relative(repoDir, currentDir);
318
+ const currentDirDisplay = relativeCurrentDir ? relativeCurrentDir : ".";
319
+ let entries = [];
320
+ try {
321
+ entries = fs.readdirSync(currentDir, { withFileTypes: true });
322
+ }
323
+ catch {
324
+ entries = [];
325
+ }
326
+ const readmeCandidates = entries
327
+ .filter((entry) => entry.isFile() && isReadmeCandidate(entry.name))
328
+ .map((entry) => entry.name)
329
+ .sort((a, b) => a.localeCompare(b));
330
+ const subDirectories = entries
331
+ .filter((entry) => entry.isDirectory() && entry.name !== ".git")
332
+ .map((entry) => entry.name)
333
+ .sort((a, b) => a.localeCompare(b));
334
+ const choices = [
335
+ { name: "✍ Enter full path manually", value: "manual" },
336
+ ...readmeCandidates.map((fileName) => ({
337
+ name: `📄 ${fileName}`,
338
+ value: `file:${fileName}`,
339
+ })),
340
+ ...subDirectories.map((dirName) => ({
341
+ name: `📁 ${dirName}`,
342
+ value: `dir:${dirName}`,
343
+ })),
344
+ ];
345
+ const parentDirectory = path.dirname(currentDir);
346
+ if (parentDirectory !== currentDir) {
347
+ choices.push({ name: "↩ Go up", value: "up" });
348
+ }
349
+ choices.push({ name: "❌ Cancel", value: "cancel" });
350
+ const choice = await select({
351
+ message: `Select README in ${currentDirDisplay} or browse:`,
352
+ choices,
353
+ });
354
+ if (choice === "cancel") {
355
+ throw new Error("README selection cancelled.");
356
+ }
357
+ if (choice === "up") {
358
+ if (parentDirectory !== currentDir) {
359
+ currentDir = parentDirectory;
360
+ }
361
+ continue;
362
+ }
363
+ if (choice === "manual") {
364
+ const selectedPath = await input({
365
+ message: "README path",
366
+ default: path.join(repoDir, "README.md"),
367
+ validate: (val) => fs.existsSync(val) || "README file does not exist",
368
+ });
369
+ return path.resolve(selectedPath);
370
+ }
371
+ if (choice.startsWith("dir:")) {
372
+ const dirName = choice.slice("dir:".length);
373
+ currentDir = path.join(currentDir, dirName);
374
+ continue;
375
+ }
376
+ if (choice.startsWith("file:")) {
377
+ const fileName = choice.slice("file:".length);
378
+ return path.join(currentDir, fileName);
379
+ }
380
+ }
381
+ }
382
+ function isReadmeCandidate(fileName) {
383
+ const lower = fileName.toLowerCase();
384
+ return (lower === "readme.md" ||
385
+ lower === "readme" ||
386
+ lower === "readme.rst" ||
387
+ lower === "readme.txt" ||
388
+ lower.startsWith("readme."));
389
+ }
390
+ function resolveCliPath() {
391
+ try {
392
+ const cmd = process.platform === "win32" ? "where" : "which";
393
+ const result = execSync(`${cmd} copilot`, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
394
+ const first = result.split("\n")[0]?.trim();
395
+ return first || "copilot";
396
+ }
397
+ catch {
398
+ return "copilot";
399
+ }
400
+ }
401
+ function getFieldValue(metadata, field) {
402
+ switch (field) {
403
+ case "name": return metadata.name;
404
+ case "tagline": return metadata.tagline;
405
+ case "description": return metadata.description;
406
+ case "github_url": return metadata.githubUrl;
407
+ case "website": return metadata.websiteUrl ?? "";
408
+ case "author": return metadata.author;
409
+ case "author_github": return metadata.authorGitHub;
410
+ case "tags": return metadata.tags;
411
+ case "language": return metadata.language ?? "";
412
+ case "license": return metadata.license ?? "";
413
+ default: return "";
414
+ }
415
+ }
416
+ function setFieldValue(metadata, field, value) {
417
+ switch (field) {
418
+ case "name":
419
+ metadata.name = value;
420
+ break;
421
+ case "tagline":
422
+ metadata.tagline = value;
423
+ break;
424
+ case "description":
425
+ metadata.description = value;
426
+ break;
427
+ case "github_url":
428
+ metadata.githubUrl = value;
429
+ break;
430
+ case "website":
431
+ metadata.websiteUrl = value;
432
+ break;
433
+ case "author":
434
+ metadata.author = value;
435
+ break;
436
+ case "author_github":
437
+ metadata.authorGitHub = value;
438
+ break;
439
+ case "tags":
440
+ metadata.tags = value;
441
+ break;
442
+ case "language":
443
+ metadata.language = value;
444
+ break;
445
+ case "license":
446
+ metadata.license = value;
447
+ break;
448
+ }
449
+ }
450
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ export interface ToolMetadata {
2
+ name: string;
3
+ tagline: string;
4
+ description: string;
5
+ githubUrl: string;
6
+ websiteUrl?: string;
7
+ author: string;
8
+ authorGitHub: string;
9
+ tags: string;
10
+ language?: string;
11
+ license?: string;
12
+ }
13
+ /**
14
+ * Builds a pre-filled GitHub issue URL for the Tiny Tool Town submission template.
15
+ */
16
+ export declare function buildIssueUrl(metadata: ToolMetadata): string;
17
+ //# sourceMappingURL=issue-url-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue-url-builder.d.ts","sourceRoot":"","sources":["../src/issue-url-builder.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAKD;;GAEG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM,CAyB5D"}
@@ -0,0 +1,30 @@
1
+ const BASE_URL = "https://github.com/shanselman/TinyToolTown/issues/new";
2
+ const TEMPLATE = "submit-tool.yml";
3
+ /**
4
+ * Builds a pre-filled GitHub issue URL for the Tiny Tool Town submission template.
5
+ */
6
+ export function buildIssueUrl(metadata) {
7
+ const params = [
8
+ `template=${encodeURIComponent(TEMPLATE)}`,
9
+ `title=${encodeURIComponent(`[Tool] ${metadata.name}`)}`,
10
+ `labels=${encodeURIComponent("new-tool")}`,
11
+ `name=${encodeURIComponent(metadata.name)}`,
12
+ `tagline=${encodeURIComponent(metadata.tagline)}`,
13
+ `description=${encodeURIComponent(metadata.description)}`,
14
+ `github_url=${encodeURIComponent(metadata.githubUrl)}`,
15
+ `author=${encodeURIComponent(metadata.author)}`,
16
+ `author_github=${encodeURIComponent(metadata.authorGitHub)}`,
17
+ `tags=${encodeURIComponent(metadata.tags)}`,
18
+ ];
19
+ if (metadata.websiteUrl) {
20
+ params.push(`website_url=${encodeURIComponent(metadata.websiteUrl)}`);
21
+ }
22
+ if (metadata.language) {
23
+ params.push(`language=${encodeURIComponent(metadata.language)}`);
24
+ }
25
+ if (metadata.license) {
26
+ params.push(`license=${encodeURIComponent(metadata.license)}`);
27
+ }
28
+ return `${BASE_URL}?${params.join("&")}`;
29
+ }
30
+ //# sourceMappingURL=issue-url-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"issue-url-builder.js","sourceRoot":"","sources":["../src/issue-url-builder.ts"],"names":[],"mappings":"AAaA,MAAM,QAAQ,GAAG,uDAAuD,CAAC;AACzE,MAAM,QAAQ,GAAG,iBAAiB,CAAC;AAEnC;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,QAAsB;IAChD,MAAM,MAAM,GAAa;QACrB,YAAY,kBAAkB,CAAC,QAAQ,CAAC,EAAE;QAC1C,SAAS,kBAAkB,CAAC,UAAU,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE;QACxD,UAAU,kBAAkB,CAAC,UAAU,CAAC,EAAE;QAC1C,QAAQ,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;QAC3C,WAAW,kBAAkB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE;QACjD,eAAe,kBAAkB,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE;QACzD,cAAc,kBAAkB,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE;QACtD,UAAU,kBAAkB,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;QAC/C,iBAAiB,kBAAkB,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE;QAC5D,QAAQ,kBAAkB,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE;KAC9C,CAAC;IAEF,IAAI,QAAQ,CAAC,UAAU,EAAE,CAAC;QACtB,MAAM,CAAC,IAAI,CAAC,eAAe,kBAAkB,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;IAC1E,CAAC;IACD,IAAI,QAAQ,CAAC,QAAQ,EAAE,CAAC;QACpB,MAAM,CAAC,IAAI,CAAC,YAAY,kBAAkB,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;QACnB,MAAM,CAAC,IAAI,CAAC,WAAW,kBAAkB,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACnE,CAAC;IAED,OAAO,GAAG,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AAC7C,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { CopilotSession } from "@github/copilot-sdk";
2
+ import type { ToolMetadata } from "./issue-url-builder.js";
3
+ /**
4
+ * Uses the Copilot SDK to analyze a README and extract tool metadata.
5
+ */
6
+ export declare function generateMetadata(session: CopilotSession, readmeContent: string, repoName: string): Promise<ToolMetadata | null>;
7
+ //# sourceMappingURL=metadata-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata-generator.d.ts","sourceRoot":"","sources":["../src/metadata-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D;;GAEG;AACH,wBAAsB,gBAAgB,CAClC,OAAO,EAAE,cAAc,EACvB,aAAa,EAAE,MAAM,EACrB,QAAQ,EAAE,MAAM,GACjB,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAgE9B"}
@@ -0,0 +1,141 @@
1
+ /**
2
+ * Uses the Copilot SDK to analyze a README and extract tool metadata.
3
+ */
4
+ export async function generateMetadata(session, readmeContent, repoName) {
5
+ const prompt = `You extract metadata from a GitHub README for Tiny Tool Town.
6
+
7
+ Return ONLY valid JSON (no markdown, no code fences) with this exact schema:
8
+ {
9
+ "name": "string",
10
+ "tagline": "string <= 100 chars",
11
+ "description": "string, 2-4 sentences",
12
+ "tags": ["lowercase-tag", "another-tag", "3-6 tags total"]
13
+ }
14
+
15
+ Rules:
16
+ - Name must match the tool name from README; do not invent a different product.
17
+ - Tagline must be concise and clear.
18
+ - Description should be enthusiastic but honest.
19
+ - Tags must be lowercase, relevant, and contain 3-6 entries.
20
+
21
+ Repository name: ${repoName}
22
+
23
+ README content:
24
+ ${readmeContent}`;
25
+ const raw = await sendPrompt(session, prompt);
26
+ let metadata = parseResponse(raw);
27
+ if (!metadata)
28
+ return null;
29
+ normalizeGeneratedFields(metadata);
30
+ const issues = getGeneratedFieldIssues(metadata);
31
+ if (issues.length > 0) {
32
+ const repairPrompt = `Fix this metadata JSON so it satisfies ALL constraints.
33
+ Return ONLY valid JSON with keys: name, tagline, description, tags.
34
+
35
+ Constraints:
36
+ - name: non-empty
37
+ - tagline: non-empty and <= 100 characters
38
+ - description: non-empty, 2-4 sentences
39
+ - tags: array of 3-6 lowercase, relevant tags
40
+
41
+ Issues found:
42
+ ${issues.join("; ")}
43
+
44
+ Current JSON:
45
+ ${JSON.stringify({
46
+ name: metadata.name,
47
+ tagline: metadata.tagline,
48
+ description: metadata.description,
49
+ tags: metadata.tags.split(",").map((t) => t.trim()).filter(Boolean),
50
+ })}`;
51
+ const repairedRaw = await sendPrompt(session, repairPrompt);
52
+ const repaired = parseResponse(repairedRaw);
53
+ if (repaired) {
54
+ normalizeGeneratedFields(repaired);
55
+ if (getGeneratedFieldIssues(repaired).length === 0) {
56
+ metadata = repaired;
57
+ }
58
+ }
59
+ }
60
+ applyFallbacks(metadata, repoName);
61
+ normalizeGeneratedFields(metadata);
62
+ return metadata;
63
+ }
64
+ async function sendPrompt(session, prompt) {
65
+ const response = await session.sendAndWait({ prompt });
66
+ return response?.data?.content?.trim() ?? "";
67
+ }
68
+ function parseResponse(raw) {
69
+ if (!raw)
70
+ return null;
71
+ try {
72
+ const json = extractJsonObject(raw);
73
+ const parsed = JSON.parse(json);
74
+ let tagsValue = "";
75
+ if (Array.isArray(parsed.tags)) {
76
+ tagsValue = parsed.tags
77
+ .filter((t) => typeof t === "string" && t.trim())
78
+ .join(", ");
79
+ }
80
+ else if (typeof parsed.tags === "string") {
81
+ tagsValue = parsed.tags;
82
+ }
83
+ return {
84
+ name: (parsed.name ?? "").trim(),
85
+ tagline: (parsed.tagline ?? "").trim(),
86
+ description: (parsed.description ?? "").trim(),
87
+ githubUrl: "",
88
+ author: "",
89
+ authorGitHub: "",
90
+ tags: tagsValue,
91
+ };
92
+ }
93
+ catch {
94
+ return null;
95
+ }
96
+ }
97
+ function extractJsonObject(raw) {
98
+ const start = raw.indexOf("{");
99
+ const end = raw.lastIndexOf("}");
100
+ return start >= 0 && end > start ? raw.slice(start, end + 1) : raw;
101
+ }
102
+ function normalizeGeneratedFields(metadata) {
103
+ metadata.name = metadata.name.trim();
104
+ metadata.tagline = metadata.tagline.trim();
105
+ metadata.description = metadata.description.trim();
106
+ const tags = metadata.tags
107
+ .split(",")
108
+ .map((t) => t.trim().toLowerCase())
109
+ .filter(Boolean);
110
+ metadata.tags = [...new Set(tags)].join(", ");
111
+ }
112
+ function getGeneratedFieldIssues(metadata) {
113
+ const issues = [];
114
+ if (!metadata.name)
115
+ issues.push("name is missing");
116
+ if (!metadata.tagline)
117
+ issues.push("tagline is missing");
118
+ else if (metadata.tagline.length > 100)
119
+ issues.push("tagline exceeds 100 characters");
120
+ if (!metadata.description)
121
+ issues.push("description is missing");
122
+ const tags = metadata.tags.split(",").map((t) => t.trim()).filter(Boolean);
123
+ if (tags.length < 3 || tags.length > 6)
124
+ issues.push("tags must contain 3 to 6 entries");
125
+ if (tags.some((t) => t !== t.toLowerCase()))
126
+ issues.push("tags must be lowercase");
127
+ return issues;
128
+ }
129
+ function applyFallbacks(metadata, repoName) {
130
+ if (!metadata.name)
131
+ metadata.name = repoName;
132
+ if (!metadata.tagline)
133
+ metadata.tagline = `A tiny tool called ${repoName}.`;
134
+ if (metadata.tagline.length > 100)
135
+ metadata.tagline = metadata.tagline.slice(0, 100).trimEnd();
136
+ if (!metadata.description)
137
+ metadata.description = `${repoName} is a helpful open source tool from this repository.`;
138
+ if (!metadata.tags)
139
+ metadata.tags = "cli, developer-tools, productivity";
140
+ }
141
+ //# sourceMappingURL=metadata-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"metadata-generator.js","sourceRoot":"","sources":["../src/metadata-generator.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAClC,OAAuB,EACvB,aAAqB,EACrB,QAAgB;IAEhB,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;mBAgBA,QAAQ;;;EAGzB,aAAa,EAAE,CAAC;IAEd,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAC9C,IAAI,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC;IAClC,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAE3B,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAEnC,MAAM,MAAM,GAAG,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IACjD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACpB,MAAM,YAAY,GAAG;;;;;;;;;;EAU3B,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;;;EAGjB,IAAI,CAAC,SAAS,CAAC;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI;YACnB,OAAO,EAAE,QAAQ,CAAC,OAAO;YACzB,WAAW,EAAE,QAAQ,CAAC,WAAW;YACjC,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;SACtE,CAAC,EAAE,CAAC;QAEL,MAAM,WAAW,GAAG,MAAM,UAAU,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QAC5D,MAAM,QAAQ,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;QAC5C,IAAI,QAAQ,EAAE,CAAC;YACX,wBAAwB,CAAC,QAAQ,CAAC,CAAC;YACnC,IAAI,uBAAuB,CAAC,QAAQ,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACjD,QAAQ,GAAG,QAAQ,CAAC;YACxB,CAAC;QACL,CAAC;IACL,CAAC;IAED,cAAc,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACnC,wBAAwB,CAAC,QAAQ,CAAC,CAAC;IAEnC,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,OAAuB,EAAE,MAAc;IAC7D,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC;IACvD,OAAO,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACjD,CAAC;AAED,SAAS,aAAa,CAAC,GAAW;IAC9B,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IAEtB,IAAI,CAAC;QACD,MAAM,IAAI,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEhC,IAAI,SAAS,GAAG,EAAE,CAAC;QACnB,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7B,SAAS,GAAG,MAAM,CAAC,IAAI;iBAClB,MAAM,CAAC,CAAC,CAAU,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;iBACzD,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,CAAC;aAAM,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACzC,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC;QAC5B,CAAC;QAED,OAAO;YACH,IAAI,EAAE,CAAC,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;YAChC,OAAO,EAAE,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;YACtC,WAAW,EAAE,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;YAC9C,SAAS,EAAE,EAAE;YACb,MAAM,EAAE,EAAE;YACV,YAAY,EAAE,EAAE;YAChB,IAAI,EAAE,SAAS;SAClB,CAAC;IACN,CAAC;IAAC,MAAM,CAAC;QACL,OAAO,IAAI,CAAC;IAChB,CAAC;AACL,CAAC;AAED,SAAS,iBAAiB,CAAC,GAAW;IAClC,MAAM,KAAK,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,GAAG,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACjC,OAAO,KAAK,IAAI,CAAC,IAAI,GAAG,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACvE,CAAC;AAED,SAAS,wBAAwB,CAAC,QAAsB;IACpD,QAAQ,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IACrC,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;IAC3C,QAAQ,CAAC,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;IAEnD,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI;SACrB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;SAClC,MAAM,CAAC,OAAO,CAAC,CAAC;IAErB,QAAQ,CAAC,IAAI,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAClD,CAAC;AAED,SAAS,uBAAuB,CAAC,QAAsB;IACnD,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,IAAI,CAAC,QAAQ,CAAC,IAAI;QAAE,MAAM,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACnD,IAAI,CAAC,QAAQ,CAAC,OAAO;QAAE,MAAM,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;SACpD,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG;QAAE,MAAM,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC;IACtF,IAAI,CAAC,QAAQ,CAAC,WAAW;QAAE,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IAEjE,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3E,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC;IACxF,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,WAAW,EAAE,CAAC;QAAE,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IAEnF,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,SAAS,cAAc,CAAC,QAAsB,EAAE,QAAgB;IAC5D,IAAI,CAAC,QAAQ,CAAC,IAAI;QAAE,QAAQ,CAAC,IAAI,GAAG,QAAQ,CAAC;IAC7C,IAAI,CAAC,QAAQ,CAAC,OAAO;QAAE,QAAQ,CAAC,OAAO,GAAG,sBAAsB,QAAQ,GAAG,CAAC;IAC5E,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,GAAG,GAAG;QAAE,QAAQ,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;IAC/F,IAAI,CAAC,QAAQ,CAAC,WAAW;QAAE,QAAQ,CAAC,WAAW,GAAG,GAAG,QAAQ,sDAAsD,CAAC;IACpH,IAAI,CAAC,QAAQ,CAAC,IAAI;QAAE,QAAQ,CAAC,IAAI,GAAG,oCAAoC,CAAC;AAC7E,CAAC"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Finds a README file in the given directory.
3
+ */
4
+ export declare function findReadme(directory: string): string | null;
5
+ /**
6
+ * Detects the GitHub repository URL from git remotes.
7
+ */
8
+ export declare function detectGitHubUrl(directory: string): string | null;
9
+ /**
10
+ * Detects the license type from the repo.
11
+ */
12
+ export declare function detectLicense(directory: string): string | null;
13
+ /**
14
+ * Detects the primary programming language by scanning file extensions.
15
+ */
16
+ export declare function detectLanguage(directory: string): string | null;
17
+ /**
18
+ * Detects the git user name from git config.
19
+ */
20
+ export declare function detectGitUserName(directory: string): string | null;
21
+ /**
22
+ * Detects the GitHub username from the remote URL.
23
+ */
24
+ export declare function detectGitHubUsername(githubUrl: string | null): string | null;
25
+ //# sourceMappingURL=repo-detector.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-detector.d.ts","sourceRoot":"","sources":["../src/repo-detector.ts"],"names":[],"mappings":"AAWA;;GAEG;AACH,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQ3D;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAahE;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsB9D;AA2BD;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CA+D/D;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAElE;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAS5E"}
@@ -0,0 +1,206 @@
1
+ import { execSync } from "child_process";
2
+ import * as fs from "fs";
3
+ import * as path from "path";
4
+ const README_NAMES = [
5
+ "README.md", "readme.md", "Readme.md",
6
+ "README", "readme",
7
+ "README.rst", "readme.rst",
8
+ "README.txt", "readme.txt",
9
+ ];
10
+ /**
11
+ * Finds a README file in the given directory.
12
+ */
13
+ export function findReadme(directory) {
14
+ for (const name of README_NAMES) {
15
+ const filePath = path.join(directory, name);
16
+ if (fs.existsSync(filePath)) {
17
+ return filePath;
18
+ }
19
+ }
20
+ return null;
21
+ }
22
+ /**
23
+ * Detects the GitHub repository URL from git remotes.
24
+ */
25
+ export function detectGitHubUrl(directory) {
26
+ try {
27
+ const output = execSync("git remote get-url origin", {
28
+ cwd: directory,
29
+ encoding: "utf-8",
30
+ stdio: ["pipe", "pipe", "pipe"],
31
+ }).trim();
32
+ if (!output)
33
+ return null;
34
+ return normalizeGitUrl(output);
35
+ }
36
+ catch {
37
+ return null;
38
+ }
39
+ }
40
+ /**
41
+ * Detects the license type from the repo.
42
+ */
43
+ export function detectLicense(directory) {
44
+ const licenseFiles = ["LICENSE", "LICENSE.md", "LICENSE.txt", "LICENCE", "LICENCE.md", "LICENCE.txt"];
45
+ for (const name of licenseFiles) {
46
+ const filePath = path.join(directory, name);
47
+ if (!fs.existsSync(filePath))
48
+ continue;
49
+ const content = fs.readFileSync(filePath, "utf-8");
50
+ const detected = detectLicenseFromText(content);
51
+ if (detected)
52
+ return detected;
53
+ return "Unknown";
54
+ }
55
+ // Fallback: check README
56
+ const readmePath = findReadme(directory);
57
+ if (readmePath && fs.existsSync(readmePath)) {
58
+ const content = fs.readFileSync(readmePath, "utf-8");
59
+ const detected = detectLicenseFromText(content);
60
+ if (detected)
61
+ return detected;
62
+ }
63
+ return null;
64
+ }
65
+ function detectLicenseFromText(content) {
66
+ const lower = content.toLowerCase();
67
+ if (lower.includes("mit license") || lower.includes("licensed under the mit") || lower.includes("license: mit"))
68
+ return "MIT";
69
+ if (lower.includes("apache license") || lower.includes("apache-2.0") || lower.includes("license: apache"))
70
+ return "Apache-2.0";
71
+ if (lower.includes("gnu general public license") || lower.includes("gpl-3.0") || lower.includes("gplv3"))
72
+ return "GPL-3.0";
73
+ if (lower.includes("gpl-2.0") || lower.includes("gplv2"))
74
+ return "GPL-2.0";
75
+ if (lower.includes("bsd 2-clause"))
76
+ return "BSD-2-Clause";
77
+ if (lower.includes("bsd 3-clause"))
78
+ return "BSD-3-Clause";
79
+ if (lower.includes("mozilla public license") || lower.includes("mpl-2.0"))
80
+ return "MPL-2.0";
81
+ if (lower.includes("isc license") || lower.includes("license: isc"))
82
+ return "ISC";
83
+ if (lower.includes("the unlicense") || lower.includes("unlicense"))
84
+ return "Unlicense";
85
+ return null;
86
+ }
87
+ /**
88
+ * Detects the primary programming language by scanning file extensions.
89
+ */
90
+ export function detectLanguage(directory) {
91
+ const extensionMap = {
92
+ ".cs": "C#",
93
+ ".fs": "F#",
94
+ ".vb": "VB.NET",
95
+ ".py": "Python",
96
+ ".rs": "Rust",
97
+ ".go": "Go",
98
+ ".ts": "TypeScript",
99
+ ".js": "JavaScript",
100
+ ".java": "Java",
101
+ ".kt": "Kotlin",
102
+ ".swift": "Swift",
103
+ ".rb": "Ruby",
104
+ ".cpp": "C++",
105
+ ".c": "C",
106
+ ".zig": "Zig",
107
+ ".lua": "Lua",
108
+ ".php": "PHP",
109
+ ".dart": "Dart",
110
+ ".ex": "Elixir",
111
+ ".exs": "Elixir",
112
+ ".hs": "Haskell",
113
+ ".scala": "Scala",
114
+ ".r": "R",
115
+ ".jl": "Julia",
116
+ ".pl": "Perl",
117
+ ".sh": "Shell",
118
+ ".ps1": "PowerShell",
119
+ };
120
+ const skipDirs = new Set([".git", "node_modules", "bin", "obj", "vendor", "target", "dist", "__pycache__"]);
121
+ const counts = {};
122
+ function walk(dir, depth) {
123
+ if (depth > 5)
124
+ return;
125
+ try {
126
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
127
+ for (const entry of entries) {
128
+ if (entry.isDirectory()) {
129
+ if (!skipDirs.has(entry.name)) {
130
+ walk(path.join(dir, entry.name), depth + 1);
131
+ }
132
+ }
133
+ else if (entry.isFile()) {
134
+ const ext = path.extname(entry.name).toLowerCase();
135
+ const lang = extensionMap[ext];
136
+ if (lang) {
137
+ counts[lang] = (counts[lang] || 0) + 1;
138
+ }
139
+ }
140
+ }
141
+ }
142
+ catch {
143
+ // Ignore enumeration errors
144
+ }
145
+ }
146
+ walk(directory, 0);
147
+ const entries = Object.entries(counts);
148
+ if (entries.length === 0)
149
+ return null;
150
+ entries.sort((a, b) => b[1] - a[1]);
151
+ return entries[0][0];
152
+ }
153
+ /**
154
+ * Detects the git user name from git config.
155
+ */
156
+ export function detectGitUserName(directory) {
157
+ return runGit(directory, "config user.name");
158
+ }
159
+ /**
160
+ * Detects the GitHub username from the remote URL.
161
+ */
162
+ export function detectGitHubUsername(githubUrl) {
163
+ if (!githubUrl)
164
+ return null;
165
+ try {
166
+ const url = new URL(githubUrl);
167
+ const segments = url.pathname.replace(/^\//, "").split("/");
168
+ return segments.length >= 1 ? segments[0] : null;
169
+ }
170
+ catch {
171
+ return null;
172
+ }
173
+ }
174
+ function normalizeGitUrl(url) {
175
+ // SSH: git@github.com:owner/repo.git -> https://github.com/owner/repo
176
+ if (url.startsWith("git@github.com:")) {
177
+ let repoPath = url.slice("git@github.com:".length).replace(/\/$/, "");
178
+ if (repoPath.endsWith(".git")) {
179
+ repoPath = repoPath.slice(0, -4);
180
+ }
181
+ return `https://github.com/${repoPath}`;
182
+ }
183
+ // HTTPS
184
+ if (url.toLowerCase().startsWith("https://github.com/")) {
185
+ let trimmed = url.replace(/\/$/, "");
186
+ if (trimmed.endsWith(".git")) {
187
+ trimmed = trimmed.slice(0, -4);
188
+ }
189
+ return trimmed;
190
+ }
191
+ return url;
192
+ }
193
+ function runGit(directory, args) {
194
+ try {
195
+ const output = execSync(`git ${args}`, {
196
+ cwd: directory,
197
+ encoding: "utf-8",
198
+ stdio: ["pipe", "pipe", "pipe"],
199
+ }).trim();
200
+ return output || null;
201
+ }
202
+ catch {
203
+ return null;
204
+ }
205
+ }
206
+ //# sourceMappingURL=repo-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repo-detector.js","sourceRoot":"","sources":["../src/repo-detector.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "tiny-tool-submitter",
3
+ "version": "1.0.0",
4
+ "description": "A CLI tool that uses GitHub Copilot to analyze your repo's README and prepare a submission to Tiny Tool Town.",
5
+ "type": "module",
6
+ "bin": {
7
+ "tiny-tool-submit": "./dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist"
11
+ ],
12
+ "scripts": {
13
+ "build": "tsc",
14
+ "start": "node dist/index.js",
15
+ "dev": "tsx src/index.ts"
16
+ },
17
+ "keywords": [
18
+ "cli",
19
+ "tool",
20
+ "github-copilot",
21
+ "tiny-tool-town"
22
+ ],
23
+ "author": "James Montemagno",
24
+ "license": "MIT",
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/jamesmontemagno/TinyToolSubmitter"
28
+ },
29
+ "homepage": "https://github.com/jamesmontemagno/TinyToolSubmitter",
30
+ "engines": {
31
+ "node": ">=18.0.0"
32
+ },
33
+ "dependencies": {
34
+ "@github/copilot-sdk": "^0.1.22",
35
+ "@inquirer/prompts": "^7.0.0"
36
+ },
37
+ "devDependencies": {
38
+ "@types/node": "^20.0.0",
39
+ "tsx": "^4.20.4",
40
+ "typescript": "^5.5.0"
41
+ }
42
+ }