fathom-cli 0.1.2 → 0.1.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/dist/index.js +112 -54
- package/dist/index.js.map +1 -1
- package/package.json +15 -15
package/dist/index.js
CHANGED
|
@@ -127,7 +127,8 @@ var require_extend = __commonJS({
|
|
|
127
127
|
});
|
|
128
128
|
|
|
129
129
|
// src/index.ts
|
|
130
|
-
import
|
|
130
|
+
import "dotenv/config";
|
|
131
|
+
import { Command as Command15 } from "commander";
|
|
131
132
|
|
|
132
133
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
|
|
133
134
|
var external_exports = {};
|
|
@@ -5170,7 +5171,7 @@ var Processor = class _Processor extends CallableInstance {
|
|
|
5170
5171
|
assertParser("process", this.parser || this.Parser);
|
|
5171
5172
|
assertCompiler("process", this.compiler || this.Compiler);
|
|
5172
5173
|
return done ? executor(void 0, done) : new Promise(executor);
|
|
5173
|
-
function executor(
|
|
5174
|
+
function executor(resolve14, reject) {
|
|
5174
5175
|
const realFile = vfile(file);
|
|
5175
5176
|
const parseTree = (
|
|
5176
5177
|
/** @type {HeadTree extends undefined ? Node : HeadTree} */
|
|
@@ -5201,8 +5202,8 @@ var Processor = class _Processor extends CallableInstance {
|
|
|
5201
5202
|
function realDone(error, file2) {
|
|
5202
5203
|
if (error || !file2) {
|
|
5203
5204
|
reject(error);
|
|
5204
|
-
} else if (
|
|
5205
|
-
|
|
5205
|
+
} else if (resolve14) {
|
|
5206
|
+
resolve14(file2);
|
|
5206
5207
|
} else {
|
|
5207
5208
|
ok(done, "`done` is defined if `resolve` is not");
|
|
5208
5209
|
done(void 0, file2);
|
|
@@ -5304,7 +5305,7 @@ var Processor = class _Processor extends CallableInstance {
|
|
|
5304
5305
|
file = void 0;
|
|
5305
5306
|
}
|
|
5306
5307
|
return done ? executor(void 0, done) : new Promise(executor);
|
|
5307
|
-
function executor(
|
|
5308
|
+
function executor(resolve14, reject) {
|
|
5308
5309
|
ok(
|
|
5309
5310
|
typeof file !== "function",
|
|
5310
5311
|
"`file` can\u2019t be a `done` anymore, we checked"
|
|
@@ -5318,8 +5319,8 @@ var Processor = class _Processor extends CallableInstance {
|
|
|
5318
5319
|
);
|
|
5319
5320
|
if (error) {
|
|
5320
5321
|
reject(error);
|
|
5321
|
-
} else if (
|
|
5322
|
-
|
|
5322
|
+
} else if (resolve14) {
|
|
5323
|
+
resolve14(resultingTree);
|
|
5323
5324
|
} else {
|
|
5324
5325
|
ok(done, "`done` is defined if `resolve` is not");
|
|
5325
5326
|
done(void 0, resultingTree, file2);
|
|
@@ -8147,10 +8148,10 @@ function resolveAll(constructs2, events, context) {
|
|
|
8147
8148
|
const called = [];
|
|
8148
8149
|
let index2 = -1;
|
|
8149
8150
|
while (++index2 < constructs2.length) {
|
|
8150
|
-
const
|
|
8151
|
-
if (
|
|
8152
|
-
events =
|
|
8153
|
-
called.push(
|
|
8151
|
+
const resolve14 = constructs2[index2].resolveAll;
|
|
8152
|
+
if (resolve14 && !called.includes(resolve14)) {
|
|
8153
|
+
events = resolve14(events, context);
|
|
8154
|
+
called.push(resolve14);
|
|
8154
8155
|
}
|
|
8155
8156
|
}
|
|
8156
8157
|
return events;
|
|
@@ -18051,11 +18052,67 @@ var initCommand = new Command12("init").description("Initialize Fathom global co
|
|
|
18051
18052
|
);
|
|
18052
18053
|
});
|
|
18053
18054
|
|
|
18054
|
-
// src/commands/
|
|
18055
|
+
// src/commands/rename.ts
|
|
18055
18056
|
import { Command as Command13 } from "commander";
|
|
18056
|
-
import { writeFileSync as writeFileSync5, existsSync as existsSync12 } from "fs";
|
|
18057
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync5, existsSync as existsSync12 } from "fs";
|
|
18057
18058
|
import { resolve as resolve12 } from "path";
|
|
18058
18059
|
import chalk14 from "chalk";
|
|
18060
|
+
var renameCommand = new Command13("rename").description("Rename the project in all .claude/te/ config files").argument("<name>", "New project name").action((name) => {
|
|
18061
|
+
const baseDir = process.cwd();
|
|
18062
|
+
const teDir = resolve12(baseDir, ".claude", "te");
|
|
18063
|
+
if (!existsSync12(teDir)) {
|
|
18064
|
+
console.error(
|
|
18065
|
+
chalk14.red("\n Error: .claude/te/ not found. Run `fathom setup` first.\n")
|
|
18066
|
+
);
|
|
18067
|
+
process.exit(1);
|
|
18068
|
+
}
|
|
18069
|
+
const jsonFiles = [
|
|
18070
|
+
resolve12(teDir, "config.json"),
|
|
18071
|
+
resolve12(teDir, "registry.json"),
|
|
18072
|
+
resolve12(teDir, "tracking", "summary.json")
|
|
18073
|
+
];
|
|
18074
|
+
let oldName = "unnamed";
|
|
18075
|
+
let updated = 0;
|
|
18076
|
+
for (const filePath of jsonFiles) {
|
|
18077
|
+
if (!existsSync12(filePath)) continue;
|
|
18078
|
+
const data = JSON.parse(readFileSync12(filePath, "utf-8"));
|
|
18079
|
+
if (data.project) {
|
|
18080
|
+
oldName = data.project;
|
|
18081
|
+
data.project = name;
|
|
18082
|
+
writeFileSync5(filePath, JSON.stringify(data, null, 2) + "\n");
|
|
18083
|
+
updated++;
|
|
18084
|
+
}
|
|
18085
|
+
}
|
|
18086
|
+
const skillPath = resolve12(baseDir, ".claude", "skills", "fathom", "SKILL.md");
|
|
18087
|
+
if (existsSync12(skillPath)) {
|
|
18088
|
+
const content3 = readFileSync12(skillPath, "utf-8");
|
|
18089
|
+
const newContent = content3.replaceAll(oldName, name);
|
|
18090
|
+
if (newContent !== content3) {
|
|
18091
|
+
writeFileSync5(skillPath, newContent);
|
|
18092
|
+
updated++;
|
|
18093
|
+
}
|
|
18094
|
+
}
|
|
18095
|
+
const hookPath = resolve12(baseDir, ".claude", "hooks", "te-session-sync.sh");
|
|
18096
|
+
if (existsSync12(hookPath)) {
|
|
18097
|
+
const content3 = readFileSync12(hookPath, "utf-8");
|
|
18098
|
+
const newContent = content3.replaceAll(oldName, name);
|
|
18099
|
+
if (newContent !== content3) {
|
|
18100
|
+
writeFileSync5(hookPath, newContent);
|
|
18101
|
+
updated++;
|
|
18102
|
+
}
|
|
18103
|
+
}
|
|
18104
|
+
console.log(
|
|
18105
|
+
chalk14.bold(`
|
|
18106
|
+
Renamed "${oldName}" \u2192 "${name}" (${updated} files updated)
|
|
18107
|
+
`)
|
|
18108
|
+
);
|
|
18109
|
+
});
|
|
18110
|
+
|
|
18111
|
+
// src/commands/research.ts
|
|
18112
|
+
import { Command as Command14 } from "commander";
|
|
18113
|
+
import { writeFileSync as writeFileSync6, existsSync as existsSync13 } from "fs";
|
|
18114
|
+
import { resolve as resolve13 } from "path";
|
|
18115
|
+
import chalk15 from "chalk";
|
|
18059
18116
|
|
|
18060
18117
|
// src/fetchers/types.ts
|
|
18061
18118
|
var RemoteManifest = external_exports.object({
|
|
@@ -18355,19 +18412,19 @@ function generateAgentsYaml(recommendations) {
|
|
|
18355
18412
|
|
|
18356
18413
|
// src/commands/research.ts
|
|
18357
18414
|
function findDataDir2() {
|
|
18358
|
-
const bundled =
|
|
18359
|
-
if (
|
|
18360
|
-
return
|
|
18415
|
+
const bundled = resolve13(import.meta.dirname ?? __dirname, "data");
|
|
18416
|
+
if (existsSync13(resolve13(bundled, "models.yaml"))) return bundled;
|
|
18417
|
+
return resolve13(import.meta.dirname ?? __dirname, "../../../../data");
|
|
18361
18418
|
}
|
|
18362
|
-
var researchCommand = new
|
|
18363
|
-
console.log(
|
|
18364
|
-
console.log(
|
|
18419
|
+
var researchCommand = new Command14("research").description("Check and update model pricing data (fetches live data)").option("--update", "Update local data files with latest pricing").option("--sync", "Also sync updated pricing to Convex").option("--check", "Check for differences without updating (default)").option("--offline", "Skip remote fetches, use local data only").option("--verbose", "Show fetch sources and timing details").action(async (options) => {
|
|
18420
|
+
console.log(chalk15.bold("\nFathom \u2014 Research: Model Pricing"));
|
|
18421
|
+
console.log(chalk15.dim("\u2500".repeat(55)));
|
|
18365
18422
|
const startTime = Date.now();
|
|
18366
18423
|
let localData;
|
|
18367
18424
|
try {
|
|
18368
18425
|
localData = loadData();
|
|
18369
18426
|
} catch {
|
|
18370
|
-
console.log(
|
|
18427
|
+
console.log(chalk15.yellow(" Warning: could not load local data files"));
|
|
18371
18428
|
localData = { models: [], recommendations: {} };
|
|
18372
18429
|
}
|
|
18373
18430
|
const [pricingResult, intelligenceResult] = await Promise.all([
|
|
@@ -18379,18 +18436,18 @@ var researchCommand = new Command13("research").description("Check and update mo
|
|
|
18379
18436
|
]);
|
|
18380
18437
|
if (options.verbose) {
|
|
18381
18438
|
const elapsed = Date.now() - startTime;
|
|
18382
|
-
console.log(
|
|
18439
|
+
console.log(chalk15.dim(`
|
|
18383
18440
|
Fetch time: ${elapsed}ms`));
|
|
18384
|
-
console.log(
|
|
18441
|
+
console.log(chalk15.dim(` Pricing source: ${pricingResult.source}`));
|
|
18385
18442
|
if (intelligenceResult) {
|
|
18386
|
-
console.log(
|
|
18443
|
+
console.log(chalk15.dim(` Intelligence source: ${intelligenceResult.source}`));
|
|
18387
18444
|
}
|
|
18388
18445
|
}
|
|
18389
18446
|
if (pricingResult.stale) {
|
|
18390
|
-
console.log(
|
|
18447
|
+
console.log(chalk15.yellow(`
|
|
18391
18448
|
\u26A0 Using local data (${pricingResult.error ?? "stale"})`));
|
|
18392
18449
|
} else {
|
|
18393
|
-
console.log(
|
|
18450
|
+
console.log(chalk15.green(`
|
|
18394
18451
|
Pricing: live data (manifest v${pricingResult.data.manifestVersion}, ${pricingResult.data.manifestDate})`));
|
|
18395
18452
|
}
|
|
18396
18453
|
const mergeResult = mergePricingData(
|
|
@@ -18407,20 +18464,20 @@ var researchCommand = new Command13("research").description("Check and update mo
|
|
|
18407
18464
|
displayRecommendations(mergeResult);
|
|
18408
18465
|
if (options.update) {
|
|
18409
18466
|
const dataDir = findDataDir2();
|
|
18410
|
-
const modelsPath =
|
|
18411
|
-
const agentsPath =
|
|
18412
|
-
|
|
18413
|
-
console.log(
|
|
18467
|
+
const modelsPath = resolve13(dataDir, "models.yaml");
|
|
18468
|
+
const agentsPath = resolve13(dataDir, "agents.yaml");
|
|
18469
|
+
writeFileSync6(modelsPath, generateModelsYaml(mergeResult.models.merged));
|
|
18470
|
+
console.log(chalk15.green(`
|
|
18414
18471
|
Updated: ${modelsPath}`));
|
|
18415
|
-
|
|
18416
|
-
console.log(
|
|
18472
|
+
writeFileSync6(agentsPath, generateAgentsYaml(mergeResult.recommendations.merged));
|
|
18473
|
+
console.log(chalk15.green(` Updated: ${agentsPath}`));
|
|
18417
18474
|
}
|
|
18418
18475
|
if (options.sync) {
|
|
18419
18476
|
await syncToConvex(mergeResult);
|
|
18420
18477
|
}
|
|
18421
18478
|
if (options.verbose) {
|
|
18422
18479
|
const totalElapsed = Date.now() - startTime;
|
|
18423
|
-
console.log(
|
|
18480
|
+
console.log(chalk15.dim(`
|
|
18424
18481
|
Total time: ${totalElapsed}ms`));
|
|
18425
18482
|
}
|
|
18426
18483
|
console.log();
|
|
@@ -18428,29 +18485,29 @@ var researchCommand = new Command13("research").description("Check and update mo
|
|
|
18428
18485
|
function displayPricingReport(result) {
|
|
18429
18486
|
const { models } = result;
|
|
18430
18487
|
if (models.added === 0 && models.updated === 0) {
|
|
18431
|
-
console.log(
|
|
18432
|
-
console.log(
|
|
18488
|
+
console.log(chalk15.green(` All model pricing is up to date.`));
|
|
18489
|
+
console.log(chalk15.dim(` ${models.merged.length} models checked.`));
|
|
18433
18490
|
} else {
|
|
18434
18491
|
if (models.updated > 0) {
|
|
18435
|
-
console.log(
|
|
18492
|
+
console.log(chalk15.yellow(`
|
|
18436
18493
|
${models.updated} pricing change(s) found:`));
|
|
18437
18494
|
for (const change of models.changes) {
|
|
18438
18495
|
if (change.status === "updated" && change.fields) {
|
|
18439
18496
|
for (const f of change.fields) {
|
|
18440
|
-
console.log(
|
|
18497
|
+
console.log(chalk15.dim(` ${change.name}: ${f.field} ${f.old} \u2192 ${f.new}`));
|
|
18441
18498
|
}
|
|
18442
18499
|
}
|
|
18443
18500
|
}
|
|
18444
18501
|
}
|
|
18445
18502
|
if (models.added > 0) {
|
|
18446
|
-
console.log(
|
|
18503
|
+
console.log(chalk15.yellow(`
|
|
18447
18504
|
${models.added} new model(s) found:`));
|
|
18448
18505
|
for (const change of models.changes) {
|
|
18449
18506
|
if (change.status === "added") {
|
|
18450
18507
|
const m = models.merged.find((x) => x.id === change.id);
|
|
18451
18508
|
if (m) {
|
|
18452
18509
|
console.log(
|
|
18453
|
-
|
|
18510
|
+
chalk15.dim(` ${m.name} (${m.tier}): $${m.input_per_mtok}/$${m.output_per_mtok} per MTok`)
|
|
18454
18511
|
);
|
|
18455
18512
|
}
|
|
18456
18513
|
}
|
|
@@ -18460,39 +18517,39 @@ function displayPricingReport(result) {
|
|
|
18460
18517
|
}
|
|
18461
18518
|
function displayIntelligence(intelligence) {
|
|
18462
18519
|
if (intelligence.suggestions.length === 0) {
|
|
18463
|
-
console.log(
|
|
18520
|
+
console.log(chalk15.dim(`
|
|
18464
18521
|
Intelligence: ${intelligence.summary}`));
|
|
18465
18522
|
return;
|
|
18466
18523
|
}
|
|
18467
|
-
console.log(
|
|
18524
|
+
console.log(chalk15.cyan(`
|
|
18468
18525
|
Intelligence suggestions (${intelligence.suggestions.length}):`));
|
|
18469
18526
|
for (const s of intelligence.suggestions) {
|
|
18470
|
-
const badge = s.confidence === "high" ?
|
|
18471
|
-
const model = s.model ?
|
|
18527
|
+
const badge = s.confidence === "high" ? chalk15.red("HIGH") : s.confidence === "medium" ? chalk15.yellow("MED") : chalk15.dim("LOW");
|
|
18528
|
+
const model = s.model ? chalk15.dim(` [${s.model}]`) : "";
|
|
18472
18529
|
console.log(` ${badge} ${s.description}${model}`);
|
|
18473
18530
|
}
|
|
18474
|
-
console.log(
|
|
18475
|
-
console.log(
|
|
18531
|
+
console.log(chalk15.dim(` Summary: ${intelligence.summary}`));
|
|
18532
|
+
console.log(chalk15.dim(` Note: Task profiles are team-calibrated and shown as suggestions only.`));
|
|
18476
18533
|
}
|
|
18477
18534
|
function displayRecommendations(result) {
|
|
18478
18535
|
const { recommendations } = result;
|
|
18479
18536
|
if (recommendations.updated > 0 || recommendations.added > 0) {
|
|
18480
|
-
console.log(
|
|
18537
|
+
console.log(chalk15.yellow(`
|
|
18481
18538
|
Recommendation changes:`));
|
|
18482
18539
|
for (const change of recommendations.changes) {
|
|
18483
18540
|
if (change.status === "updated") {
|
|
18484
|
-
console.log(
|
|
18541
|
+
console.log(chalk15.dim(` ${change.category}: ${change.oldModel} \u2192 ${change.newModel}`));
|
|
18485
18542
|
} else if (change.status === "added") {
|
|
18486
|
-
console.log(
|
|
18543
|
+
console.log(chalk15.dim(` ${change.category}: ${change.newModel} (new)`));
|
|
18487
18544
|
}
|
|
18488
18545
|
}
|
|
18489
18546
|
}
|
|
18490
|
-
console.log(
|
|
18491
|
-
console.log(
|
|
18492
|
-
console.log(
|
|
18493
|
-
console.log(
|
|
18547
|
+
console.log(chalk15.dim("\n Current model recommendations:"));
|
|
18548
|
+
console.log(chalk15.dim(" S/M complexity \u2192 Haiku 4.5 ($1/$5 per MTok) \u2014 fast, cheap"));
|
|
18549
|
+
console.log(chalk15.dim(" L complexity \u2192 Sonnet 4.6 ($3/$15 per MTok) \u2014 balanced"));
|
|
18550
|
+
console.log(chalk15.dim(" XL complexity \u2192 Opus 4.6 ($15/$75 per MTok) \u2014 highest quality"));
|
|
18494
18551
|
console.log(
|
|
18495
|
-
|
|
18552
|
+
chalk15.dim("\n Tip: Enable prompt caching to save 90% on input tokens for repeated context.")
|
|
18496
18553
|
);
|
|
18497
18554
|
}
|
|
18498
18555
|
async function syncToConvex(result) {
|
|
@@ -18518,12 +18575,12 @@ async function syncToConvex(result) {
|
|
|
18518
18575
|
}
|
|
18519
18576
|
logConvexStatus(synced > 0);
|
|
18520
18577
|
if (synced > 0) {
|
|
18521
|
-
console.log(
|
|
18578
|
+
console.log(chalk15.dim(` ${synced} models synced to Convex.`));
|
|
18522
18579
|
}
|
|
18523
18580
|
}
|
|
18524
18581
|
|
|
18525
18582
|
// src/index.ts
|
|
18526
|
-
var program = new
|
|
18583
|
+
var program = new Command15();
|
|
18527
18584
|
program.name("fathom").description("Workflow intelligence platform for AI-augmented development").version(VERSION);
|
|
18528
18585
|
program.addCommand(analyzeCommand);
|
|
18529
18586
|
program.addCommand(pricingCommand);
|
|
@@ -18537,6 +18594,7 @@ program.addCommand(validateCommand);
|
|
|
18537
18594
|
program.addCommand(velocityCommand);
|
|
18538
18595
|
program.addCommand(intakeCommand);
|
|
18539
18596
|
program.addCommand(initCommand);
|
|
18597
|
+
program.addCommand(renameCommand);
|
|
18540
18598
|
program.addCommand(researchCommand);
|
|
18541
18599
|
program.parse();
|
|
18542
18600
|
/*! Bundled license information:
|