@a-company/paradigm 1.5.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/README.md +142 -0
- package/dist/accept-orchestration-CWZNCGZX.js +188 -0
- package/dist/agents-suggest-35LIQKDH.js +83 -0
- package/dist/aggregate-W7Q6VIM2.js +88 -0
- package/dist/auto-IU7VN55K.js +470 -0
- package/dist/beacon-B47XSTL7.js +251 -0
- package/dist/chunk-2M6OSOIG.js +1302 -0
- package/dist/chunk-4NCFWYGG.js +110 -0
- package/dist/chunk-5C4SGQKH.js +705 -0
- package/dist/chunk-5GOA7WYD.js +1095 -0
- package/dist/chunk-5JGJACDU.js +37 -0
- package/dist/chunk-6QC3YGB6.js +114 -0
- package/dist/chunk-753RICFF.js +325 -0
- package/dist/chunk-AD2LSCHB.js +1595 -0
- package/dist/chunk-CHSHON3O.js +669 -0
- package/dist/chunk-ELLR7WP6.js +3175 -0
- package/dist/chunk-ILOWBJRC.js +12 -0
- package/dist/chunk-IRKUEJVW.js +405 -0
- package/dist/chunk-MC7XC7XQ.js +533 -0
- package/dist/chunk-MO4EEYFW.js +38 -0
- package/dist/chunk-MQWH7PFI.js +13366 -0
- package/dist/chunk-N6PJAPDE.js +364 -0
- package/dist/chunk-PBHIFAL4.js +259 -0
- package/dist/chunk-PMXRGPRQ.js +305 -0
- package/dist/chunk-PW2EXJQT.js +689 -0
- package/dist/chunk-TAP5N3HH.js +245 -0
- package/dist/chunk-THFVK5AE.js +148 -0
- package/dist/chunk-UM54F7G5.js +1533 -0
- package/dist/chunk-UUZ2DMG5.js +185 -0
- package/dist/chunk-WS5KM7OL.js +780 -0
- package/dist/chunk-YDNKXH4Z.js +2316 -0
- package/dist/chunk-YO6DVTL7.js +99 -0
- package/dist/claude-SUYNN72C.js +362 -0
- package/dist/claude-cli-OF43XAO3.js +276 -0
- package/dist/claude-code-PW6SKD2M.js +126 -0
- package/dist/claude-code-teams-JLZ5IXB6.js +199 -0
- package/dist/constellation-K3CIQCHI.js +225 -0
- package/dist/cost-AEK6R7HK.js +174 -0
- package/dist/cost-KYXIQ62X.js +93 -0
- package/dist/cursor-cli-IHJMPRCW.js +269 -0
- package/dist/cursorrules-KI5QWHIX.js +84 -0
- package/dist/diff-AJJ5H6HV.js +125 -0
- package/dist/dist-7MPIRMTZ-IOQOREMZ.js +10866 -0
- package/dist/dist-NHJQVVUW.js +68 -0
- package/dist/dist-ZEMSQV74.js +20 -0
- package/dist/doctor-6Y6L6HEB.js +11 -0
- package/dist/echo-VYZW3OTT.js +248 -0
- package/dist/export-R4FJ5NOH.js +38 -0
- package/dist/history-EVO3L6SC.js +277 -0
- package/dist/hooks-MBWE4ILT.js +12 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +568 -0
- package/dist/lint-HXKTWRNO.js +316 -0
- package/dist/manual-Y3QOXWYA.js +204 -0
- package/dist/mcp.js +14745 -0
- package/dist/orchestrate-4ZH5GUQH.js +323 -0
- package/dist/probe-OYCP4JYG.js +151 -0
- package/dist/promote-Z52ZJTJU.js +181 -0
- package/dist/providers-4PGPZEWP.js +104 -0
- package/dist/remember-6VZ74B7E.js +77 -0
- package/dist/ripple-SBQOSTZD.js +215 -0
- package/dist/sentinel-LCFD56OJ.js +43 -0
- package/dist/server-F5ITNK6T.js +9846 -0
- package/dist/server-T6WIFYRQ.js +16076 -0
- package/dist/setup-DF4F3ICN.js +25 -0
- package/dist/setup-JHBPZAG7.js +296 -0
- package/dist/shift-HKIAP4ZN.js +226 -0
- package/dist/snapshot-GTVPRYZG.js +62 -0
- package/dist/spawn-BJRQA2NR.js +196 -0
- package/dist/summary-H6J6N6PJ.js +140 -0
- package/dist/switch-6EANJ7O6.js +232 -0
- package/dist/sync-BEOCW7TZ.js +11 -0
- package/dist/team-NWP2KJAB.js +32 -0
- package/dist/test-MA5TWJQV.js +934 -0
- package/dist/thread-JCJVRUQR.js +258 -0
- package/dist/triage-ETVXXFMV.js +1880 -0
- package/dist/tutorial-L5Q3ZDHK.js +666 -0
- package/dist/university-R2WDQLSI.js +40 -0
- package/dist/upgrade-5B3YGGC6.js +550 -0
- package/dist/validate-F3YHBCRZ.js +39 -0
- package/dist/validate-QEEY6KFS.js +64 -0
- package/dist/watch-4LT4O6K7.js +123 -0
- package/dist/watch-6IIWPWDN.js +111 -0
- package/dist/wisdom-LRM4FFCH.js +319 -0
- package/package.json +68 -0
- package/templates/paradigm/config.yaml +175 -0
- package/templates/paradigm/docs/commands.md +727 -0
- package/templates/paradigm/docs/decisions/000-template.md +47 -0
- package/templates/paradigm/docs/decisions/README.md +26 -0
- package/templates/paradigm/docs/error-patterns.md +215 -0
- package/templates/paradigm/docs/patterns.md +358 -0
- package/templates/paradigm/docs/queries.md +200 -0
- package/templates/paradigm/docs/troubleshooting.md +477 -0
- package/templates/paradigm/echoes.yaml +25 -0
- package/templates/paradigm/prompts/add-feature.md +152 -0
- package/templates/paradigm/prompts/add-gate.md +117 -0
- package/templates/paradigm/prompts/debug-auth.md +174 -0
- package/templates/paradigm/prompts/implement-ftux.md +722 -0
- package/templates/paradigm/prompts/implement-sandbox.md +651 -0
- package/templates/paradigm/prompts/read-docs.md +84 -0
- package/templates/paradigm/prompts/refactor.md +106 -0
- package/templates/paradigm/prompts/run-e2e-tests.md +340 -0
- package/templates/paradigm/prompts/trace-flow.md +202 -0
- package/templates/paradigm/prompts/validate-portals.md +279 -0
- package/templates/paradigm/specs/context-tracking.md +200 -0
- package/templates/paradigm/specs/context.md +461 -0
- package/templates/paradigm/specs/disciplines.md +413 -0
- package/templates/paradigm/specs/history.md +339 -0
- package/templates/paradigm/specs/logger.md +303 -0
- package/templates/paradigm/specs/navigator.md +236 -0
- package/templates/paradigm/specs/purpose.md +265 -0
- package/templates/paradigm/specs/scan.md +177 -0
- package/templates/paradigm/specs/symbols.md +451 -0
- package/templates/paradigm/specs/wisdom.md +294 -0
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
aggregateFromDirectory,
|
|
4
|
+
buildSymbolIndex,
|
|
5
|
+
getAllSymbols,
|
|
6
|
+
getSymbolCounts,
|
|
7
|
+
getSymbolsByType
|
|
8
|
+
} from "./chunk-5C4SGQKH.js";
|
|
9
|
+
import "./chunk-PW2EXJQT.js";
|
|
10
|
+
import "./chunk-IRKUEJVW.js";
|
|
11
|
+
import {
|
|
12
|
+
log
|
|
13
|
+
} from "./chunk-4NCFWYGG.js";
|
|
14
|
+
import "./chunk-MO4EEYFW.js";
|
|
15
|
+
|
|
16
|
+
// src/commands/constellation.ts
|
|
17
|
+
import * as fs from "fs";
|
|
18
|
+
import * as path from "path";
|
|
19
|
+
import chalk from "chalk";
|
|
20
|
+
import ora from "ora";
|
|
21
|
+
function categorizeReferences(refs) {
|
|
22
|
+
const categories = {
|
|
23
|
+
gates: [],
|
|
24
|
+
signals: [],
|
|
25
|
+
components: [],
|
|
26
|
+
flows: [],
|
|
27
|
+
aspects: []
|
|
28
|
+
};
|
|
29
|
+
for (const ref of refs) {
|
|
30
|
+
if (!ref || ref.length < 2) continue;
|
|
31
|
+
const prefix = ref[0];
|
|
32
|
+
switch (prefix) {
|
|
33
|
+
case "^":
|
|
34
|
+
categories.gates.push(ref);
|
|
35
|
+
break;
|
|
36
|
+
case "!":
|
|
37
|
+
categories.signals.push(ref);
|
|
38
|
+
break;
|
|
39
|
+
case "#":
|
|
40
|
+
categories.components.push(ref);
|
|
41
|
+
break;
|
|
42
|
+
case "$":
|
|
43
|
+
categories.flows.push(ref);
|
|
44
|
+
break;
|
|
45
|
+
case "~":
|
|
46
|
+
categories.aspects.push(ref);
|
|
47
|
+
break;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return categories;
|
|
51
|
+
}
|
|
52
|
+
function buildConstellation(index, projectName) {
|
|
53
|
+
const stars = {};
|
|
54
|
+
const orbits = {};
|
|
55
|
+
const counts = getSymbolCounts(index);
|
|
56
|
+
const allSymbols = getAllSymbols(index);
|
|
57
|
+
for (const entry of allSymbols) {
|
|
58
|
+
const categories = categorizeReferences(entry.references);
|
|
59
|
+
const star = {
|
|
60
|
+
type: entry.type,
|
|
61
|
+
path: entry.filePath,
|
|
62
|
+
references: entry.references,
|
|
63
|
+
referencedBy: entry.referencedBy
|
|
64
|
+
};
|
|
65
|
+
if (entry.description) star.description = entry.description;
|
|
66
|
+
if (entry.tags && entry.tags.length > 0) star.tags = entry.tags;
|
|
67
|
+
if (categories.gates.length > 0) star.gates = categories.gates;
|
|
68
|
+
if (categories.signals.length > 0) star.signals = categories.signals;
|
|
69
|
+
if (categories.components.length > 0) star.components = categories.components;
|
|
70
|
+
if (categories.flows.length > 0) star.flows = categories.flows;
|
|
71
|
+
if (categories.aspects.length > 0) star.aspects = categories.aspects;
|
|
72
|
+
stars[entry.symbol] = star;
|
|
73
|
+
}
|
|
74
|
+
const flowSymbols = getSymbolsByType(index, "flow");
|
|
75
|
+
for (const flow of flowSymbols) {
|
|
76
|
+
const data = flow.data;
|
|
77
|
+
const sequence = data?.sequence || data?.gates || flow.references;
|
|
78
|
+
orbits[flow.symbol] = {
|
|
79
|
+
description: flow.description,
|
|
80
|
+
sequence
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return {
|
|
84
|
+
version: "1.0",
|
|
85
|
+
generated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
86
|
+
project: projectName,
|
|
87
|
+
stats: {
|
|
88
|
+
components: counts.component,
|
|
89
|
+
flows: counts.flow,
|
|
90
|
+
gates: counts.gate,
|
|
91
|
+
signals: counts.signal,
|
|
92
|
+
aspects: counts.aspect,
|
|
93
|
+
total: Object.values(counts).reduce((a, b) => a + b, 0)
|
|
94
|
+
},
|
|
95
|
+
stars,
|
|
96
|
+
orbits
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
async function constellationCommand(targetPath, options = {}) {
|
|
100
|
+
const cwd = process.cwd();
|
|
101
|
+
const absolutePath = targetPath ? path.resolve(cwd, targetPath) : cwd;
|
|
102
|
+
const projectName = path.basename(absolutePath);
|
|
103
|
+
const format = options.format || "json";
|
|
104
|
+
if (!options.quiet) {
|
|
105
|
+
console.log(chalk.blue("\n\u2728 Building Constellation...\n"));
|
|
106
|
+
}
|
|
107
|
+
const spinner = ora("Aggregating symbols...").start();
|
|
108
|
+
const tracker = log.command("constellation").start("Building constellation", { project: projectName });
|
|
109
|
+
try {
|
|
110
|
+
const result = await aggregateFromDirectory(absolutePath);
|
|
111
|
+
const index = buildSymbolIndex(result);
|
|
112
|
+
log.operation("aggregate").debug("Symbols aggregated", { count: getAllSymbols(index).length });
|
|
113
|
+
spinner.text = "Building constellation...";
|
|
114
|
+
const constellation = buildConstellation(index, projectName);
|
|
115
|
+
const paradigmDir = path.join(absolutePath, ".paradigm");
|
|
116
|
+
if (!fs.existsSync(paradigmDir)) {
|
|
117
|
+
fs.mkdirSync(paradigmDir, { recursive: true });
|
|
118
|
+
}
|
|
119
|
+
const outputPath = options.output || path.join(paradigmDir, `constellation.${format}`);
|
|
120
|
+
let content;
|
|
121
|
+
if (format === "yaml") {
|
|
122
|
+
content = serializeToYaml(constellation);
|
|
123
|
+
} else {
|
|
124
|
+
content = JSON.stringify(constellation, null, 2);
|
|
125
|
+
}
|
|
126
|
+
fs.writeFileSync(outputPath, content, "utf8");
|
|
127
|
+
log.component("constellation-file").success("Constellation written", { path: outputPath, format });
|
|
128
|
+
spinner.succeed("Constellation built");
|
|
129
|
+
tracker.success("Constellation built", { path: outputPath, stars: Object.keys(constellation.stars).length });
|
|
130
|
+
if (!options.quiet) {
|
|
131
|
+
console.log(chalk.white("\nConstellation Stats"));
|
|
132
|
+
console.log(chalk.gray("\u2500".repeat(40)));
|
|
133
|
+
const stats = constellation.stats;
|
|
134
|
+
const statLines = [
|
|
135
|
+
{ symbol: "#", name: "Components", count: stats.components, color: chalk.green },
|
|
136
|
+
{ symbol: "$", name: "Flows", count: stats.flows, color: chalk.yellow },
|
|
137
|
+
{ symbol: "^", name: "Gates", count: stats.gates, color: chalk.red },
|
|
138
|
+
{ symbol: "!", name: "Signals", count: stats.signals, color: chalk.cyan },
|
|
139
|
+
{ symbol: "~", name: "Aspects", count: stats.aspects, color: chalk.magenta }
|
|
140
|
+
];
|
|
141
|
+
for (const { symbol, name, count, color } of statLines) {
|
|
142
|
+
if (count > 0) {
|
|
143
|
+
console.log(` ${color(symbol)} ${name.padEnd(12)} ${chalk.cyan(count.toString())}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
console.log(chalk.gray("\u2500".repeat(40)));
|
|
147
|
+
console.log(` Total stars: ${chalk.cyan(stats.total.toString())}`);
|
|
148
|
+
console.log(` Total orbits: ${chalk.cyan(Object.keys(constellation.orbits).length.toString())}`);
|
|
149
|
+
console.log(chalk.gray(`
|
|
150
|
+
Output: ${outputPath}
|
|
151
|
+
`));
|
|
152
|
+
const sampleStar = Object.entries(constellation.stars).find(
|
|
153
|
+
([, star]) => star.references.length > 0 || star.referencedBy.length > 0
|
|
154
|
+
);
|
|
155
|
+
if (sampleStar) {
|
|
156
|
+
console.log(chalk.white("Sample Star"));
|
|
157
|
+
console.log(chalk.gray("\u2500".repeat(40)));
|
|
158
|
+
console.log(chalk.cyan(` ${sampleStar[0]}`));
|
|
159
|
+
const star = sampleStar[1];
|
|
160
|
+
if (star.gates?.length) console.log(chalk.gray(` gates: ${star.gates.join(", ")}`));
|
|
161
|
+
if (star.components?.length) console.log(chalk.gray(` components: ${star.components.join(", ")}`));
|
|
162
|
+
if (star.signals?.length) console.log(chalk.gray(` signals: ${star.signals.join(", ")}`));
|
|
163
|
+
if (star.referencedBy.length) console.log(chalk.gray(` referencedBy: ${star.referencedBy.join(", ")}`));
|
|
164
|
+
console.log("");
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
if (result.errors.length > 0 && !options.quiet) {
|
|
168
|
+
console.log(chalk.yellow("Warnings"));
|
|
169
|
+
console.log(chalk.gray("\u2500".repeat(40)));
|
|
170
|
+
for (const error of result.errors.slice(0, 5)) {
|
|
171
|
+
console.log(chalk.yellow(` \u26A0 ${error.filePath}: ${error.message}`));
|
|
172
|
+
}
|
|
173
|
+
if (result.errors.length > 5) {
|
|
174
|
+
console.log(chalk.gray(` ... and ${result.errors.length - 5} more`));
|
|
175
|
+
}
|
|
176
|
+
console.log("");
|
|
177
|
+
}
|
|
178
|
+
return constellation;
|
|
179
|
+
} catch (error) {
|
|
180
|
+
spinner.fail("Failed to build constellation");
|
|
181
|
+
tracker.error("Constellation build failed", { error: error.message });
|
|
182
|
+
console.log(chalk.red(`Error: ${error.message}
|
|
183
|
+
`));
|
|
184
|
+
process.exit(1);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
function serializeToYaml(obj, indent = 0) {
|
|
188
|
+
const spaces = " ".repeat(indent);
|
|
189
|
+
if (obj === null || obj === void 0) {
|
|
190
|
+
return "null";
|
|
191
|
+
}
|
|
192
|
+
if (typeof obj === "string") {
|
|
193
|
+
if (obj.includes(":") || obj.includes("#") || obj.includes("\n") || obj.startsWith("@") || obj.startsWith("^")) {
|
|
194
|
+
return `"${obj.replace(/"/g, '\\"')}"`;
|
|
195
|
+
}
|
|
196
|
+
return obj;
|
|
197
|
+
}
|
|
198
|
+
if (typeof obj === "number" || typeof obj === "boolean") {
|
|
199
|
+
return String(obj);
|
|
200
|
+
}
|
|
201
|
+
if (Array.isArray(obj)) {
|
|
202
|
+
if (obj.length === 0) return "[]";
|
|
203
|
+
return obj.map((item) => `${spaces}- ${serializeToYaml(item, indent)}`).join("\n");
|
|
204
|
+
}
|
|
205
|
+
if (typeof obj === "object") {
|
|
206
|
+
const entries = Object.entries(obj);
|
|
207
|
+
if (entries.length === 0) return "{}";
|
|
208
|
+
return entries.map(([key, value]) => {
|
|
209
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
210
|
+
return `${spaces}${key}:
|
|
211
|
+
${serializeToYaml(value, indent + 1)}`;
|
|
212
|
+
}
|
|
213
|
+
if (Array.isArray(value)) {
|
|
214
|
+
if (value.length === 0) return `${spaces}${key}: []`;
|
|
215
|
+
return `${spaces}${key}:
|
|
216
|
+
${serializeToYaml(value, indent + 1)}`;
|
|
217
|
+
}
|
|
218
|
+
return `${spaces}${key}: ${serializeToYaml(value, indent)}`;
|
|
219
|
+
}).join("\n");
|
|
220
|
+
}
|
|
221
|
+
return String(obj);
|
|
222
|
+
}
|
|
223
|
+
export {
|
|
224
|
+
constellationCommand
|
|
225
|
+
};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
findPurposeFiles
|
|
4
|
+
} from "./chunk-PW2EXJQT.js";
|
|
5
|
+
import {
|
|
6
|
+
findGateFiles
|
|
7
|
+
} from "./chunk-IRKUEJVW.js";
|
|
8
|
+
import "./chunk-MO4EEYFW.js";
|
|
9
|
+
|
|
10
|
+
// src/commands/cost.ts
|
|
11
|
+
import * as fs from "fs";
|
|
12
|
+
import * as path from "path";
|
|
13
|
+
import chalk from "chalk";
|
|
14
|
+
import ora from "ora";
|
|
15
|
+
function estimateTokens(text) {
|
|
16
|
+
const chars = text.length;
|
|
17
|
+
return Math.ceil(chars / 3.5);
|
|
18
|
+
}
|
|
19
|
+
function getFileTokens(filePath, rootDir) {
|
|
20
|
+
try {
|
|
21
|
+
const content = fs.readFileSync(filePath, "utf8");
|
|
22
|
+
const bytes = Buffer.byteLength(content, "utf8");
|
|
23
|
+
const tokens = estimateTokens(content);
|
|
24
|
+
const relativePath = path.relative(rootDir, filePath);
|
|
25
|
+
return {
|
|
26
|
+
path: filePath,
|
|
27
|
+
relativePath,
|
|
28
|
+
tokens,
|
|
29
|
+
bytes
|
|
30
|
+
};
|
|
31
|
+
} catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function formatTokens(tokens) {
|
|
36
|
+
if (tokens < 1e3) return tokens.toString();
|
|
37
|
+
return `${(tokens / 1e3).toFixed(1)}k`;
|
|
38
|
+
}
|
|
39
|
+
async function costCommand(targetPath, options) {
|
|
40
|
+
const rootDir = targetPath ? path.resolve(targetPath) : process.cwd();
|
|
41
|
+
const spinner = ora();
|
|
42
|
+
if (!options.json) {
|
|
43
|
+
console.log(chalk.blue("\n\u{1F4B0} Paradigm Cost Analysis\n"));
|
|
44
|
+
}
|
|
45
|
+
spinner.start("Analyzing context files...");
|
|
46
|
+
const purposeFilePaths = await findPurposeFiles(rootDir);
|
|
47
|
+
const purposeFiles = [];
|
|
48
|
+
for (const filePath of purposeFilePaths) {
|
|
49
|
+
const tokens = getFileTokens(filePath, rootDir);
|
|
50
|
+
if (tokens) purposeFiles.push(tokens);
|
|
51
|
+
}
|
|
52
|
+
const portalFilePaths = await findGateFiles(rootDir);
|
|
53
|
+
const portalFiles = [];
|
|
54
|
+
for (const filePath of portalFilePaths) {
|
|
55
|
+
const tokens = getFileTokens(filePath, rootDir);
|
|
56
|
+
if (tokens) portalFiles.push(tokens);
|
|
57
|
+
}
|
|
58
|
+
const scanIndexPath = path.join(rootDir, ".paradigm", "scan-index.json");
|
|
59
|
+
const scanIndex = getFileTokens(scanIndexPath, rootDir);
|
|
60
|
+
const cursorrrulesPath = path.join(rootDir, ".cursorrules");
|
|
61
|
+
const cursorrulesNew = path.join(rootDir, ".cursor", "rules", "paradigm.mdc");
|
|
62
|
+
let cursorrules = getFileTokens(cursorrrulesPath, rootDir);
|
|
63
|
+
if (!cursorrules) {
|
|
64
|
+
cursorrules = getFileTokens(cursorrulesNew, rootDir);
|
|
65
|
+
}
|
|
66
|
+
spinner.stop();
|
|
67
|
+
const purposeTotal = purposeFiles.reduce((sum, f) => sum + f.tokens, 0);
|
|
68
|
+
const portalTotal = portalFiles.reduce((sum, f) => sum + f.tokens, 0);
|
|
69
|
+
const scanTotal = scanIndex?.tokens || 0;
|
|
70
|
+
const cursorrulesTotal = cursorrules?.tokens || 0;
|
|
71
|
+
const staticTotal = purposeTotal + portalTotal + scanTotal;
|
|
72
|
+
const staticWithRules = staticTotal + cursorrulesTotal;
|
|
73
|
+
const avgQueryTokens = 150;
|
|
74
|
+
const typicalConversation = avgQueryTokens * 7;
|
|
75
|
+
const savingsPercent = staticWithRules > 0 ? Math.round((1 - typicalConversation / staticWithRules) * 100) : 0;
|
|
76
|
+
const recommendations = [];
|
|
77
|
+
const largeFiles = purposeFiles.filter((f) => f.tokens > 500);
|
|
78
|
+
if (largeFiles.length > 0) {
|
|
79
|
+
recommendations.push(
|
|
80
|
+
`${largeFiles.length} .purpose file(s) exceed 500 tokens. Consider splitting large features.`
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
const mcpConfigPath = path.join(rootDir, ".cursor", "mcp.json");
|
|
84
|
+
const hasMcp = fs.existsSync(mcpConfigPath);
|
|
85
|
+
if (!hasMcp) {
|
|
86
|
+
recommendations.push(
|
|
87
|
+
"MCP not configured. Run `paradigm mcp setup` to enable dynamic context (80%+ savings)."
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
if (!scanIndex) {
|
|
91
|
+
recommendations.push(
|
|
92
|
+
"No scan-index.json found. Run `paradigm index` for visual discovery support."
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
if (purposeFiles.length < 3) {
|
|
96
|
+
recommendations.push(
|
|
97
|
+
"Few .purpose files found. Add more context for better AI understanding."
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
const analysis = {
|
|
101
|
+
static: {
|
|
102
|
+
purposeFiles,
|
|
103
|
+
portalFiles,
|
|
104
|
+
scanIndex,
|
|
105
|
+
cursorrules,
|
|
106
|
+
total: staticWithRules
|
|
107
|
+
},
|
|
108
|
+
dynamic: {
|
|
109
|
+
avgQueryTokens,
|
|
110
|
+
typicalConversation
|
|
111
|
+
},
|
|
112
|
+
savings: {
|
|
113
|
+
percentage: Math.max(0, savingsPercent),
|
|
114
|
+
description: savingsPercent > 0 ? `${savingsPercent}% fewer tokens with MCP vs static context` : "MCP provides on-demand context loading"
|
|
115
|
+
},
|
|
116
|
+
recommendations
|
|
117
|
+
};
|
|
118
|
+
if (options.json) {
|
|
119
|
+
console.log(JSON.stringify(analysis, null, 2));
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
console.log(chalk.white("Context Token Analysis"));
|
|
123
|
+
console.log(chalk.gray("\u2500".repeat(50)));
|
|
124
|
+
console.log(chalk.cyan("\nStatic Context (loaded every conversation):"));
|
|
125
|
+
console.log(` .purpose files (${purposeFiles.length}):`.padEnd(35) + chalk.yellow(formatTokens(purposeTotal) + " tokens"));
|
|
126
|
+
console.log(` portal.yaml (${portalFiles.length}):`.padEnd(35) + chalk.yellow(formatTokens(portalTotal) + " tokens"));
|
|
127
|
+
if (scanIndex) {
|
|
128
|
+
console.log(" scan-index.json:".padEnd(35) + chalk.yellow(formatTokens(scanTotal) + " tokens"));
|
|
129
|
+
}
|
|
130
|
+
if (cursorrules) {
|
|
131
|
+
console.log(" .cursorrules:".padEnd(35) + chalk.yellow(formatTokens(cursorrulesTotal) + " tokens"));
|
|
132
|
+
}
|
|
133
|
+
console.log(chalk.gray("\u2500".repeat(50)));
|
|
134
|
+
console.log(" Static Total:".padEnd(35) + chalk.yellow.bold(formatTokens(staticWithRules) + " tokens"));
|
|
135
|
+
console.log(chalk.cyan("\nDynamic Context (MCP on-demand):"));
|
|
136
|
+
console.log(" Avg query response:".padEnd(35) + chalk.green(formatTokens(avgQueryTokens) + " tokens"));
|
|
137
|
+
console.log(" Typical conversation (~7 queries):".padEnd(35) + chalk.green(formatTokens(typicalConversation) + " tokens"));
|
|
138
|
+
console.log(chalk.cyan("\nPotential Savings:"));
|
|
139
|
+
if (savingsPercent > 0) {
|
|
140
|
+
const savingsColor = savingsPercent > 70 ? chalk.green : savingsPercent > 40 ? chalk.yellow : chalk.white;
|
|
141
|
+
console.log(` MCP vs Static:`.padEnd(35) + savingsColor.bold(`${savingsPercent}% reduction`));
|
|
142
|
+
const staticCost = staticWithRules / 1e3 * 0.01;
|
|
143
|
+
const dynamicCost = typicalConversation / 1e3 * 0.01;
|
|
144
|
+
const savedCost = staticCost - dynamicCost;
|
|
145
|
+
if (savedCost > 1e-3) {
|
|
146
|
+
console.log(` Est. savings per conversation:`.padEnd(35) + chalk.green(`~$${savedCost.toFixed(4)}`));
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (options.detailed && purposeFiles.length > 0) {
|
|
150
|
+
console.log(chalk.cyan("\nTop Token Consumers:"));
|
|
151
|
+
const sorted = [...purposeFiles].sort((a, b) => b.tokens - a.tokens).slice(0, 5);
|
|
152
|
+
for (const file of sorted) {
|
|
153
|
+
const percentage = Math.round(file.tokens / staticTotal * 100);
|
|
154
|
+
console.log(` ${file.relativePath}`.padEnd(40) + chalk.gray(`${formatTokens(file.tokens)} (${percentage}%)`));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
if (recommendations.length > 0) {
|
|
158
|
+
console.log(chalk.cyan("\nRecommendations:"));
|
|
159
|
+
for (const rec of recommendations) {
|
|
160
|
+
console.log(chalk.yellow(` \u2022 ${rec}`));
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
console.log(chalk.cyan("\nMCP Status:"));
|
|
164
|
+
if (hasMcp) {
|
|
165
|
+
console.log(chalk.green(" \u2713 MCP configured - using dynamic context loading"));
|
|
166
|
+
} else {
|
|
167
|
+
console.log(chalk.yellow(" \u25CB MCP not configured"));
|
|
168
|
+
console.log(chalk.gray(" Run `paradigm mcp setup` to enable token-efficient queries"));
|
|
169
|
+
}
|
|
170
|
+
console.log("");
|
|
171
|
+
}
|
|
172
|
+
export {
|
|
173
|
+
costCommand
|
|
174
|
+
};
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
AuditLogger
|
|
4
|
+
} from "./chunk-PBHIFAL4.js";
|
|
5
|
+
import {
|
|
6
|
+
formatCost,
|
|
7
|
+
formatTokens
|
|
8
|
+
} from "./chunk-5JGJACDU.js";
|
|
9
|
+
import "./chunk-MO4EEYFW.js";
|
|
10
|
+
|
|
11
|
+
// src/commands/team/cost.ts
|
|
12
|
+
import * as path from "path";
|
|
13
|
+
import chalk from "chalk";
|
|
14
|
+
async function teamCostCommand(targetPath, options) {
|
|
15
|
+
const rootDir = targetPath ? path.resolve(targetPath) : process.cwd();
|
|
16
|
+
let from;
|
|
17
|
+
let to;
|
|
18
|
+
if (options.days) {
|
|
19
|
+
const days = parseInt(options.days);
|
|
20
|
+
from = /* @__PURE__ */ new Date();
|
|
21
|
+
from.setDate(from.getDate() - days);
|
|
22
|
+
}
|
|
23
|
+
if (options.from) {
|
|
24
|
+
from = new Date(options.from);
|
|
25
|
+
}
|
|
26
|
+
if (options.to) {
|
|
27
|
+
to = new Date(options.to);
|
|
28
|
+
}
|
|
29
|
+
const auditLogger = new AuditLogger(rootDir);
|
|
30
|
+
const summary = auditLogger.getCostSummary(from, to);
|
|
31
|
+
if (options.json) {
|
|
32
|
+
console.log(JSON.stringify(summary, null, 2));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
console.log();
|
|
36
|
+
console.log(chalk.blue("\u2501".repeat(50)));
|
|
37
|
+
console.log(chalk.blue(" Orchestration Cost Summary"));
|
|
38
|
+
console.log(chalk.blue("\u2501".repeat(50)));
|
|
39
|
+
console.log();
|
|
40
|
+
if (from || to) {
|
|
41
|
+
const fromStr = from ? from.toISOString().slice(0, 10) : "beginning";
|
|
42
|
+
const toStr = to ? to.toISOString().slice(0, 10) : "now";
|
|
43
|
+
console.log(chalk.gray(` Period: ${fromStr} to ${toStr}`));
|
|
44
|
+
console.log();
|
|
45
|
+
}
|
|
46
|
+
console.log(chalk.cyan(" Totals:"));
|
|
47
|
+
console.log(chalk.white(` Orchestrations: ${summary.orchestrationCount}`));
|
|
48
|
+
console.log(chalk.white(` Total tokens: ${formatTokens(summary.totalTokens)}`));
|
|
49
|
+
console.log(chalk.white(` Total cost: ${formatCost(summary.totalCost)}`));
|
|
50
|
+
console.log();
|
|
51
|
+
if (Object.keys(summary.byModel).length > 0) {
|
|
52
|
+
console.log(chalk.cyan(" By Model:"));
|
|
53
|
+
for (const [model, data] of Object.entries(summary.byModel)) {
|
|
54
|
+
const percent = (data.cost / summary.totalCost * 100).toFixed(1);
|
|
55
|
+
console.log(chalk.gray(` ${model.padEnd(8)} ${formatCost(data.cost).padStart(10)} (${percent}%) - ${data.count} calls`));
|
|
56
|
+
}
|
|
57
|
+
console.log();
|
|
58
|
+
}
|
|
59
|
+
if (Object.keys(summary.byAgent).length > 0 && options.detailed) {
|
|
60
|
+
console.log(chalk.cyan(" By Agent:"));
|
|
61
|
+
for (const [agent, data] of Object.entries(summary.byAgent)) {
|
|
62
|
+
const percent = (data.cost / summary.totalCost * 100).toFixed(1);
|
|
63
|
+
console.log(chalk.gray(` ${agent.padEnd(12)} ${formatCost(data.cost).padStart(10)} (${percent}%) - ${data.count} calls`));
|
|
64
|
+
}
|
|
65
|
+
console.log();
|
|
66
|
+
}
|
|
67
|
+
if (summary.byDay.length > 0 && options.detailed) {
|
|
68
|
+
console.log(chalk.cyan(" By Day (recent):"));
|
|
69
|
+
const recentDays = summary.byDay.slice(-7);
|
|
70
|
+
for (const day of recentDays) {
|
|
71
|
+
const bar = "\u2588".repeat(Math.ceil(day.cost / summary.totalCost * 20));
|
|
72
|
+
console.log(chalk.gray(` ${day.date} ${formatCost(day.cost).padStart(10)} ${chalk.blue(bar)}`));
|
|
73
|
+
}
|
|
74
|
+
console.log();
|
|
75
|
+
}
|
|
76
|
+
if (options.detailed) {
|
|
77
|
+
console.log(chalk.cyan(" Model Pricing Reference:"));
|
|
78
|
+
console.log(chalk.gray(" opus: $15.00 / $75.00 per 1M tokens (in/out)"));
|
|
79
|
+
console.log(chalk.gray(" sonnet: $3.00 / $15.00 per 1M tokens (in/out)"));
|
|
80
|
+
console.log(chalk.gray(" haiku: $0.25 / $1.25 per 1M tokens (in/out)"));
|
|
81
|
+
console.log();
|
|
82
|
+
}
|
|
83
|
+
if (summary.totalCost > 1) {
|
|
84
|
+
console.log(chalk.yellow(" Tips to reduce costs:"));
|
|
85
|
+
console.log(chalk.gray(" - Use haiku for builder/tester agents"));
|
|
86
|
+
console.log(chalk.gray(' - Set budget limits: --budget "cost=5"'));
|
|
87
|
+
console.log(chalk.gray(' - Compare modes: paradigm team orchestrate "..." --compare'));
|
|
88
|
+
console.log();
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
export {
|
|
92
|
+
teamCostCommand
|
|
93
|
+
};
|