truecourse 0.5.2 → 0.5.4
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/cli.mjs +60 -37
- package/package.json +1 -1
package/cli.mjs
CHANGED
|
@@ -4080,7 +4080,7 @@ __export(helpers_exports, {
|
|
|
4080
4080
|
writeConfig: () => writeConfig
|
|
4081
4081
|
});
|
|
4082
4082
|
import { exec as exec2 } from "node:child_process";
|
|
4083
|
-
import { cpSync, existsSync } from "node:fs";
|
|
4083
|
+
import { cpSync, existsSync, mkdirSync, readdirSync } from "node:fs";
|
|
4084
4084
|
import fs3 from "node:fs";
|
|
4085
4085
|
import os2 from "node:os";
|
|
4086
4086
|
import path3 from "node:path";
|
|
@@ -4319,12 +4319,6 @@ function openInBrowser(url) {
|
|
|
4319
4319
|
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
4320
4320
|
exec2(`${cmd} ${url}`);
|
|
4321
4321
|
}
|
|
4322
|
-
function skillDestPath(repoPath) {
|
|
4323
|
-
return resolve(repoPath, ".claude", "skills", "truecourse");
|
|
4324
|
-
}
|
|
4325
|
-
function hasInstalledSkills(repoPath) {
|
|
4326
|
-
return existsSync(skillDestPath(repoPath));
|
|
4327
|
-
}
|
|
4328
4322
|
function isInteractive() {
|
|
4329
4323
|
return !!process.stdin.isTTY;
|
|
4330
4324
|
}
|
|
@@ -4336,35 +4330,64 @@ Running non-interactively with no answer. ${flagGuidance}`
|
|
|
4336
4330
|
);
|
|
4337
4331
|
process.exit(1);
|
|
4338
4332
|
}
|
|
4339
|
-
function
|
|
4333
|
+
function resolveSkillsSrcDir() {
|
|
4340
4334
|
const __dirname4 = dirname(fileURLToPath(import.meta.url));
|
|
4341
|
-
const
|
|
4342
|
-
|
|
4343
|
-
|
|
4344
|
-
|
|
4335
|
+
const candidate = resolve(__dirname4, "skills", "truecourse");
|
|
4336
|
+
return existsSync(candidate) ? candidate : null;
|
|
4337
|
+
}
|
|
4338
|
+
function skillsParentDir(repoPath) {
|
|
4339
|
+
return resolve(repoPath, ".claude", "skills");
|
|
4340
|
+
}
|
|
4341
|
+
function listSkillDirs(root) {
|
|
4342
|
+
if (!existsSync(root)) return [];
|
|
4343
|
+
return readdirSync(root, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
4344
|
+
}
|
|
4345
|
+
function computeMissingSkills(repoPath) {
|
|
4346
|
+
const src = resolveSkillsSrcDir();
|
|
4347
|
+
if (!src) return [];
|
|
4348
|
+
const shipped = listSkillDirs(src);
|
|
4349
|
+
const parent = skillsParentDir(repoPath);
|
|
4350
|
+
return shipped.filter((name) => !existsSync(resolve(parent, name)));
|
|
4351
|
+
}
|
|
4352
|
+
function hasInstalledSkills(repoPath) {
|
|
4353
|
+
return computeMissingSkills(repoPath).length === 0;
|
|
4354
|
+
}
|
|
4355
|
+
function copySkills(repoPath, skillNames) {
|
|
4356
|
+
const src = resolveSkillsSrcDir();
|
|
4357
|
+
if (!src) {
|
|
4345
4358
|
O2.warn("Skills directory not found in package \u2014 skipping.");
|
|
4346
4359
|
return;
|
|
4347
4360
|
}
|
|
4348
|
-
const
|
|
4349
|
-
|
|
4350
|
-
|
|
4351
|
-
|
|
4352
|
-
|
|
4353
|
-
|
|
4361
|
+
const parent = skillsParentDir(repoPath);
|
|
4362
|
+
mkdirSync(parent, { recursive: true });
|
|
4363
|
+
for (const name of skillNames) {
|
|
4364
|
+
const skillSrc = resolve(src, name);
|
|
4365
|
+
const skillDest = resolve(parent, name);
|
|
4366
|
+
if (existsSync(skillDest)) continue;
|
|
4367
|
+
cpSync(skillSrc, skillDest, { recursive: true });
|
|
4368
|
+
}
|
|
4369
|
+
O2.success(
|
|
4370
|
+
`Installed ${skillNames.length} Claude Code skill${skillNames.length === 1 ? "" : "s"}:`
|
|
4371
|
+
);
|
|
4372
|
+
for (const name of skillNames) O2.message(` - ${name}`);
|
|
4354
4373
|
}
|
|
4355
4374
|
async function promptInstallSkills(repoPath, { install } = {}) {
|
|
4356
|
-
|
|
4375
|
+
const missing = computeMissingSkills(repoPath);
|
|
4376
|
+
if (missing.length === 0) return;
|
|
4357
4377
|
if (install === true) {
|
|
4358
|
-
|
|
4378
|
+
copySkills(repoPath, missing);
|
|
4359
4379
|
return;
|
|
4360
4380
|
}
|
|
4361
4381
|
if (install === false) return;
|
|
4362
4382
|
if (!isInteractive()) return;
|
|
4363
|
-
const
|
|
4364
|
-
|
|
4365
|
-
|
|
4383
|
+
const src = resolveSkillsSrcDir();
|
|
4384
|
+
const shipped = src ? listSkillDirs(src) : [];
|
|
4385
|
+
const parent = skillsParentDir(repoPath);
|
|
4386
|
+
const alreadyInstalled = shipped.some((name) => existsSync(resolve(parent, name)));
|
|
4387
|
+
const message = alreadyInstalled ? `New Claude Code skill${missing.length === 1 ? "" : "s"} available: ${missing.join(", ")}. Install?` : "Would you like to install Claude Code skills?";
|
|
4388
|
+
const answer = await ot2({ message });
|
|
4366
4389
|
if (q(answer) || !answer) return;
|
|
4367
|
-
|
|
4390
|
+
copySkills(repoPath, missing);
|
|
4368
4391
|
}
|
|
4369
4392
|
var DEFAULT_PORT, DEFAULT_CONFIG;
|
|
4370
4393
|
var init_helpers = __esm({
|
|
@@ -10563,7 +10586,7 @@ var init_language_config = __esm({
|
|
|
10563
10586
|
});
|
|
10564
10587
|
|
|
10565
10588
|
// packages/analyzer/dist/file-discovery.js
|
|
10566
|
-
import { existsSync as existsSync2, readFileSync, readdirSync, statSync } from "fs";
|
|
10589
|
+
import { existsSync as existsSync2, readFileSync, readdirSync as readdirSync2, statSync } from "fs";
|
|
10567
10590
|
import { join, relative, resolve as resolve2 } from "path";
|
|
10568
10591
|
function findAllGitignores(startDir) {
|
|
10569
10592
|
const gitignores = [];
|
|
@@ -10606,7 +10629,7 @@ function discoverFiles(dir) {
|
|
|
10606
10629
|
const { ig, rootDir } = loadIgnorePatterns(dir);
|
|
10607
10630
|
function traverse(currentPath) {
|
|
10608
10631
|
try {
|
|
10609
|
-
const entries =
|
|
10632
|
+
const entries = readdirSync2(currentPath).sort();
|
|
10610
10633
|
for (const entry of entries) {
|
|
10611
10634
|
const fullPath = join(currentPath, entry);
|
|
10612
10635
|
const relativePath = relative(rootDir, fullPath);
|
|
@@ -10894,7 +10917,7 @@ var init_service_patterns = __esm({
|
|
|
10894
10917
|
// packages/analyzer/dist/ts-compiler.js
|
|
10895
10918
|
import * as ts from "typescript";
|
|
10896
10919
|
import { dirname as dirname2, join as join2 } from "path";
|
|
10897
|
-
import { existsSync as existsSync3, readdirSync as
|
|
10920
|
+
import { existsSync as existsSync3, readdirSync as readdirSync3, statSync as statSync2 } from "fs";
|
|
10898
10921
|
function buildScopedCompilerOptions(rootPath) {
|
|
10899
10922
|
const result = [];
|
|
10900
10923
|
const candidates = [join2(rootPath, "tsconfig.json")];
|
|
@@ -10903,7 +10926,7 @@ function buildScopedCompilerOptions(rootPath) {
|
|
|
10903
10926
|
if (!existsSync3(dirPath) || !statSync2(dirPath).isDirectory())
|
|
10904
10927
|
continue;
|
|
10905
10928
|
try {
|
|
10906
|
-
for (const entry of
|
|
10929
|
+
for (const entry of readdirSync3(dirPath).sort()) {
|
|
10907
10930
|
candidates.push(join2(dirPath, entry, "tsconfig.json"));
|
|
10908
10931
|
}
|
|
10909
10932
|
} catch {
|
|
@@ -13533,7 +13556,7 @@ var init_registry2 = __esm({
|
|
|
13533
13556
|
|
|
13534
13557
|
// packages/analyzer/dist/dependency-graph.js
|
|
13535
13558
|
import { resolve as resolve4, dirname as dirname4, join as join3 } from "path";
|
|
13536
|
-
import { existsSync as existsSync4, readFileSync as readFileSync2, readdirSync as
|
|
13559
|
+
import { existsSync as existsSync4, readFileSync as readFileSync2, readdirSync as readdirSync4, realpathSync, statSync as statSync3 } from "fs";
|
|
13537
13560
|
function resolveRelativeFallback(importSource, containingFile, analyzedFiles, extensions, indexFiles) {
|
|
13538
13561
|
const fromDir = dirname4(containingFile);
|
|
13539
13562
|
const basePath = resolve4(fromDir, importSource);
|
|
@@ -13561,7 +13584,7 @@ function buildWorkspacePackageMap(rootPath) {
|
|
|
13561
13584
|
if (!existsSync4(dirPath) || !statSync3(dirPath).isDirectory())
|
|
13562
13585
|
continue;
|
|
13563
13586
|
try {
|
|
13564
|
-
for (const entry of
|
|
13587
|
+
for (const entry of readdirSync4(dirPath).sort()) {
|
|
13565
13588
|
const pkgDir = join3(dirPath, entry);
|
|
13566
13589
|
const pkgJsonPath = join3(pkgDir, "package.json");
|
|
13567
13590
|
if (!existsSync4(pkgJsonPath))
|
|
@@ -16249,7 +16272,7 @@ var init_registry3 = __esm({
|
|
|
16249
16272
|
});
|
|
16250
16273
|
|
|
16251
16274
|
// packages/analyzer/dist/service-detector.js
|
|
16252
|
-
import { existsSync as existsSync7, readFileSync as readFileSync5, readdirSync as
|
|
16275
|
+
import { existsSync as existsSync7, readFileSync as readFileSync5, readdirSync as readdirSync5, statSync as statSync4 } from "fs";
|
|
16253
16276
|
import { join as join6, basename, dirname as dirname5 } from "path";
|
|
16254
16277
|
function detectServices(rootPath, allFiles) {
|
|
16255
16278
|
const monorepoServices = detectMonorepoServices(rootPath, allFiles);
|
|
@@ -16294,7 +16317,7 @@ function detectMonorepoServices(rootPath, allFiles) {
|
|
|
16294
16317
|
if (!existsSync7(dirPath))
|
|
16295
16318
|
continue;
|
|
16296
16319
|
try {
|
|
16297
|
-
const entries =
|
|
16320
|
+
const entries = readdirSync5(dirPath).sort();
|
|
16298
16321
|
for (const entry of entries) {
|
|
16299
16322
|
const servicePath = join6(dirPath, entry);
|
|
16300
16323
|
const stats = statSync4(servicePath);
|
|
@@ -17050,7 +17073,7 @@ var init_registry4 = __esm({
|
|
|
17050
17073
|
});
|
|
17051
17074
|
|
|
17052
17075
|
// packages/analyzer/dist/database-detector.js
|
|
17053
|
-
import { existsSync as existsSync8, readFileSync as readFileSync6, readdirSync as
|
|
17076
|
+
import { existsSync as existsSync8, readFileSync as readFileSync6, readdirSync as readdirSync6 } from "fs";
|
|
17054
17077
|
import { join as join7, resolve as resolve5 } from "path";
|
|
17055
17078
|
function detectDatabases(rootPath, analyses, services) {
|
|
17056
17079
|
const detections = [];
|
|
@@ -17219,7 +17242,7 @@ function parseDockerCompose(rootPath) {
|
|
|
17219
17242
|
function findFiles(dir, fileName, ignoreDirs) {
|
|
17220
17243
|
const results = [];
|
|
17221
17244
|
try {
|
|
17222
|
-
const entries =
|
|
17245
|
+
const entries = readdirSync6(dir, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
|
|
17223
17246
|
for (const entry of entries) {
|
|
17224
17247
|
if (ignoreDirs.includes(entry.name))
|
|
17225
17248
|
continue;
|
|
@@ -123658,7 +123681,7 @@ var init_schemas2 = __esm({
|
|
|
123658
123681
|
|
|
123659
123682
|
// apps/server/dist/services/llm/cli-provider.js
|
|
123660
123683
|
import { spawn as spawn3 } from "node:child_process";
|
|
123661
|
-
import { mkdirSync, writeFileSync } from "node:fs";
|
|
123684
|
+
import { mkdirSync as mkdirSync2, writeFileSync } from "node:fs";
|
|
123662
123685
|
import { join as join8 } from "node:path";
|
|
123663
123686
|
import { tmpdir } from "node:os";
|
|
123664
123687
|
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
@@ -123721,7 +123744,7 @@ var init_cli_provider = __esm({
|
|
|
123721
123744
|
constructor() {
|
|
123722
123745
|
if (process.env.TRUECOURSE_CLI_DEBUG) {
|
|
123723
123746
|
this.debugDir = join8(tmpdir(), "truecourse-cli-debug");
|
|
123724
|
-
|
|
123747
|
+
mkdirSync2(this.debugDir, { recursive: true });
|
|
123725
123748
|
log.info(`[CLI] Debug output: ${this.debugDir}`);
|
|
123726
123749
|
}
|
|
123727
123750
|
}
|
|
@@ -130710,7 +130733,7 @@ async function runHooksRun() {
|
|
|
130710
130733
|
|
|
130711
130734
|
// tools/cli/src/index.ts
|
|
130712
130735
|
var program2 = new Command();
|
|
130713
|
-
program2.name("truecourse").version("0.5.
|
|
130736
|
+
program2.name("truecourse").version("0.5.4").description("TrueCourse CLI \u2014 analyze your repository and open the dashboard");
|
|
130714
130737
|
var dashboardCmd = program2.command("dashboard").description("Start the TrueCourse dashboard and open it in your browser").option("--reconfigure", "Re-prompt for console vs background service mode").option("--service", "Run as a background service (skips mode prompt)").option("--console", "Run in this terminal (skips mode prompt)").action(async (options) => {
|
|
130715
130738
|
if (options.service && options.console) {
|
|
130716
130739
|
console.error("error: --service and --console are mutually exclusive");
|