ft-scout 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.
- package/.ft/context.json +14 -0
- package/README.md +48 -0
- package/bin/ft.js +2 -0
- package/bin/src/commands/brief.d.ts.map +1 -0
- package/bin/src/commands/brief.js +27 -0
- package/bin/src/commands/brief.js.map +1 -0
- package/bin/src/commands/init.d.ts.map +1 -0
- package/bin/src/commands/init.js +22 -0
- package/bin/src/commands/init.js.map +1 -0
- package/bin/src/commands/owners.d.ts.map +1 -0
- package/bin/src/commands/owners.js +2 -0
- package/bin/src/commands/owners.js.map +1 -0
- package/bin/src/commands/risky.d.ts.map +1 -0
- package/bin/src/commands/risky.js +43 -0
- package/bin/src/commands/risky.js.map +1 -0
- package/bin/src/commands/setup.d.ts.map +1 -0
- package/bin/src/commands/setup.js +35 -0
- package/bin/src/commands/setup.js.map +1 -0
- package/bin/src/engine/git.d.ts.map +1 -0
- package/bin/src/engine/git.js +25 -0
- package/bin/src/engine/git.js.map +1 -0
- package/bin/src/engine/llm.d.ts.map +1 -0
- package/bin/src/engine/llm.js +49 -0
- package/bin/src/engine/llm.js.map +1 -0
- package/bin/src/engine/scanners.d.ts.map +1 -0
- package/bin/src/engine/scanners.js +2 -0
- package/bin/src/engine/scanners.js.map +1 -0
- package/bin/src/index.d.ts.map +1 -0
- package/bin/src/index.js +48 -0
- package/bin/src/index.js.map +1 -0
- package/bin/src/utils/config.d.ts.map +1 -0
- package/bin/src/utils/config.js +16 -0
- package/bin/src/utils/config.js.map +1 -0
- package/bin/src/utils/logger.d.ts.map +1 -0
- package/bin/src/utils/logger.js +2 -0
- package/bin/src/utils/logger.js.map +1 -0
- package/front-terrain-cli-1.0.0.tgz +0 -0
- package/package.json +36 -0
package/.ft/context.json
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"projectName": "FT-CLI",
|
|
3
|
+
"stack": "The FT-CLI project is a command-line interface tool built with Node.js, TypeScript, and various dependencies such as commander and dotenv, which suggests it handles tasks related to file management, git operations, and possibly AI-powered features via OpenAI. Its core stack includes TypeScript, JavaScript, and multiple libraries for interactive prompts and terminal output customization.",
|
|
4
|
+
"entryPoint": "bin/ft.js",
|
|
5
|
+
"painPoints": [
|
|
6
|
+
"Potential complexity in integrating multiple third-party libraries, lack of tests as indicated by the 'test' script in package.json"
|
|
7
|
+
],
|
|
8
|
+
"readOrder": [
|
|
9
|
+
"package.json",
|
|
10
|
+
"bin/ft.js",
|
|
11
|
+
"tsconfig.json"
|
|
12
|
+
],
|
|
13
|
+
"createdAt": "2026-07-30T07:56:23.435Z"
|
|
14
|
+
}
|
package/README.md
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# ft-scout
|
|
2
|
+
|
|
3
|
+
FrontTerrain — The Onboarding Co-Pilot for New Codebases.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Install globally using npm:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install -g ft-scout
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Setup
|
|
14
|
+
|
|
15
|
+
To use the AI-powered summary and onboarding features, you must provide your own API key for the GROQ platform.
|
|
16
|
+
|
|
17
|
+
Set the `GROQ_API_KEY` environment variable in your shell:
|
|
18
|
+
|
|
19
|
+
**macOS / Linux:**
|
|
20
|
+
```bash
|
|
21
|
+
export GROQ_API_KEY="your-groq-api-key"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
**Windows (PowerShell):**
|
|
25
|
+
```powershell
|
|
26
|
+
$env:GROQ_API_KEY="your-groq-api-key"
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
Once installed, you can use the `ft` or `ft-cli` commands.
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Initialize learning on a local repository
|
|
35
|
+
ft init [repoUrl]
|
|
36
|
+
|
|
37
|
+
# Print a brief, AI-powered onboarding summary
|
|
38
|
+
ft brief
|
|
39
|
+
|
|
40
|
+
# Show knowledge holders of a specific directory or file
|
|
41
|
+
ft owners <path>
|
|
42
|
+
|
|
43
|
+
# Show a code fragility map based on churn and hotfixes
|
|
44
|
+
ft risky
|
|
45
|
+
|
|
46
|
+
# Diagnose local setup, missing .env files, and runtime mismatches
|
|
47
|
+
ft setup
|
|
48
|
+
```
|
package/bin/ft.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brief.d.ts","sourceRoot":"","sources":["brief.ts"],"names":[],"mappings":"AAKA,wBAAsB,WAAW,kBA6BhC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { spinner, note } from '@clack/prompts';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
export async function handleBrief() {
|
|
6
|
+
const s = spinner();
|
|
7
|
+
s.start('Reading codebase structure and .ft metadata...');
|
|
8
|
+
const configPath = path.join(process.cwd(), '.ft', 'context.json');
|
|
9
|
+
if (!fs.existsSync(configPath)) {
|
|
10
|
+
s.stop(chalk.red('No local context found.'));
|
|
11
|
+
console.log('\nPlease run `ft init` first to index this repository.');
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
const rawData = fs.readFileSync(configPath, 'utf-8');
|
|
15
|
+
const context = JSON.parse(rawData);
|
|
16
|
+
s.stop('Repository analysis complete.');
|
|
17
|
+
note(`Project: ${chalk.bold(context.projectName)}
|
|
18
|
+
Primary Stack: ${chalk.yellow(context.stack)}
|
|
19
|
+
Entry Point: ${chalk.cyan(context.entryPoint)}
|
|
20
|
+
|
|
21
|
+
${chalk.bold('Known Pain Points:')}
|
|
22
|
+
${context.painPoints.map((p) => `• ${p}`).join('\n')}
|
|
23
|
+
|
|
24
|
+
${chalk.bold('Suggested Reading Order:')}
|
|
25
|
+
${context.readOrder.map((r, idx) => `${idx + 1}. ${r}`).join('\n')}`, '💡 Onboarding Brief');
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=brief.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brief.js","sourceRoot":"","sources":["brief.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,CAAC,GAAG,OAAO,EAAE,CAAC;IACpB,CAAC,CAAC,KAAK,CAAC,gDAAgD,CAAC,CAAC;IAE1D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,cAAc,CAAC,CAAC;IAEnE,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,yBAAyB,CAAC,CAAC,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,wDAAwD,CAAC,CAAC;QACtE,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAEpC,CAAC,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC;IAExC,IAAI,CACF,YAAY,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC;iBAC9B,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;eAC7B,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC;;EAE3C,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC;EAChC,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAS,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;;EAE1D,KAAK,CAAC,IAAI,CAAC,0BAA0B,CAAC;EACtC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAS,EAAE,GAAW,EAAE,EAAE,CAAC,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAChF,qBAAqB,CACtB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["init.ts"],"names":[],"mappings":"AAKA,wBAAsB,UAAU,CAAC,OAAO,EAAE,GAAG,iBAmB5C"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { generateRepoSummary } from '../engine/llm.js';
|
|
4
|
+
import { saveContext } from '../utils/config.js';
|
|
5
|
+
export async function handleInit(repoUrl) {
|
|
6
|
+
const cwd = process.cwd();
|
|
7
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
8
|
+
const pkgContent = fs.existsSync(pkgPath) ? fs.readFileSync(pkgPath, 'utf-8') : '{}';
|
|
9
|
+
// Quick file scanner (excluding node_modules / git)
|
|
10
|
+
const filesList = fs.readdirSync(cwd).filter((f) => !['node_modules', '.git', 'dist'].includes(f));
|
|
11
|
+
// Get AI insight
|
|
12
|
+
const aiInsight = await generateRepoSummary(path.basename(cwd), filesList, pkgContent);
|
|
13
|
+
saveContext({
|
|
14
|
+
projectName: path.basename(cwd),
|
|
15
|
+
stack: aiInsight.summary,
|
|
16
|
+
entryPoint: aiInsight.entryPoint,
|
|
17
|
+
painPoints: aiInsight.painPoints,
|
|
18
|
+
readOrder: aiInsight.readOrder,
|
|
19
|
+
createdAt: new Date().toISOString(),
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAY;IAC3C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAErF,oDAAoD;IACpD,MAAM,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAEnG,iBAAiB;IACjB,MAAM,SAAS,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;IAEvF,WAAW,CAAC;QACV,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;QAC/B,KAAK,EAAE,SAAS,CAAC,OAAO;QACxB,UAAU,EAAE,SAAS,CAAC,UAAU;QAChC,UAAU,EAAE,SAAS,CAAC,UAAU;QAChC,SAAS,EAAE,SAAS,CAAC,SAAS;QAC9B,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owners.d.ts","sourceRoot":"","sources":["owners.ts"],"names":[],"mappings":"AAAA,wBAAsB,YAAY,CAAC,IAAI,EAAE,MAAM,iBAAI"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"owners.js","sourceRoot":"","sources":["owners.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAY,IAAG,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risky.d.ts","sourceRoot":"","sources":["risky.ts"],"names":[],"mappings":"AAWA,wBAAsB,WAAW,kBA6ChC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { spinner, note } from '@clack/prompts';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { simpleGit } from 'simple-git';
|
|
4
|
+
export async function handleRisky() {
|
|
5
|
+
const s = spinner();
|
|
6
|
+
s.start('Analyzing git history & churn patterns...');
|
|
7
|
+
const git = simpleGit();
|
|
8
|
+
const log = await git.log({ maxCount: 200 }); // Scan last 200 commits
|
|
9
|
+
const fileStats = {};
|
|
10
|
+
for (const commit of log.all) {
|
|
11
|
+
const isHotfix = /fix|bug|hotfix|patch/i.test(commit.message);
|
|
12
|
+
// Get files changed in this commit
|
|
13
|
+
const diff = await git.show(['--name-only', '--oneline', commit.hash]);
|
|
14
|
+
const files = diff.split('\n').slice(1).filter(Boolean);
|
|
15
|
+
for (const file of files) {
|
|
16
|
+
if (!fileStats[file]) {
|
|
17
|
+
fileStats[file] = { total: 0, hotfixes: 0 };
|
|
18
|
+
}
|
|
19
|
+
fileStats[file].total += 1;
|
|
20
|
+
if (isHotfix)
|
|
21
|
+
fileStats[file].hotfixes += 1;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
s.stop('Fragility analysis complete.');
|
|
25
|
+
// Sort by risk score
|
|
26
|
+
const results = Object.entries(fileStats)
|
|
27
|
+
.map(([file, stats]) => {
|
|
28
|
+
let riskLevel = 'LOW';
|
|
29
|
+
if (stats.hotfixes >= 3 || stats.total > 15)
|
|
30
|
+
riskLevel = 'HIGH';
|
|
31
|
+
else if (stats.hotfixes >= 1 || stats.total > 7)
|
|
32
|
+
riskLevel = 'MEDIUM';
|
|
33
|
+
return { file, churnCount: stats.total, hotfixes: stats.hotfixes, riskLevel };
|
|
34
|
+
})
|
|
35
|
+
.filter((r) => r.riskLevel !== 'LOW')
|
|
36
|
+
.sort((a, b) => b.hotfixes - a.hotfixes);
|
|
37
|
+
const formattedOutput = results.slice(0, 5).map((r) => {
|
|
38
|
+
const icon = r.riskLevel === 'HIGH' ? chalk.red('🔴 HIGH RISK') : chalk.yellow('🟡 MEDIUM RISK');
|
|
39
|
+
return `${icon} ${chalk.bold(r.file)}\n └─ ${r.churnCount} commits, ${r.hotfixes} hotfixes detected`;
|
|
40
|
+
}).join('\n\n');
|
|
41
|
+
note(formattedOutput || chalk.green('No high-risk hotspots found!'), '🔥 Codebase Risk Map');
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=risky.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"risky.js","sourceRoot":"","sources":["risky.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["setup.ts"],"names":[],"mappings":"AAKA,wBAAsB,WAAW,kBAmChC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { spinner, note } from '@clack/prompts';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
export async function handleSetup() {
|
|
6
|
+
const s = spinner();
|
|
7
|
+
s.start('Diagnosing local runtime environment...');
|
|
8
|
+
const issues = [];
|
|
9
|
+
const passes = [];
|
|
10
|
+
// Check 1: .env vs .env.example
|
|
11
|
+
const cwd = process.cwd();
|
|
12
|
+
const hasEnv = fs.existsSync(path.join(cwd, '.env'));
|
|
13
|
+
const hasExample = fs.existsSync(path.join(cwd, '.env.example'));
|
|
14
|
+
if (!hasEnv && hasExample) {
|
|
15
|
+
issues.push(`Missing ${chalk.yellow('.env')} file! (Found .env.example)`);
|
|
16
|
+
}
|
|
17
|
+
else if (hasEnv) {
|
|
18
|
+
passes.push(`${chalk.green('✓')} Environment file .env present.`);
|
|
19
|
+
}
|
|
20
|
+
// Check 2: Node version check (.nvmrc or package.json engines)
|
|
21
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
22
|
+
if (fs.existsSync(pkgPath)) {
|
|
23
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
24
|
+
if (pkg.engines?.node) {
|
|
25
|
+
passes.push(`${chalk.green('✓')} Expected Node engine: ${pkg.engines.node} (Current: ${process.version})`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
s.stop('Setup diagnosis complete.');
|
|
29
|
+
const report = [
|
|
30
|
+
...passes,
|
|
31
|
+
...issues.map((i) => `${chalk.red('⚠️ ')} ${i}`),
|
|
32
|
+
].join('\n');
|
|
33
|
+
note(report, '🛠️ Setup Doctor');
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=setup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.js","sourceRoot":"","sources":["setup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,CAAC,KAAK,UAAU,WAAW;IAC/B,MAAM,CAAC,GAAG,OAAO,EAAE,CAAC;IACpB,CAAC,CAAC,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAEnD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,gCAAgC;IAChC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;IACrD,MAAM,UAAU,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC,CAAC;IAEjE,IAAI,CAAC,MAAM,IAAI,UAAU,EAAE,CAAC;QAC1B,MAAM,CAAC,IAAI,CAAC,WAAW,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,6BAA6B,CAAC,CAAC;IAC5E,CAAC;SAAM,IAAI,MAAM,EAAE,CAAC;QAClB,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,iCAAiC,CAAC,CAAC;IACpE,CAAC;IAED,+DAA+D;IAC/D,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAC/C,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1D,IAAI,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC;YACtB,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,0BAA0B,GAAG,CAAC,OAAO,CAAC,IAAI,cAAc,OAAO,CAAC,OAAO,GAAG,CAAC,CAAC;QAC7G,CAAC;IACH,CAAC;IAED,CAAC,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;IAEpC,MAAM,MAAM,GAAG;QACb,GAAG,MAAM;QACT,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;KACjD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,IAAI,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["git.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAwB1E"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { simpleGit } from 'simple-git';
|
|
2
|
+
const git = simpleGit();
|
|
3
|
+
export async function getFileOwners(filePath) {
|
|
4
|
+
const log = await git.log({ file: filePath });
|
|
5
|
+
const total = log.total;
|
|
6
|
+
if (total === 0)
|
|
7
|
+
return [];
|
|
8
|
+
const stats = {};
|
|
9
|
+
for (const commit of log.all) {
|
|
10
|
+
const author = commit.author_name;
|
|
11
|
+
if (!stats[author]) {
|
|
12
|
+
stats[author] = { count: 0, lastDate: commit.date };
|
|
13
|
+
}
|
|
14
|
+
stats[author].count += 1;
|
|
15
|
+
}
|
|
16
|
+
return Object.entries(stats)
|
|
17
|
+
.map(([author, data]) => ({
|
|
18
|
+
author,
|
|
19
|
+
commits: data.count,
|
|
20
|
+
percentage: Math.round((data.count / total) * 100),
|
|
21
|
+
lastTouched: data.lastDate,
|
|
22
|
+
}))
|
|
23
|
+
.sort((a, b) => b.commits - a.commits);
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=git.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAkB,MAAM,YAAY,CAAC;AAEvD,MAAM,GAAG,GAAc,SAAS,EAAE,CAAC;AASnC,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB;IAClD,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC9C,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC;IAExB,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAE3B,MAAM,KAAK,GAAwD,EAAE,CAAC;IAEtE,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,GAAG,EAAE,CAAC;QAC7B,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC;QAClC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YACnB,KAAK,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;QACtD,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;IAC3B,CAAC;IAED,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;SACzB,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QACxB,MAAM;QACN,OAAO,EAAE,IAAI,CAAC,KAAK;QACnB,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC;QAClD,WAAW,EAAE,IAAI,CAAC,QAAQ;KAC3B,CAAC,CAAC;SACF,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm.d.ts","sourceRoot":"","sources":["llm.ts"],"names":[],"mappings":"AAcA,wBAAsB,mBAAmB,CACvC,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,MAAM,EAAE,EACnB,kBAAkB,EAAE,MAAM,GACzB,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,UAAU,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC,CAqC7F"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import OpenAI from 'openai';
|
|
2
|
+
import dotenv from 'dotenv';
|
|
3
|
+
import * as url from 'url';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
const __dirname = url.fileURLToPath(new URL('.', import.meta.url));
|
|
6
|
+
// Attempt to load .env from the root of the CLI installation
|
|
7
|
+
dotenv.config({ path: path.resolve(__dirname, '../../../.env'), quiet: true });
|
|
8
|
+
const openai = new OpenAI({
|
|
9
|
+
apiKey: process.env.GROQ_API_KEY || 'missing-key',
|
|
10
|
+
baseURL: 'https://api.groq.com/openai/v1',
|
|
11
|
+
});
|
|
12
|
+
export async function generateRepoSummary(projectName, filesList, packageJsonContent) {
|
|
13
|
+
const prompt = `
|
|
14
|
+
You are an expert developer co-pilot summarizing a codebase for a new engineer.
|
|
15
|
+
Project Name: ${projectName}
|
|
16
|
+
File Tree Overview:
|
|
17
|
+
${filesList.join('\n')}
|
|
18
|
+
|
|
19
|
+
package.json:
|
|
20
|
+
${packageJsonContent}
|
|
21
|
+
|
|
22
|
+
Provide a JSON output matching this schema:
|
|
23
|
+
{
|
|
24
|
+
"summary": "1-2 sentence description of what this project does and its core stack",
|
|
25
|
+
"entryPoint": "the primary entry point file path",
|
|
26
|
+
"readOrder": ["file1", "file2", "file3"],
|
|
27
|
+
"painPoints": ["known architectural risk or complex folder"]
|
|
28
|
+
}
|
|
29
|
+
`;
|
|
30
|
+
try {
|
|
31
|
+
const response = await openai.chat.completions.create({
|
|
32
|
+
model: 'llama-3.3-70b-versatile',
|
|
33
|
+
messages: [{ role: 'user', content: prompt }],
|
|
34
|
+
response_format: { type: 'json_object' },
|
|
35
|
+
});
|
|
36
|
+
return JSON.parse(response.choices[0]?.message?.content || '{}');
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error("OpenAI Error:", error);
|
|
40
|
+
// Fallback if no API key or network failure
|
|
41
|
+
return {
|
|
42
|
+
summary: `${projectName} (Static Analysis)`,
|
|
43
|
+
entryPoint: 'src/index.ts',
|
|
44
|
+
readOrder: ['package.json', 'src/index.ts'],
|
|
45
|
+
painPoints: ['LLM key missing — run with GROQ_API_KEY for deep AI insights.'],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=llm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"llm.js","sourceRoot":"","sources":["llm.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,KAAK,GAAG,MAAM,KAAK,CAAC;AAC3B,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,IAAI,GAAG,CAAC,GAAG,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACnE,6DAA6D;AAC7D,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,eAAe,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAE/E,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,YAAY,IAAI,aAAa;IACjD,OAAO,EAAE,gCAAgC;CAC1C,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,WAAmB,EACnB,SAAmB,EACnB,kBAA0B;IAE1B,MAAM,MAAM,GAAG;;gBAED,WAAW;;EAEzB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC;;;EAGpB,kBAAkB;;;;;;;;;CASnB,CAAC;IAEA,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;YACpD,KAAK,EAAE,yBAAyB;YAChC,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;YAC7C,eAAe,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE;SACzC,CAAC,CAAC;QAEH,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,IAAI,IAAI,CAAC,CAAC;IACnE,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;QACtC,4CAA4C;QAC5C,OAAO;YACL,OAAO,EAAE,GAAG,WAAW,oBAAoB;YAC3C,UAAU,EAAE,cAAc;YAC1B,SAAS,EAAE,CAAC,cAAc,EAAE,cAAc,CAAC;YAC3C,UAAU,EAAE,CAAC,+DAA+D,CAAC;SAC9E,CAAC;IACJ,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanners.d.ts","sourceRoot":"","sources":["scanners.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scanners.js","sourceRoot":"","sources":["scanners.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":""}
|
package/bin/src/index.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import { intro, outro } from '@clack/prompts';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { handleInit } from './commands/init.js';
|
|
5
|
+
import { handleBrief } from './commands/brief.js';
|
|
6
|
+
import { handleOwners } from './commands/owners.js';
|
|
7
|
+
import { handleRisky } from './commands/risky.js';
|
|
8
|
+
import { handleSetup } from './commands/setup.js';
|
|
9
|
+
const program = new Command();
|
|
10
|
+
program
|
|
11
|
+
.command('risky')
|
|
12
|
+
.description('Show code fragility map based on churn and hotfixes')
|
|
13
|
+
.action(async () => handleRisky());
|
|
14
|
+
program
|
|
15
|
+
.command('setup')
|
|
16
|
+
.description('Diagnose local setup, missing .env files, and runtime mismatches')
|
|
17
|
+
.action(async () => handleSetup());
|
|
18
|
+
program
|
|
19
|
+
.name('ft')
|
|
20
|
+
.description('FrontTerrain — The Onboarding Co-Pilot for New Codebases')
|
|
21
|
+
.version('0.1.0');
|
|
22
|
+
// Header UI on execution
|
|
23
|
+
program.hook('preAction', () => {
|
|
24
|
+
intro(chalk.bgCyan.black(' FrontTerrain CLI (v0.1.0) '));
|
|
25
|
+
});
|
|
26
|
+
// Command definitions
|
|
27
|
+
program
|
|
28
|
+
.command('init [repoUrl]')
|
|
29
|
+
.description('Build local understanding map of the repository')
|
|
30
|
+
.action(async (repoUrl) => {
|
|
31
|
+
await handleInit(repoUrl);
|
|
32
|
+
outro(chalk.green('Initialization complete! Run `ft brief` to get started.'));
|
|
33
|
+
});
|
|
34
|
+
program
|
|
35
|
+
.command('brief')
|
|
36
|
+
.description('Print human-readable onboarding summary')
|
|
37
|
+
.action(async () => {
|
|
38
|
+
await handleBrief();
|
|
39
|
+
outro(chalk.cyan('Ready for your first task.'));
|
|
40
|
+
});
|
|
41
|
+
program
|
|
42
|
+
.command('owners <path>')
|
|
43
|
+
.description('Show actual file knowledge holders based on git history')
|
|
44
|
+
.action(async (path) => {
|
|
45
|
+
await handleOwners(path);
|
|
46
|
+
});
|
|
47
|
+
program.parse(process.argv);
|
|
48
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,qDAAqD,CAAC;KAClE,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;AAErC,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,kEAAkE,CAAC;KAC/E,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;AAGrC,OAAO;KACJ,IAAI,CAAC,IAAI,CAAC;KACV,WAAW,CAAC,0DAA0D,CAAC;KACvE,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,yBAAyB;AACzB,OAAO,CAAC,IAAI,CAAC,WAAW,EAAE,GAAG,EAAE;IAC7B,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC,CAAC;AAC3D,CAAC,CAAC,CAAC;AAEH,sBAAsB;AACtB,OAAO;KACJ,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CAAC,iDAAiD,CAAC;KAC9D,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;IACxB,MAAM,UAAU,CAAC,OAAO,CAAC,CAAC;IAC1B,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,yDAAyD,CAAC,CAAC,CAAC;AAChF,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,yCAAyC,CAAC;KACtD,MAAM,CAAC,KAAK,IAAI,EAAE;IACjB,MAAM,WAAW,EAAE,CAAC;IACpB,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC,CAAC;AAClD,CAAC,CAAC,CAAC;AAEL,OAAO;KACJ,OAAO,CAAC,eAAe,CAAC;KACxB,WAAW,CAAC,yDAAyD,CAAC;KACtE,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;IACrB,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["config.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAKD,wBAAgB,WAAW,CAAC,IAAI,EAAE,WAAW,QAK5C;AAED,wBAAgB,WAAW,IAAI,WAAW,GAAG,IAAI,CAGhD"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
const FT_DIR = path.join(process.cwd(), '.ft');
|
|
4
|
+
const CONTEXT_FILE = path.join(FT_DIR, 'context.json');
|
|
5
|
+
export function saveContext(data) {
|
|
6
|
+
if (!fs.existsSync(FT_DIR)) {
|
|
7
|
+
fs.mkdirSync(FT_DIR, { recursive: true });
|
|
8
|
+
}
|
|
9
|
+
fs.writeFileSync(CONTEXT_FILE, JSON.stringify(data, null, 2));
|
|
10
|
+
}
|
|
11
|
+
export function loadContext() {
|
|
12
|
+
if (!fs.existsSync(CONTEXT_FILE))
|
|
13
|
+
return null;
|
|
14
|
+
return JSON.parse(fs.readFileSync(CONTEXT_FILE, 'utf-8'));
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAWxB,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;AAC/C,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;AAEvD,MAAM,UAAU,WAAW,CAAC,IAAiB;IAC3C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IACD,EAAE,CAAC,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC;AAC5D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["logger.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["logger.ts"],"names":[],"mappings":""}
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "ft-scout",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "FrontTerrain — The Onboarding Co-Pilot for New Codebases",
|
|
6
|
+
"main": "index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"ft": "bin/ft.js"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
12
|
+
"build": "tsc"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"cli",
|
|
16
|
+
"onboarding",
|
|
17
|
+
"git",
|
|
18
|
+
"llm",
|
|
19
|
+
"ai"
|
|
20
|
+
],
|
|
21
|
+
"author": "rishi",
|
|
22
|
+
"license": "ISC",
|
|
23
|
+
"dependencies": {
|
|
24
|
+
"@clack/prompts": "^1.7.0",
|
|
25
|
+
"chalk": "^6.0.0",
|
|
26
|
+
"commander": "^15.0.0",
|
|
27
|
+
"dotenv": "^17.4.2",
|
|
28
|
+
"openai": "^7.1.0",
|
|
29
|
+
"simple-git": "^3.36.0"
|
|
30
|
+
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@types/node": "^26.1.2",
|
|
33
|
+
"tsx": "^4.23.1",
|
|
34
|
+
"typescript": "^7.0.2"
|
|
35
|
+
}
|
|
36
|
+
}
|