repomemory 0.1.0 → 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 (62) hide show
  1. package/README.md +151 -104
  2. package/dist/commands/analyze.d.ts +2 -0
  3. package/dist/commands/analyze.d.ts.map +1 -1
  4. package/dist/commands/analyze.js +162 -188
  5. package/dist/commands/analyze.js.map +1 -1
  6. package/dist/commands/dashboard.d.ts +5 -0
  7. package/dist/commands/dashboard.d.ts.map +1 -0
  8. package/dist/commands/dashboard.js +520 -0
  9. package/dist/commands/dashboard.js.map +1 -0
  10. package/dist/commands/init.d.ts.map +1 -1
  11. package/dist/commands/init.js +33 -34
  12. package/dist/commands/init.js.map +1 -1
  13. package/dist/commands/serve.d.ts.map +1 -1
  14. package/dist/commands/serve.js +2 -1
  15. package/dist/commands/serve.js.map +1 -1
  16. package/dist/commands/setup.d.ts.map +1 -1
  17. package/dist/commands/setup.js +151 -35
  18. package/dist/commands/setup.js.map +1 -1
  19. package/dist/commands/status.d.ts +4 -0
  20. package/dist/commands/status.d.ts.map +1 -0
  21. package/dist/commands/status.js +87 -0
  22. package/dist/commands/status.js.map +1 -0
  23. package/dist/commands/sync.d.ts.map +1 -1
  24. package/dist/commands/sync.js +57 -27
  25. package/dist/commands/sync.js.map +1 -1
  26. package/dist/commands/wizard.d.ts +4 -0
  27. package/dist/commands/wizard.d.ts.map +1 -0
  28. package/dist/commands/wizard.js +184 -0
  29. package/dist/commands/wizard.js.map +1 -0
  30. package/dist/index.js +37 -42
  31. package/dist/index.js.map +1 -1
  32. package/dist/lib/ai-provider.d.ts +11 -0
  33. package/dist/lib/ai-provider.d.ts.map +1 -1
  34. package/dist/lib/ai-provider.js +138 -69
  35. package/dist/lib/ai-provider.js.map +1 -1
  36. package/dist/lib/config.d.ts +11 -15
  37. package/dist/lib/config.d.ts.map +1 -1
  38. package/dist/lib/config.js +33 -21
  39. package/dist/lib/config.js.map +1 -1
  40. package/dist/lib/context-store.d.ts +11 -0
  41. package/dist/lib/context-store.d.ts.map +1 -1
  42. package/dist/lib/context-store.js +51 -18
  43. package/dist/lib/context-store.js.map +1 -1
  44. package/dist/lib/git.d.ts +1 -0
  45. package/dist/lib/git.d.ts.map +1 -1
  46. package/dist/lib/git.js +34 -20
  47. package/dist/lib/git.js.map +1 -1
  48. package/dist/lib/json-repair.d.ts +24 -0
  49. package/dist/lib/json-repair.d.ts.map +1 -0
  50. package/dist/lib/json-repair.js +140 -0
  51. package/dist/lib/json-repair.js.map +1 -0
  52. package/dist/lib/repo-scanner.d.ts.map +1 -1
  53. package/dist/lib/repo-scanner.js +103 -26
  54. package/dist/lib/repo-scanner.js.map +1 -1
  55. package/dist/lib/search.d.ts +10 -4
  56. package/dist/lib/search.d.ts.map +1 -1
  57. package/dist/lib/search.js +136 -51
  58. package/dist/lib/search.js.map +1 -1
  59. package/dist/mcp/server.d.ts.map +1 -1
  60. package/dist/mcp/server.js +128 -54
  61. package/dist/mcp/server.js.map +1 -1
  62. package/package.json +20 -8
@@ -0,0 +1,184 @@
1
+ import chalk from "chalk";
2
+ import * as p from "@clack/prompts";
3
+ import { existsSync } from "fs";
4
+ import { join } from "path";
5
+ import { initCommand } from "./init.js";
6
+ import { analyzeCommand } from "./analyze.js";
7
+ import { setupCommand } from "./setup.js";
8
+ const PROVIDER_INFO = {
9
+ anthropic: {
10
+ envVar: "ANTHROPIC_API_KEY",
11
+ label: "Anthropic (Claude)",
12
+ hint: "Best quality. Recommended.",
13
+ },
14
+ openai: {
15
+ envVar: "OPENAI_API_KEY",
16
+ label: "OpenAI (GPT-4o)",
17
+ hint: "Fast and reliable.",
18
+ },
19
+ gemini: {
20
+ envVar: "GEMINI_API_KEY",
21
+ label: "Google (Gemini)",
22
+ hint: "Cheapest option.",
23
+ },
24
+ grok: {
25
+ envVar: "GROK_API_KEY",
26
+ label: "xAI (Grok)",
27
+ hint: "OpenAI-compatible.",
28
+ },
29
+ };
30
+ export async function wizardCommand(options) {
31
+ const repoRoot = options.dir || process.cwd();
32
+ console.clear();
33
+ p.intro(chalk.bgCyan.black(" repomemory ") + chalk.dim(" Your codebase never forgets."));
34
+ // Step 1: Check if already initialized
35
+ const contextExists = existsSync(join(repoRoot, ".context"));
36
+ if (contextExists) {
37
+ const overwrite = await p.confirm({
38
+ message: ".context/ already exists. Re-analyze and refresh?",
39
+ initialValue: false,
40
+ });
41
+ if (p.isCancel(overwrite)) {
42
+ p.cancel("Setup cancelled.");
43
+ process.exit(0);
44
+ }
45
+ if (!overwrite) {
46
+ p.cancel("Keeping existing context.");
47
+ process.exit(0);
48
+ }
49
+ }
50
+ // Step 2: Detect available API keys
51
+ const detectedProviders = [];
52
+ for (const [provider, info] of Object.entries(PROVIDER_INFO)) {
53
+ if (process.env[info.envVar]) {
54
+ detectedProviders.push(provider);
55
+ }
56
+ }
57
+ // Check alternate env vars
58
+ if (!detectedProviders.includes("gemini") && (process.env.GOOGLE_API_KEY || process.env.GOOGLE_GENERATIVE_AI_API_KEY)) {
59
+ detectedProviders.push("gemini");
60
+ }
61
+ if (!detectedProviders.includes("grok") && process.env.XAI_API_KEY) {
62
+ detectedProviders.push("grok");
63
+ }
64
+ // Step 3: Choose provider
65
+ let selectedProvider;
66
+ if (detectedProviders.length === 1) {
67
+ p.log.success(`Detected API key for ${chalk.bold(PROVIDER_INFO[detectedProviders[0]].label)}`);
68
+ selectedProvider = detectedProviders[0];
69
+ }
70
+ else if (detectedProviders.length > 1) {
71
+ const provider = await p.select({
72
+ message: `Found ${detectedProviders.length} API keys. Which provider?`,
73
+ options: detectedProviders.map((prov) => ({
74
+ value: prov,
75
+ label: PROVIDER_INFO[prov].label,
76
+ hint: PROVIDER_INFO[prov].hint,
77
+ })),
78
+ });
79
+ if (p.isCancel(provider)) {
80
+ p.cancel("Setup cancelled.");
81
+ process.exit(0);
82
+ }
83
+ selectedProvider = provider;
84
+ }
85
+ else {
86
+ // No API keys found — ask which they want to use
87
+ p.log.warn("No API keys detected in environment.");
88
+ const provider = await p.select({
89
+ message: "Which AI provider will you use?",
90
+ options: Object.entries(PROVIDER_INFO).map(([key, info]) => ({
91
+ value: key,
92
+ label: info.label,
93
+ hint: info.hint,
94
+ })),
95
+ });
96
+ if (p.isCancel(provider)) {
97
+ p.cancel("Setup cancelled.");
98
+ process.exit(0);
99
+ }
100
+ selectedProvider = provider;
101
+ const info = PROVIDER_INFO[selectedProvider];
102
+ p.log.info(`Set your API key:\n ${chalk.cyan(`export ${info.envVar}=your-key-here`)}`);
103
+ const hasKey = await p.confirm({
104
+ message: "Have you set the key? (You can set it now in another terminal)",
105
+ initialValue: false,
106
+ });
107
+ if (p.isCancel(hasKey) || !hasKey) {
108
+ p.log.info("You can run this wizard again after setting your API key.");
109
+ p.log.info(` ${chalk.dim(`export ${info.envVar}=...`)}`);
110
+ p.log.info(` ${chalk.dim("repomemory wizard")}`);
111
+ p.outro("See you soon!");
112
+ process.exit(0);
113
+ }
114
+ }
115
+ // Step 4: Choose AI tools to integrate
116
+ const tools = await p.multiselect({
117
+ message: "Which AI tools do you use?",
118
+ options: [
119
+ { value: "claude", label: "Claude Code", hint: "MCP server auto-starts" },
120
+ { value: "cursor", label: "Cursor", hint: "Adds .cursor/rules/" },
121
+ { value: "copilot", label: "GitHub Copilot", hint: "Adds copilot-instructions.md" },
122
+ { value: "windsurf", label: "Windsurf", hint: "Adds .windsurfrules" },
123
+ { value: "cline", label: "Cline", hint: "Adds .clinerules" },
124
+ { value: "aider", label: "Aider", hint: "Adds .aider.conf.yml" },
125
+ { value: "continue", label: "Continue", hint: "Adds .continue/rules/" },
126
+ ],
127
+ required: false,
128
+ });
129
+ if (p.isCancel(tools)) {
130
+ p.cancel("Setup cancelled.");
131
+ process.exit(0);
132
+ }
133
+ const selectedTools = tools;
134
+ // Step 5: Run analysis?
135
+ const runAnalysis = await p.confirm({
136
+ message: `Analyze your repo with ${PROVIDER_INFO[selectedProvider].label}? (2-5 min, uses AI)`,
137
+ initialValue: true,
138
+ });
139
+ if (p.isCancel(runAnalysis)) {
140
+ p.cancel("Setup cancelled.");
141
+ process.exit(0);
142
+ }
143
+ // Step 6: Execute everything
144
+ console.log(); // spacing
145
+ const s = p.spinner();
146
+ // Init
147
+ s.start("Initializing .context/ directory...");
148
+ if (!contextExists) {
149
+ await initCommand({ dir: repoRoot, provider: selectedProvider });
150
+ }
151
+ s.stop("Initialized .context/ directory");
152
+ // Setup tools
153
+ for (const tool of selectedTools) {
154
+ s.start(`Configuring ${tool}...`);
155
+ await setupCommand(tool, { dir: repoRoot });
156
+ s.stop(`Configured ${tool}`);
157
+ }
158
+ // Analyze
159
+ if (runAnalysis) {
160
+ console.log(); // spacing before analyze (it has its own output)
161
+ await analyzeCommand({
162
+ dir: repoRoot,
163
+ provider: selectedProvider,
164
+ verbose: false,
165
+ });
166
+ }
167
+ // Done!
168
+ console.log();
169
+ p.note([
170
+ `${chalk.cyan("git add .context/ && git commit -m 'Add repomemory'")}`,
171
+ "",
172
+ "Your team now shares the knowledge.",
173
+ "",
174
+ selectedTools.includes("claude")
175
+ ? "Claude Code will auto-discover context via the MCP server."
176
+ : `Run ${chalk.cyan("repomemory setup claude")} to add MCP server integration.`,
177
+ "",
178
+ `Run ${chalk.cyan("repomemory status")} to see your context coverage.`,
179
+ `Run ${chalk.cyan("repomemory analyze --merge")} to update without overwriting edits.`,
180
+ `Run ${chalk.cyan("repomemory dashboard")} to browse context in your browser.`,
181
+ ].join("\n"), "Next steps");
182
+ p.outro(chalk.green("Your codebase will never forget again."));
183
+ }
184
+ //# sourceMappingURL=wizard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wizard.js","sourceRoot":"","sources":["../../src/commands/wizard.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -5,11 +5,17 @@ import { analyzeCommand } from "./commands/analyze.js";
5
5
  import { syncCommand } from "./commands/sync.js";
6
6
  import { serveCommand } from "./commands/serve.js";
7
7
  import { setupCommand } from "./commands/setup.js";
8
+ import { statusCommand } from "./commands/status.js";
9
+ import { wizardCommand } from "./commands/wizard.js";
10
+ import { dashboardCommand } from "./commands/dashboard.js";
11
+ import { createRequire } from "module";
12
+ const require = createRequire(import.meta.url);
13
+ const { version } = require("../package.json");
8
14
  const program = new Command();
9
15
  program
10
16
  .name("repomemory")
11
- .description("Persistent, structured memory for AI coding agents. Your repo remembers what every session learned.")
12
- .version("0.1.0");
17
+ .description("Your codebase never forgets. Persistent, structured memory for AI coding agents.")
18
+ .version(version);
13
19
  program
14
20
  .command("init")
15
21
  .description("Initialize .context/ directory in the current repo")
@@ -23,6 +29,8 @@ program
23
29
  .option("-p, --provider <provider>", "AI provider (anthropic, openai, gemini, grok)")
24
30
  .option("-m, --model <model>", "Model to use (provider-specific)")
25
31
  .option("-v, --verbose", "Show detailed output", false)
32
+ .option("--dry-run", "Show what would be analyzed without calling the AI", false)
33
+ .option("--merge", "Merge with existing context (don't overwrite manual edits)", false)
26
34
  .action(analyzeCommand);
27
35
  program
28
36
  .command("sync")
@@ -37,48 +45,30 @@ program
37
45
  .action(serveCommand);
38
46
  program
39
47
  .command("setup <tool>")
40
- .description("Configure AI tool integration (claude, cursor, copilot)")
48
+ .description("Configure AI tool integration (claude, cursor, copilot, windsurf, cline, aider, continue)")
41
49
  .option("-d, --dir <path>", "Repository root directory", process.cwd())
42
50
  .action(setupCommand);
43
51
  program
44
52
  .command("status")
45
- .description("Show the current state of .context/")
53
+ .description("Show the current state of .context/ with coverage and freshness")
46
54
  .option("-d, --dir <path>", "Repository root directory", process.cwd())
47
- .action(async (options) => {
48
- const { default: chalk } = await import("chalk");
49
- const { loadConfig } = await import("./lib/config.js");
50
- const { ContextStore } = await import("./lib/context-store.js");
51
- const repoRoot = options.dir || process.cwd();
52
- const config = loadConfig(repoRoot);
53
- const store = new ContextStore(repoRoot, config);
54
- if (!store.exists()) {
55
- console.log(chalk.red(" No .context/ directory found."));
56
- console.log(chalk.dim(" Run `repomemory init` to get started."));
57
- process.exit(1);
58
- }
59
- const stats = store.getStats();
60
- const entries = store.listEntries();
61
- console.log(chalk.bold("\n📊 repomemory status\n"));
62
- console.log(` ${chalk.cyan("Total files:")} ${stats.totalFiles}`);
63
- console.log(` ${chalk.cyan("Total size:")} ${(stats.totalSize / 1024).toFixed(1)}KB`);
64
- console.log();
65
- for (const [category, count] of Object.entries(stats.categories)) {
66
- console.log(` ${chalk.bold(category + "/")} (${count} files)`);
67
- const catEntries = entries.filter((e) => e.category === category);
68
- for (const entry of catEntries) {
69
- const sizeKb = (entry.sizeBytes / 1024).toFixed(1);
70
- console.log(` ${chalk.dim("•")} ${entry.filename} — ${entry.title} (${sizeKb}KB)`);
71
- }
72
- }
73
- console.log();
74
- console.log(chalk.dim(` Provider: ${config.provider} | Model: ${config.model}`));
75
- });
76
- // Global error handler — no stack traces for users
55
+ .action(statusCommand);
56
+ program
57
+ .command("wizard")
58
+ .description("Interactive guided setup provider, tools, and first analysis in one flow")
59
+ .option("-d, --dir <path>", "Repository root directory", process.cwd())
60
+ .action(wizardCommand);
61
+ program
62
+ .command("dashboard")
63
+ .description("Open a web dashboard to browse and search your context files")
64
+ .option("-d, --dir <path>", "Repository root directory", process.cwd())
65
+ .option("--port <port>", "Port to serve on", "3333")
66
+ .action(dashboardCommand);
67
+ // Global error handlers
77
68
  process.on("uncaughtException", (err) => {
78
69
  const msg = err.message || String(err);
79
- // Known error patterns → friendly messages
80
70
  if (msg.includes("API key")) {
81
- console.error(`\n ${msg}`);
71
+ console.error(`\n\u2717 ${msg}`);
82
72
  console.error("\n Set your API key and try again:");
83
73
  console.error(" export ANTHROPIC_API_KEY=sk-ant-...");
84
74
  console.error(" export OPENAI_API_KEY=sk-...");
@@ -86,24 +76,29 @@ process.on("uncaughtException", (err) => {
86
76
  console.error(" export GROK_API_KEY=...");
87
77
  }
88
78
  else if (msg.includes("ENOENT")) {
89
- console.error(`\n File or directory not found: ${msg.split("'")[1] || "unknown"}`);
79
+ console.error(`\n\u2717 File or directory not found: ${msg.split("'")[1] || "unknown"}`);
90
80
  }
91
81
  else if (msg.includes("EACCES")) {
92
- console.error(`\n Permission denied. Try running with appropriate permissions.`);
82
+ console.error(`\n\u2717 Permission denied. Try running with appropriate permissions.`);
93
83
  }
94
84
  else if (msg.includes("fetch failed") || msg.includes("ECONNREFUSED")) {
95
- console.error(`\n Network error. Check your internet connection and try again.`);
85
+ console.error(`\n\u2717 Network error. Check your internet connection and try again.`);
96
86
  }
97
87
  else if (msg.includes("401") || msg.includes("authentication")) {
98
- console.error(`\n Authentication failed. Check your API key is valid.`);
88
+ console.error(`\n\u2717 Authentication failed. Check your API key is valid.`);
99
89
  }
100
90
  else if (msg.includes("429") || msg.includes("rate limit")) {
101
- console.error(`\n Rate limited. Wait a moment and try again.`);
91
+ console.error(`\n\u2717 Rate limited. Wait a moment and try again.`);
102
92
  }
103
93
  else {
104
- console.error(`\n ${msg}`);
94
+ console.error(`\n\u2717 ${msg}`);
105
95
  }
106
96
  process.exit(1);
107
97
  });
98
+ process.on("unhandledRejection", (reason) => {
99
+ const msg = reason instanceof Error ? reason.message : String(reason);
100
+ console.error(`\n\u2717 ${msg}`);
101
+ process.exit(1);
102
+ });
108
103
  program.parse();
109
104
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,8 @@ export interface AIMessage {
6
6
  export interface AIResponse {
7
7
  content: string;
8
8
  tokensUsed?: number;
9
+ inputTokens?: number;
10
+ outputTokens?: number;
9
11
  }
10
12
  export interface AIProvider {
11
13
  name: string;
@@ -14,5 +16,14 @@ export interface AIProvider {
14
16
  temperature?: number;
15
17
  }): Promise<AIResponse>;
16
18
  }
19
+ export declare class AIError extends Error {
20
+ readonly provider: string;
21
+ readonly statusCode?: number | undefined;
22
+ readonly isRetryable: boolean;
23
+ constructor(message: string, provider: string, statusCode?: number | undefined, isRetryable?: boolean);
24
+ }
17
25
  export declare function createProvider(config: RepoContextConfig): Promise<AIProvider>;
26
+ export declare function validateApiKey(config: RepoContextConfig): Promise<boolean>;
27
+ /** Estimate cost for a given provider/model/token count */
28
+ export declare function estimateCost(provider: string, model: string, inputTokens: number, outputTokens: number): string;
18
29
  //# sourceMappingURL=ai-provider.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ai-provider.d.ts","sourceRoot":"","sources":["../../src/lib/ai-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,QAAQ,EAAE,SAAS,EAAE,EAAE,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC9G;AAED,wBAAsB,cAAc,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CAenF"}
1
+ {"version":3,"file":"ai-provider.d.ts","sourceRoot":"","sources":["../../src/lib/ai-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAErD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,CAAC;IACtC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,QAAQ,EAAE,SAAS,EAAE,EAAE,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC9G;AAED,qBAAa,OAAQ,SAAQ,KAAK;aAGd,QAAQ,EAAE,MAAM;aAChB,UAAU,CAAC,EAAE,MAAM;aACnB,WAAW,EAAE,OAAO;gBAHpC,OAAO,EAAE,MAAM,EACC,QAAQ,EAAE,MAAM,EAChB,UAAU,CAAC,EAAE,MAAM,YAAA,EACnB,WAAW,GAAE,OAAe;CAK/C;AAED,wBAAsB,cAAc,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,UAAU,CAAC,CAenF;AAED,wBAAsB,cAAc,CAAC,MAAM,EAAE,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,CAOhF;AAiCD,2DAA2D;AAC3D,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB,MAAM,CAmBR"}
@@ -1,3 +1,15 @@
1
+ export class AIError extends Error {
2
+ provider;
3
+ statusCode;
4
+ isRetryable;
5
+ constructor(message, provider, statusCode, isRetryable = false) {
6
+ super(message);
7
+ this.provider = provider;
8
+ this.statusCode = statusCode;
9
+ this.isRetryable = isRetryable;
10
+ this.name = "AIError";
11
+ }
12
+ }
1
13
  export async function createProvider(config) {
2
14
  const apiKey = resolveApiKeyForProvider(config);
3
15
  switch (config.provider) {
@@ -13,6 +25,15 @@ export async function createProvider(config) {
13
25
  throw new Error(`Unknown provider: ${config.provider}. Supported: anthropic, openai, gemini, grok`);
14
26
  }
15
27
  }
28
+ export async function validateApiKey(config) {
29
+ try {
30
+ resolveApiKeyForProvider(config);
31
+ return true;
32
+ }
33
+ catch {
34
+ return false;
35
+ }
36
+ }
16
37
  function resolveApiKeyForProvider(config) {
17
38
  if (config.apiKey)
18
39
  return config.apiKey;
@@ -22,7 +43,6 @@ function resolveApiKeyForProvider(config) {
22
43
  gemini: "GEMINI_API_KEY",
23
44
  grok: "GROK_API_KEY",
24
45
  };
25
- // Also check alternate env var names
26
46
  const altEnvMap = {
27
47
  gemini: ["GOOGLE_API_KEY", "GOOGLE_GENERATIVE_AI_API_KEY"],
28
48
  grok: ["XAI_API_KEY"],
@@ -36,7 +56,28 @@ function resolveApiKeyForProvider(config) {
36
56
  if (process.env[alt])
37
57
  return process.env[alt];
38
58
  }
39
- throw new Error(`No API key found for ${config.provider}. Set ${envVar} environment variable or add apiKey to .repomemory.json`);
59
+ throw new AIError(`No API key found for ${config.provider}. Set ${envVar} environment variable or add apiKey to .repomemory.json`, config.provider);
60
+ }
61
+ /** Estimate cost for a given provider/model/token count */
62
+ export function estimateCost(provider, model, inputTokens, outputTokens) {
63
+ // Approximate pricing per 1M tokens (as of 2025)
64
+ const pricing = {
65
+ "claude-sonnet-4-5-20250929": { input: 3, output: 15 },
66
+ "claude-opus-4-6": { input: 15, output: 75 },
67
+ "gpt-4o": { input: 2.5, output: 10 },
68
+ "o3-mini": { input: 1.1, output: 4.4 },
69
+ "gemini-2.0-flash": { input: 0.1, output: 0.4 },
70
+ "gemini-2.5-pro": { input: 1.25, output: 10 },
71
+ "grok-3": { input: 3, output: 15 },
72
+ "grok-3-mini": { input: 0.3, output: 0.5 },
73
+ };
74
+ const price = pricing[model];
75
+ if (!price)
76
+ return "unknown";
77
+ const cost = (inputTokens / 1_000_000) * price.input + (outputTokens / 1_000_000) * price.output;
78
+ if (cost < 0.01)
79
+ return "<$0.01";
80
+ return `~$${cost.toFixed(2)}`;
40
81
  }
41
82
  // --- Anthropic (streaming for large outputs) ---
42
83
  async function createAnthropicProvider(apiKey, model) {
@@ -53,32 +94,30 @@ async function createAnthropicProvider(apiKey, model) {
53
94
  role: m.role,
54
95
  content: m.content,
55
96
  }));
56
- // Use streaming to handle large outputs (required for >10min responses)
57
- const stream = client.messages.stream({
58
- model: model || "claude-sonnet-4-5-20250929",
59
- max_tokens: maxTokens,
60
- temperature,
61
- system: systemMsg?.content || "",
62
- messages: conversationMsgs,
63
- });
64
- // Show progress dots while streaming
65
- let dotCount = 0;
66
- stream.on("text", () => {
67
- dotCount++;
68
- if (dotCount % 200 === 0) {
69
- process.stderr.write(".");
70
- }
71
- });
72
- const finalMessage = await stream.finalMessage();
73
- process.stderr.write("\n");
74
- const content = finalMessage.content
75
- .filter((block) => block.type === "text")
76
- .map((block) => ("text" in block ? block.text : ""))
77
- .join("");
78
- return {
79
- content,
80
- tokensUsed: finalMessage.usage.input_tokens + finalMessage.usage.output_tokens,
81
- };
97
+ try {
98
+ const stream = client.messages.stream({
99
+ model: model || "claude-sonnet-4-5-20250929",
100
+ max_tokens: maxTokens,
101
+ temperature,
102
+ system: systemMsg?.content || "",
103
+ messages: conversationMsgs,
104
+ });
105
+ const finalMessage = await stream.finalMessage();
106
+ const content = finalMessage.content
107
+ .filter((block) => block.type === "text")
108
+ .map((block) => ("text" in block ? block.text : ""))
109
+ .join("");
110
+ return {
111
+ content,
112
+ tokensUsed: finalMessage.usage.input_tokens + finalMessage.usage.output_tokens,
113
+ inputTokens: finalMessage.usage.input_tokens,
114
+ outputTokens: finalMessage.usage.output_tokens,
115
+ };
116
+ }
117
+ catch (err) {
118
+ const e = err;
119
+ throw new AIError(e.message, "anthropic", e.status, e.status === 429 || e.status === 529 || e.status === 500);
120
+ }
82
121
  },
83
122
  };
84
123
  }
@@ -90,19 +129,28 @@ async function createOpenAIProvider(apiKey, model) {
90
129
  name: "openai",
91
130
  async generate(messages, options = {}) {
92
131
  const { maxTokens = 16000, temperature = 0.3 } = options;
93
- const response = await client.chat.completions.create({
94
- model: model || "gpt-4o",
95
- max_tokens: maxTokens,
96
- temperature,
97
- messages: messages.map((m) => ({
98
- role: m.role,
99
- content: m.content,
100
- })),
101
- });
102
- return {
103
- content: response.choices[0]?.message?.content || "",
104
- tokensUsed: response.usage?.total_tokens,
105
- };
132
+ try {
133
+ const response = await client.chat.completions.create({
134
+ model: model || "gpt-4o",
135
+ max_completion_tokens: maxTokens,
136
+ temperature,
137
+ messages: messages.map((m) => ({
138
+ role: m.role,
139
+ content: m.content,
140
+ })),
141
+ });
142
+ const usage = response.usage;
143
+ return {
144
+ content: response.choices[0]?.message?.content || "",
145
+ tokensUsed: usage?.total_tokens,
146
+ inputTokens: usage?.prompt_tokens,
147
+ outputTokens: usage?.completion_tokens,
148
+ };
149
+ }
150
+ catch (err) {
151
+ const e = err;
152
+ throw new AIError(e.message, "openai", e.status, e.status === 429 || e.status === 500);
153
+ }
106
154
  },
107
155
  };
108
156
  }
@@ -110,27 +158,39 @@ async function createOpenAIProvider(apiKey, model) {
110
158
  async function createGeminiProvider(apiKey, model) {
111
159
  const { GoogleGenerativeAI } = await import("@google/generative-ai");
112
160
  const genAI = new GoogleGenerativeAI(apiKey);
113
- const genModel = genAI.getGenerativeModel({ model: model || "gemini-2.0-flash" });
161
+ const modelName = model || "gemini-2.0-flash";
114
162
  return {
115
163
  name: "gemini",
116
164
  async generate(messages, options = {}) {
117
- const { temperature = 0.3 } = options;
118
- // Combine system + user messages for Gemini
165
+ const { temperature = 0.3, maxTokens = 16000 } = options;
119
166
  const systemMsg = messages.find((m) => m.role === "system");
120
167
  const userMsgs = messages.filter((m) => m.role !== "system");
121
- const prompt = [
122
- systemMsg ? `<system>\n${systemMsg.content}\n</system>\n\n` : "",
123
- ...userMsgs.map((m) => m.content),
124
- ].join("\n");
125
- const result = await genModel.generateContent({
126
- contents: [{ role: "user", parts: [{ text: prompt }] }],
127
- generationConfig: { temperature },
168
+ // Use systemInstruction properly
169
+ const genModel = genAI.getGenerativeModel({
170
+ model: modelName,
171
+ systemInstruction: systemMsg?.content || undefined,
128
172
  });
129
- const response = result.response;
130
- return {
131
- content: response.text(),
132
- tokensUsed: response.usageMetadata?.totalTokenCount,
133
- };
173
+ try {
174
+ const result = await genModel.generateContent({
175
+ contents: userMsgs.map((m) => ({
176
+ role: m.role === "assistant" ? "model" : "user",
177
+ parts: [{ text: m.content }],
178
+ })),
179
+ generationConfig: { temperature, maxOutputTokens: maxTokens },
180
+ });
181
+ const response = result.response;
182
+ const usage = response.usageMetadata;
183
+ return {
184
+ content: response.text(),
185
+ tokensUsed: usage?.totalTokenCount,
186
+ inputTokens: usage?.promptTokenCount,
187
+ outputTokens: usage?.candidatesTokenCount,
188
+ };
189
+ }
190
+ catch (err) {
191
+ const e = err;
192
+ throw new AIError(e.message, "gemini", e.status, true);
193
+ }
134
194
  },
135
195
  };
136
196
  }
@@ -145,19 +205,28 @@ async function createGrokProvider(apiKey, model) {
145
205
  name: "grok",
146
206
  async generate(messages, options = {}) {
147
207
  const { maxTokens = 16000, temperature = 0.3 } = options;
148
- const response = await client.chat.completions.create({
149
- model: model || "grok-3",
150
- max_tokens: maxTokens,
151
- temperature,
152
- messages: messages.map((m) => ({
153
- role: m.role,
154
- content: m.content,
155
- })),
156
- });
157
- return {
158
- content: response.choices[0]?.message?.content || "",
159
- tokensUsed: response.usage?.total_tokens,
160
- };
208
+ try {
209
+ const response = await client.chat.completions.create({
210
+ model: model || "grok-3",
211
+ max_tokens: maxTokens,
212
+ temperature,
213
+ messages: messages.map((m) => ({
214
+ role: m.role,
215
+ content: m.content,
216
+ })),
217
+ });
218
+ const usage = response.usage;
219
+ return {
220
+ content: response.choices[0]?.message?.content || "",
221
+ tokensUsed: usage?.total_tokens,
222
+ inputTokens: usage?.prompt_tokens,
223
+ outputTokens: usage?.completion_tokens,
224
+ };
225
+ }
226
+ catch (err) {
227
+ const e = err;
228
+ throw new AIError(e.message, "grok", e.status, e.status === 429 || e.status === 500);
229
+ }
161
230
  },
162
231
  };
163
232
  }