quackstack 1.0.15 ā 1.0.17
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/cli.cjs +2 -2
- package/dist/lib/ai-provider.js +13 -34
- package/dist/repl.js +65 -49
- package/package.json +1 -1
package/dist/cli.cjs
CHANGED
|
@@ -46,8 +46,8 @@ program
|
|
|
46
46
|
});
|
|
47
47
|
});
|
|
48
48
|
console.log(chalk_1.default.cyan("\nUsage:"));
|
|
49
|
-
console.log(chalk_1.default.white("
|
|
50
|
-
console.log(chalk_1.default.white("
|
|
49
|
+
console.log(chalk_1.default.white(" quack --provider anthropic --model claude-sonnet-4-20250514"));
|
|
50
|
+
console.log(chalk_1.default.white(" quack -p openai -m gpt-4o\n"));
|
|
51
51
|
process.exit(0);
|
|
52
52
|
}
|
|
53
53
|
const title = chalk_animation_1.default.rainbow("QuackStack\n");
|
package/dist/lib/ai-provider.js
CHANGED
|
@@ -68,18 +68,10 @@ export class AIClient {
|
|
|
68
68
|
provider: "openai",
|
|
69
69
|
name: "OpenAI",
|
|
70
70
|
models: [
|
|
71
|
-
"gpt-5",
|
|
72
|
-
"gpt-5-mini",
|
|
73
|
-
"gpt-5-nano",
|
|
74
|
-
"gpt-4.1",
|
|
75
|
-
"gpt-4.1-mini",
|
|
76
|
-
"gpt-4.1-nano",
|
|
77
71
|
"gpt-4o",
|
|
78
72
|
"gpt-4o-mini",
|
|
79
73
|
"gpt-4-turbo",
|
|
80
|
-
"
|
|
81
|
-
"o4-mini",
|
|
82
|
-
"o4-mini-high"
|
|
74
|
+
"gpt-3.5-turbo"
|
|
83
75
|
],
|
|
84
76
|
defaultModel: "gpt-4o-mini"
|
|
85
77
|
});
|
|
@@ -89,15 +81,12 @@ export class AIClient {
|
|
|
89
81
|
provider: "anthropic",
|
|
90
82
|
name: "Anthropic",
|
|
91
83
|
models: [
|
|
92
|
-
"claude-opus-4-
|
|
93
|
-
"claude-
|
|
94
|
-
"claude-sonnet-
|
|
95
|
-
"claude-
|
|
96
|
-
"claude-haiku-4-5",
|
|
97
|
-
"claude-3-7-sonnet",
|
|
98
|
-
"claude-3-5-haiku"
|
|
84
|
+
"claude-opus-4-20250514",
|
|
85
|
+
"claude-sonnet-4-20250514",
|
|
86
|
+
"claude-3-7-sonnet-20250219",
|
|
87
|
+
"claude-3-5-haiku-20241022"
|
|
99
88
|
],
|
|
100
|
-
defaultModel: "claude-sonnet-4"
|
|
89
|
+
defaultModel: "claude-sonnet-4-20250514"
|
|
101
90
|
});
|
|
102
91
|
}
|
|
103
92
|
if (process.env.QUACKSTACK_GEMINI_KEY) {
|
|
@@ -105,16 +94,12 @@ export class AIClient {
|
|
|
105
94
|
provider: "gemini",
|
|
106
95
|
name: "Gemini",
|
|
107
96
|
models: [
|
|
108
|
-
"gemini-
|
|
109
|
-
"gemini-3-pro",
|
|
110
|
-
"gemini-2.5-pro",
|
|
111
|
-
"gemini-2.5-flash",
|
|
112
|
-
"gemini-2.5-flash-lite",
|
|
113
|
-
"gemini-2.0-flash",
|
|
97
|
+
"gemini-2.0-flash-exp",
|
|
114
98
|
"gemini-1.5-pro",
|
|
115
|
-
"gemini-1.5-flash"
|
|
99
|
+
"gemini-1.5-flash",
|
|
100
|
+
"gemini-1.5-flash-8b"
|
|
116
101
|
],
|
|
117
|
-
defaultModel: "gemini-
|
|
102
|
+
defaultModel: "gemini-1.5-flash"
|
|
118
103
|
});
|
|
119
104
|
}
|
|
120
105
|
if (process.env.QUACKSTACK_DEEPSEEK_KEY) {
|
|
@@ -134,14 +119,8 @@ export class AIClient {
|
|
|
134
119
|
name: "Mistral",
|
|
135
120
|
models: [
|
|
136
121
|
"mistral-large-latest",
|
|
137
|
-
"mistral-large-24.11",
|
|
138
|
-
"mistral-medium-3",
|
|
139
122
|
"mistral-small-latest",
|
|
140
|
-
"codestral-
|
|
141
|
-
"codestral-latest",
|
|
142
|
-
"magistral-small-2506",
|
|
143
|
-
"magistral-medium-2506",
|
|
144
|
-
"pixtral-12b"
|
|
123
|
+
"codestral-latest"
|
|
145
124
|
],
|
|
146
125
|
defaultModel: "mistral-large-latest"
|
|
147
126
|
});
|
|
@@ -151,8 +130,8 @@ export class AIClient {
|
|
|
151
130
|
getDefaultModel(provider) {
|
|
152
131
|
const defaults = {
|
|
153
132
|
openai: "gpt-4o-mini",
|
|
154
|
-
anthropic: "claude-sonnet-4",
|
|
155
|
-
gemini: "gemini-
|
|
133
|
+
anthropic: "claude-sonnet-4-20250514",
|
|
134
|
+
gemini: "gemini-1.5-flash",
|
|
156
135
|
deepseek: "deepseek-chat",
|
|
157
136
|
mistral: "mistral-large-latest",
|
|
158
137
|
};
|
package/dist/repl.js
CHANGED
|
@@ -8,17 +8,33 @@ import { detectFileChanges, formatChangeMessage } from "./lib/file-change-detect
|
|
|
8
8
|
import { getAIClient, resetAIClient } from "./lib/ai-provider.js";
|
|
9
9
|
const PROJECT_NAME = path.basename(process.cwd());
|
|
10
10
|
export async function startREPL(forceReindex = false, provider, model) {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
console.log(chalk.cyan("\nš„ Welcome to QuackStack!\n"));
|
|
12
|
+
try {
|
|
13
|
+
const aiClient = getAIClient(provider, model);
|
|
14
|
+
console.log(chalk.cyan(`Using: ${aiClient.getProviderName()} - ${aiClient.getModel()}`));
|
|
15
|
+
console.log(chalk.gray("š” Tip: Type '/help' for commands or 'quack --list-models' to see all options"));
|
|
16
|
+
console.log(chalk.cyan("ā” Press Ctrl+C to exit\n"));
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
console.error(chalk.red(`\nFailed to initialize AI provider: ${error.message}\n`));
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
15
22
|
if (!forceReindex) {
|
|
16
23
|
const changes = await detectFileChanges(process.cwd(), PROJECT_NAME);
|
|
17
24
|
if (changes && changes.totalChanges > 0) {
|
|
18
|
-
console.log(chalk.yellow(`\
|
|
25
|
+
console.log(chalk.yellow(`\nā ļø Detected ${changes.totalChanges} file change${changes.totalChanges > 1 ? 's' : ''} since last index:`));
|
|
19
26
|
console.log(chalk.yellow(` ${formatChangeMessage(changes)}`));
|
|
20
27
|
console.log(chalk.yellow(` Run 'quack --reindex' for best results.\n`));
|
|
21
|
-
const
|
|
28
|
+
const tempRl = readline.createInterface({
|
|
29
|
+
input: process.stdin,
|
|
30
|
+
output: process.stdout,
|
|
31
|
+
});
|
|
32
|
+
const shouldReindex = await new Promise((resolve) => {
|
|
33
|
+
tempRl.question(chalk.yellow("Reindex now? (y/n) > "), (answer) => {
|
|
34
|
+
tempRl.close();
|
|
35
|
+
resolve(answer);
|
|
36
|
+
});
|
|
37
|
+
});
|
|
22
38
|
if (shouldReindex.toLowerCase() === 'y') {
|
|
23
39
|
forceReindex = true;
|
|
24
40
|
}
|
|
@@ -34,14 +50,14 @@ export async function startREPL(forceReindex = false, provider, model) {
|
|
|
34
50
|
where: { projectName: PROJECT_NAME },
|
|
35
51
|
});
|
|
36
52
|
}
|
|
37
|
-
console.log(chalk.gray("Indexing your codebase..."));
|
|
53
|
+
console.log(chalk.gray("š Indexing your codebase..."));
|
|
38
54
|
await ingest(process.cwd(), PROJECT_NAME, true);
|
|
39
|
-
console.log(chalk.green("Indexing complete"));
|
|
55
|
+
console.log(chalk.green("Indexing complete\n"));
|
|
40
56
|
}
|
|
41
57
|
const rl = readline.createInterface({
|
|
42
58
|
input: process.stdin,
|
|
43
59
|
output: process.stdout,
|
|
44
|
-
prompt: chalk.yellow("quack > "),
|
|
60
|
+
prompt: chalk.yellow("š„ quack > "),
|
|
45
61
|
});
|
|
46
62
|
rl.prompt();
|
|
47
63
|
rl.on("line", async (line) => {
|
|
@@ -58,23 +74,25 @@ export async function startREPL(forceReindex = false, provider, model) {
|
|
|
58
74
|
try {
|
|
59
75
|
const { answer, sources } = await search(query, PROJECT_NAME, provider, model);
|
|
60
76
|
console.log(chalk.white(`\n${answer}\n`));
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
77
|
+
rl.question(chalk.cyan("š” Want more details? (y/n) > "), (showDetails) => {
|
|
78
|
+
if (showDetails.toLowerCase() === "y") {
|
|
79
|
+
console.log(chalk.blue("\nš Relevant Code:\n"));
|
|
80
|
+
sources.forEach((src, i) => {
|
|
81
|
+
console.log(chalk.gray(`[${i + 1}] ${src.filePath} (relevance: ${(src.score * 100).toFixed(1)}%)`));
|
|
82
|
+
console.log(chalk.white(src.content));
|
|
83
|
+
console.log(chalk.gray("\n---\n"));
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
rl.prompt();
|
|
87
|
+
});
|
|
70
88
|
}
|
|
71
89
|
catch (error) {
|
|
72
|
-
console.error(chalk.red(`\
|
|
90
|
+
console.error(chalk.red(`\nā Error: ${error.message}\n`));
|
|
91
|
+
rl.prompt();
|
|
73
92
|
}
|
|
74
|
-
rl.prompt();
|
|
75
93
|
});
|
|
76
94
|
rl.on("close", () => {
|
|
77
|
-
console.log(chalk.gray("\
|
|
95
|
+
console.log(chalk.gray("\nš Happy coding!\n"));
|
|
78
96
|
process.exit(0);
|
|
79
97
|
});
|
|
80
98
|
}
|
|
@@ -84,8 +102,13 @@ async function handleCommand(command, rl) {
|
|
|
84
102
|
case "model":
|
|
85
103
|
case "m":
|
|
86
104
|
if (args.length === 0) {
|
|
87
|
-
|
|
88
|
-
|
|
105
|
+
try {
|
|
106
|
+
const client = getAIClient();
|
|
107
|
+
console.log(chalk.cyan(`\nCurrent: ${client.getProviderName()} - ${client.getModel()}\n`));
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
console.log(chalk.red(`\nā Error: ${error.message}\n`));
|
|
111
|
+
}
|
|
89
112
|
}
|
|
90
113
|
else {
|
|
91
114
|
const [newModel] = args;
|
|
@@ -95,56 +118,49 @@ async function handleCommand(command, rl) {
|
|
|
95
118
|
console.log(chalk.green(`\nSwitched to: ${client.getProviderName()} - ${client.getModel()}\n`));
|
|
96
119
|
}
|
|
97
120
|
catch (error) {
|
|
98
|
-
console.log(chalk.red(`\
|
|
121
|
+
console.log(chalk.red(`\nā Error: ${error.message}\n`));
|
|
99
122
|
}
|
|
100
123
|
}
|
|
101
124
|
break;
|
|
102
125
|
case "provider":
|
|
103
126
|
case "p":
|
|
104
127
|
if (args.length === 0) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
128
|
+
try {
|
|
129
|
+
const client = getAIClient();
|
|
130
|
+
const providers = client.getAvailableProviders();
|
|
131
|
+
console.log(chalk.cyan("\nš Available Providers:\n"));
|
|
132
|
+
providers.forEach(p => {
|
|
133
|
+
const current = p.provider === client.getProvider() ? chalk.green(" ā current") : "";
|
|
134
|
+
console.log(chalk.white(` ⢠${p.provider}: ${p.name}${current}`));
|
|
135
|
+
});
|
|
136
|
+
console.log();
|
|
137
|
+
}
|
|
138
|
+
catch (error) {
|
|
139
|
+
console.log(chalk.red(`\nā Error: ${error.message}\n`));
|
|
140
|
+
}
|
|
113
141
|
}
|
|
114
142
|
else {
|
|
115
143
|
const [newProvider] = args;
|
|
116
144
|
try {
|
|
117
145
|
resetAIClient();
|
|
118
146
|
const client = getAIClient(newProvider);
|
|
119
|
-
console.log(chalk.green(`\
|
|
147
|
+
console.log(chalk.green(`\nā
Switched to: ${client.getProviderName()} - ${client.getModel()}\n`));
|
|
120
148
|
}
|
|
121
149
|
catch (error) {
|
|
122
|
-
console.log(chalk.red(`\
|
|
150
|
+
console.log(chalk.red(`\nā Error: ${error.message}\n`));
|
|
123
151
|
}
|
|
124
152
|
}
|
|
125
153
|
break;
|
|
126
154
|
case "help":
|
|
127
155
|
case "h":
|
|
128
|
-
console.log(chalk.cyan("\
|
|
156
|
+
console.log(chalk.cyan("\nš Available Commands:\n"));
|
|
129
157
|
console.log(chalk.white(" /model, /m [model] Show or change model"));
|
|
130
158
|
console.log(chalk.white(" /provider, /p [name] Show or change provider"));
|
|
131
159
|
console.log(chalk.white(" /help, /h Show this help"));
|
|
132
160
|
console.log();
|
|
133
161
|
break;
|
|
134
162
|
default:
|
|
135
|
-
console.log(chalk.red(`\
|
|
136
|
-
console.log(chalk.gray("Type /help for available commands\n"));
|
|
163
|
+
console.log(chalk.red(`\nā Unknown command: ${cmd}\n`));
|
|
164
|
+
console.log(chalk.gray("š” Type /help for available commands\n"));
|
|
137
165
|
}
|
|
138
166
|
}
|
|
139
|
-
function promptUser(question) {
|
|
140
|
-
const rl = readline.createInterface({
|
|
141
|
-
input: process.stdin,
|
|
142
|
-
output: process.stdout,
|
|
143
|
-
});
|
|
144
|
-
return new Promise((resolve) => {
|
|
145
|
-
rl.question(question, (answer) => {
|
|
146
|
-
rl.close();
|
|
147
|
-
resolve(answer);
|
|
148
|
-
});
|
|
149
|
-
});
|
|
150
|
-
}
|