@stupify/cli 0.0.16 → 0.2.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.
Files changed (89) hide show
  1. package/.review/CORPUS.md +44 -0
  2. package/.review/CORPUS.template.md +73 -0
  3. package/.review/REVIEW-PROMPT.md +52 -0
  4. package/.review/RUBRIC.md +46 -0
  5. package/LICENSE +1 -1
  6. package/README.md +95 -37
  7. package/package.json +27 -26
  8. package/packs/antirez.md +10 -0
  9. package/packs/anton-kropp.md +10 -0
  10. package/packs/dhh.md +10 -0
  11. package/packs/dtolnay.md +10 -0
  12. package/packs/jarred-sumner.md +9 -0
  13. package/packs/mitchell-hashimoto.md +10 -0
  14. package/packs/rich-harris.md +10 -0
  15. package/packs/simon-willison.md +10 -0
  16. package/packs/sindre-sorhus.md +10 -0
  17. package/packs/tanner-linsley.md +10 -0
  18. package/packs/zod.md +10 -0
  19. package/src/cli.ts +626 -0
  20. package/src/prime-install.test.ts +109 -0
  21. package/src/prime.ts +50 -0
  22. package/src/review-sweep.test.ts +101 -0
  23. package/src/review-sweep.ts +526 -0
  24. package/dist/analysis.d.ts +0 -16
  25. package/dist/analysis.js +0 -168
  26. package/dist/cache.d.ts +0 -2
  27. package/dist/cache.js +0 -57
  28. package/dist/checks.d.ts +0 -4
  29. package/dist/checks.js +0 -228
  30. package/dist/command.d.ts +0 -2
  31. package/dist/command.js +0 -147
  32. package/dist/constants.d.ts +0 -4
  33. package/dist/constants.js +0 -53
  34. package/dist/counter-scout.d.ts +0 -21
  35. package/dist/counter-scout.js +0 -167
  36. package/dist/diff.d.ts +0 -1
  37. package/dist/diff.js +0 -10
  38. package/dist/doctor.d.ts +0 -16
  39. package/dist/doctor.js +0 -143
  40. package/dist/git.d.ts +0 -17
  41. package/dist/git.js +0 -368
  42. package/dist/hooks.d.ts +0 -5
  43. package/dist/hooks.js +0 -135
  44. package/dist/index.d.ts +0 -1
  45. package/dist/index.js +0 -1
  46. package/dist/model.d.ts +0 -11
  47. package/dist/model.js +0 -296
  48. package/dist/prompts.d.ts +0 -8
  49. package/dist/prompts.js +0 -89
  50. package/dist/render.d.ts +0 -6
  51. package/dist/render.js +0 -295
  52. package/dist/repomix-provider.d.ts +0 -12
  53. package/dist/repomix-provider.js +0 -196
  54. package/dist/search-bench.d.ts +0 -1
  55. package/dist/search-bench.js +0 -677
  56. package/dist/search-profile.d.ts +0 -6
  57. package/dist/search-profile.js +0 -73
  58. package/dist/sem-provider.d.ts +0 -2
  59. package/dist/sem-provider.js +0 -255
  60. package/dist/stupify.d.ts +0 -38
  61. package/dist/stupify.js +0 -505
  62. package/dist/trace.d.ts +0 -31
  63. package/dist/trace.js +0 -86
  64. package/dist/types.d.ts +0 -341
  65. package/dist/types.js +0 -6
  66. package/dist/ui.d.ts +0 -34
  67. package/dist/ui.js +0 -143
  68. package/src/analysis.ts +0 -223
  69. package/src/cache.ts +0 -63
  70. package/src/checks.ts +0 -231
  71. package/src/command.ts +0 -173
  72. package/src/constants.ts +0 -56
  73. package/src/counter-scout.ts +0 -195
  74. package/src/diff.ts +0 -9
  75. package/src/doctor.ts +0 -166
  76. package/src/git.ts +0 -380
  77. package/src/hooks.ts +0 -151
  78. package/src/index.ts +0 -1
  79. package/src/model.ts +0 -367
  80. package/src/prompts.ts +0 -100
  81. package/src/render.ts +0 -328
  82. package/src/repomix-provider.ts +0 -219
  83. package/src/search-bench.ts +0 -783
  84. package/src/search-profile.ts +0 -89
  85. package/src/sem-provider.ts +0 -300
  86. package/src/stupify.ts +0 -604
  87. package/src/trace.ts +0 -126
  88. package/src/types.ts +0 -362
  89. package/src/ui.ts +0 -187
@@ -1,12 +0,0 @@
1
- import type { RepomixSearchConfig, SemCandidate, SemChange, SemContext, SemContextPack } from "./types.ts";
2
- export declare function emptyContextPack(): SemContextPack;
3
- export declare function repomixContextPack(cwd: string, contexts: readonly SemContext[], changes: readonly SemChange[], config?: Readonly<{
4
- compress: boolean;
5
- showLineNumbers: boolean;
6
- removeEmptyLines: boolean;
7
- maxFileSizeBytes: number;
8
- maxTotalSizeBytes: number;
9
- ignorePatterns: readonly string[];
10
- }>): Promise<SemContextPack>;
11
- export declare function entityContextsFromChanges(candidates: readonly SemCandidate[], changes: readonly SemChange[]): readonly SemContext[];
12
- export declare function repomixSearchConfig(): RepomixSearchConfig;
@@ -1,196 +0,0 @@
1
- import { mkdtemp, readFile, rm, stat } from "node:fs/promises";
2
- import { tmpdir } from "node:os";
3
- import path from "node:path";
4
- import { pack, setLogLevel } from "repomix";
5
- const MAX_PACK_FILE_SIZE_BYTES = 48 * 1024;
6
- const MAX_PACK_TOTAL_SIZE_BYTES = 128 * 1024;
7
- export function emptyContextPack() {
8
- const config = repomixSearchConfig();
9
- return {
10
- provider: "repomix",
11
- filePaths: [],
12
- totalCharacters: 0,
13
- totalTokens: 0,
14
- text: "",
15
- config,
16
- };
17
- }
18
- export async function repomixContextPack(cwd, contexts, changes, config = repomixSearchConfig()) {
19
- const filePaths = await candidateFilePaths(cwd, contexts, changes, config);
20
- if (filePaths.length === 0) {
21
- return {
22
- ...emptyContextPack(),
23
- config,
24
- };
25
- }
26
- setLogLevel(-1);
27
- const tempDir = await mkdtemp(path.join(tmpdir(), "stupify-repomix-"));
28
- const outputPath = path.join(tempDir, "context.xml");
29
- try {
30
- const result = await pack([cwd], {
31
- cwd,
32
- input: { maxFileSize: config.maxFileSizeBytes },
33
- output: {
34
- filePath: outputPath,
35
- style: "xml",
36
- parsableStyle: false,
37
- fileSummary: false,
38
- directoryStructure: false,
39
- files: true,
40
- removeComments: false,
41
- removeEmptyLines: config.removeEmptyLines,
42
- compress: config.compress,
43
- topFilesLength: 0,
44
- showLineNumbers: config.showLineNumbers,
45
- truncateBase64: true,
46
- copyToClipboard: false,
47
- includeFullDirectoryStructure: false,
48
- tokenCountTree: false,
49
- git: {
50
- sortByChanges: false,
51
- sortByChangesMaxCommits: 1,
52
- includeDiffs: false,
53
- includeLogs: false,
54
- includeLogsCount: 1,
55
- },
56
- },
57
- include: [],
58
- ignore: {
59
- useGitignore: true,
60
- useDotIgnore: true,
61
- useDefaultPatterns: true,
62
- customPatterns: [...config.ignorePatterns],
63
- },
64
- security: { enableSecurityCheck: false },
65
- tokenCount: { encoding: "o200k_base" },
66
- }, () => undefined, {}, [...filePaths]);
67
- return {
68
- provider: "repomix",
69
- filePaths,
70
- totalCharacters: result.totalCharacters,
71
- totalTokens: result.totalTokens,
72
- text: await readFile(outputPath, "utf8"),
73
- config,
74
- };
75
- }
76
- finally {
77
- await rm(tempDir, { recursive: true, force: true });
78
- }
79
- }
80
- export function entityContextsFromChanges(candidates, changes) {
81
- const byEntityId = new Map(changes.map((change) => [change.entityId, change]));
82
- return candidates.flatMap((candidate) => {
83
- const change = byEntityId.get(candidate.entityId);
84
- if (!change)
85
- return [];
86
- return [{
87
- targetId: candidate.targetId,
88
- entityId: change.entityId,
89
- entityName: change.entityName,
90
- entityKind: change.entityType,
91
- changeKind: change.changeType,
92
- checkId: candidate.checkId,
93
- reason: candidate.reason,
94
- filePath: change.filePath,
95
- text: JSON.stringify({
96
- source: "sem diff",
97
- file: change.filePath,
98
- type: change.entityType,
99
- name: change.entityName,
100
- change: change.changeType,
101
- before: shortenCode(change.beforeContent),
102
- after: shortenCode(change.afterContent),
103
- }, null, 2),
104
- }];
105
- });
106
- }
107
- async function candidateFilePaths(cwd, contexts, changes, config) {
108
- const byEntityId = new Map(changes.map((change) => [change.entityId, change.filePath]));
109
- const paths = contexts.flatMap((context) => context.filePath ?? byEntityId.get(context.entityId) ?? []);
110
- const safePaths = [...new Set(paths)].filter(isSafeRelativeFilePath);
111
- const selected = [];
112
- let totalBytes = 0;
113
- for (const filePath of safePaths) {
114
- if (matchesAnyPattern(filePath, config.ignorePatterns))
115
- continue;
116
- const bytes = await fileSize(cwd, filePath);
117
- if (bytes === null || bytes > config.maxFileSizeBytes)
118
- continue;
119
- if (totalBytes + bytes > config.maxTotalSizeBytes)
120
- continue;
121
- totalBytes += bytes;
122
- selected.push(filePath);
123
- }
124
- return selected;
125
- }
126
- export function repomixSearchConfig() {
127
- return {
128
- compress: envBoolean("STUPIFY_REPOMIX_COMPRESS", true),
129
- showLineNumbers: envBoolean("STUPIFY_REPOMIX_SHOW_LINE_NUMBERS", true),
130
- removeEmptyLines: envBoolean("STUPIFY_REPOMIX_REMOVE_EMPTY_LINES", true),
131
- maxFileSizeBytes: envInteger("STUPIFY_REPOMIX_MAX_FILE_BYTES", MAX_PACK_FILE_SIZE_BYTES),
132
- maxTotalSizeBytes: envInteger("STUPIFY_REPOMIX_MAX_TOTAL_BYTES", MAX_PACK_TOTAL_SIZE_BYTES),
133
- ignorePatterns: envList("STUPIFY_REPOMIX_IGNORE_PATTERNS"),
134
- };
135
- }
136
- function envBoolean(name, fallback) {
137
- const value = process.env[name];
138
- if (value === undefined || value === "")
139
- return fallback;
140
- return /^(1|true|yes|on)$/i.test(value);
141
- }
142
- function envInteger(name, fallback) {
143
- const value = Number(process.env[name]);
144
- return Number.isInteger(value) && value > 0 ? value : fallback;
145
- }
146
- function envList(name) {
147
- return (process.env[name] ?? "")
148
- .split(",")
149
- .map((item) => item.trim())
150
- .filter(Boolean);
151
- }
152
- function matchesAnyPattern(filePath, patterns) {
153
- return patterns.some((pattern) => matchesPattern(filePath, pattern));
154
- }
155
- function matchesPattern(filePath, pattern) {
156
- if (pattern === filePath)
157
- return true;
158
- if (!pattern.includes("*"))
159
- return false;
160
- const escaped = pattern
161
- .split("*")
162
- .map(escapeRegExp)
163
- .join(".*");
164
- return new RegExp(`^${escaped}$`).test(filePath);
165
- }
166
- function escapeRegExp(value) {
167
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
168
- }
169
- function isSafeRelativeFilePath(value) {
170
- if (!value || path.isAbsolute(value))
171
- return false;
172
- const normalized = path.normalize(value);
173
- return normalized !== "." && !normalized.startsWith("..") && !path.isAbsolute(normalized);
174
- }
175
- async function fileSize(cwd, filePath) {
176
- try {
177
- const fullPath = path.join(cwd, filePath);
178
- if (!fullPath.startsWith(`${cwd}${path.sep}`))
179
- return null;
180
- const result = await stat(fullPath);
181
- return result.isFile() ? result.size : null;
182
- }
183
- catch {
184
- return null;
185
- }
186
- }
187
- function shortenCode(value) {
188
- if (!value)
189
- return "(none)";
190
- const lines = value.split(/\r?\n/);
191
- const limit = 120;
192
- if (lines.length <= limit)
193
- return value;
194
- return `${lines.slice(0, limit).join("\n")}
195
- [stupify: sem entity content shortened after ${limit} lines]`;
196
- }
@@ -1 +0,0 @@
1
- export declare function runSearchBench(configPath: string): Promise<string>;