@intend-it/cli 1.1.1 → 1.1.3
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 +86 -6
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -137,6 +137,7 @@ function printHelp() {
|
|
|
137
137
|
console.log(` ${cmd("--config")} ${dim("<path>")} Path to config file`);
|
|
138
138
|
console.log(` ${cmd("--output")} ${dim("<dir>")} Output directory`);
|
|
139
139
|
console.log(` ${cmd("--provider")} ${dim("<name>")} AI provider ${dim("(gemini | ollama)")}`);
|
|
140
|
+
console.log(` ${cmd("--model")} ${dim("<name>")} AI model name`);
|
|
140
141
|
console.log(` ${cmd("--api-key")} ${dim("<key>")} Gemini API key`);
|
|
141
142
|
console.log(` ${cmd("--force")} Force regeneration (skip cache)`);
|
|
142
143
|
console.log(` ${cmd("--help")} Show this help`);
|
|
@@ -174,14 +175,45 @@ async function initCommand(args) {
|
|
|
174
175
|
text: warn(error2.message)
|
|
175
176
|
});
|
|
176
177
|
}
|
|
178
|
+
const typesPath = join2(directory, "src", "types.ts");
|
|
179
|
+
if (!existsSync2(typesPath)) {
|
|
180
|
+
const typesContent = `export interface User {
|
|
181
|
+
name: string;
|
|
182
|
+
id: number;
|
|
183
|
+
createdAt: Date;
|
|
184
|
+
}`;
|
|
185
|
+
writeFileSync2(typesPath, typesContent, "utf-8");
|
|
186
|
+
console.log(bullet(`${dim("src/types.ts")} ${dim("(typescript definition)")}`));
|
|
187
|
+
}
|
|
177
188
|
const examplePath = join2(srcDir, "example.intent");
|
|
178
189
|
if (!existsSync2(examplePath)) {
|
|
179
|
-
const exampleContent = `
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
190
|
+
const exampleContent = `import { User } from "../types";
|
|
191
|
+
|
|
192
|
+
export intent CreateUser(name: string) -> User {
|
|
193
|
+
step "Generate a random ID" => const id
|
|
194
|
+
step "Create a User object with name, id, and current date" => const user
|
|
195
|
+
return user
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
export entry intent Main() -> void {
|
|
199
|
+
step "Call CreateUser with name 'Intender'" => const user
|
|
200
|
+
step "Log 'Created user:' and the user object to console"
|
|
201
|
+
}
|
|
202
|
+
`;
|
|
183
203
|
writeFileSync2(examplePath, exampleContent, "utf-8");
|
|
184
|
-
console.log(bullet(`${dim("src/intents/example.intent")} ${dim("(example)")}`));
|
|
204
|
+
console.log(bullet(`${dim("src/intents/example.intent")} ${dim("(example intent)")}`));
|
|
205
|
+
}
|
|
206
|
+
const gitignorePath = join2(directory, ".gitignore");
|
|
207
|
+
if (!existsSync2(gitignorePath)) {
|
|
208
|
+
const gitignoreContent = `node_modules/
|
|
209
|
+
dist/
|
|
210
|
+
out/
|
|
211
|
+
.intend/
|
|
212
|
+
.env
|
|
213
|
+
.DS_Store
|
|
214
|
+
`;
|
|
215
|
+
writeFileSync2(gitignorePath, gitignoreContent, "utf-8");
|
|
216
|
+
console.log(bullet(`${dim(".gitignore")} ${dim("(git config)")}`));
|
|
185
217
|
}
|
|
186
218
|
newline();
|
|
187
219
|
printSuccess("Project initialized");
|
|
@@ -196,7 +228,8 @@ async function initCommand(args) {
|
|
|
196
228
|
// src/commands/build.ts
|
|
197
229
|
import { existsSync as existsSync3, mkdirSync as mkdirSync2, writeFileSync as writeFileSync3, readFileSync as readFileSync2 } from "fs";
|
|
198
230
|
import { join as join3, resolve as resolve3, basename } from "path";
|
|
199
|
-
import { AICodeGenerator, FileSystemCAS, computeHash } from "@intend-it/core";
|
|
231
|
+
import { AICodeGenerator, FileSystemCAS, computeHash, OllamaProvider } from "@intend-it/core";
|
|
232
|
+
import * as readline from "readline";
|
|
200
233
|
import { parseToAST } from "@intend-it/parser";
|
|
201
234
|
import { readdirSync, statSync } from "fs";
|
|
202
235
|
function findIntentFiles(dir, fileList = []) {
|
|
@@ -224,6 +257,13 @@ async function buildCommand(options) {
|
|
|
224
257
|
config.gemini.apiKey = options.apiKey;
|
|
225
258
|
if (options.provider)
|
|
226
259
|
config.provider = options.provider;
|
|
260
|
+
if (options.model) {
|
|
261
|
+
if (config.provider === "ollama" && config.ollama) {
|
|
262
|
+
config.ollama.model = options.model;
|
|
263
|
+
} else if (config.gemini) {
|
|
264
|
+
config.gemini.model = options.model;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
227
267
|
const sourceDir = resolve3(process.cwd(), config.sourceDir);
|
|
228
268
|
const outDir = resolve3(process.cwd(), config.outDir);
|
|
229
269
|
const providerName = config.provider || "gemini";
|
|
@@ -294,6 +334,42 @@ async function buildCommand(options) {
|
|
|
294
334
|
connectSpinner.fail(error(`Connection failed: ${error2.message}`));
|
|
295
335
|
process.exit(1);
|
|
296
336
|
}
|
|
337
|
+
const provider = generator.getProvider();
|
|
338
|
+
if (provider instanceof OllamaProvider) {
|
|
339
|
+
const ollama = provider;
|
|
340
|
+
if (typeof ollama.checkModelExists === "function") {
|
|
341
|
+
const exists = await ollama.checkModelExists();
|
|
342
|
+
if (!exists) {
|
|
343
|
+
const modelName = config.ollama?.model || "llama3";
|
|
344
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
345
|
+
console.log();
|
|
346
|
+
const answer = await new Promise((resolve4) => {
|
|
347
|
+
rl.question(` ${icons.info} Model '${accent(modelName)}' is not found locally.
|
|
348
|
+
${dim("Do you want to pull it now? [Y/n]")} `, resolve4);
|
|
349
|
+
});
|
|
350
|
+
rl.close();
|
|
351
|
+
if (answer.toLowerCase() === "n") {
|
|
352
|
+
printError("Model missing, cannot proceed.");
|
|
353
|
+
process.exit(1);
|
|
354
|
+
}
|
|
355
|
+
const pullSpinner = spinner(`Pulling ${modelName}...`).start();
|
|
356
|
+
try {
|
|
357
|
+
await ollama.pullModel((status, completed, total) => {
|
|
358
|
+
if (completed && total) {
|
|
359
|
+
const percent = Math.round(completed / total * 100);
|
|
360
|
+
pullSpinner.text = `Pulling ${modelName}: ${status} ${percent}%`;
|
|
361
|
+
} else {
|
|
362
|
+
pullSpinner.text = `Pulling ${modelName}: ${status}`;
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
pullSpinner.succeed(`${modelName} ready`);
|
|
366
|
+
} catch (e) {
|
|
367
|
+
pullSpinner.fail(`Failed to pull model: ${e.message}`);
|
|
368
|
+
process.exit(1);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
297
373
|
const casDir = resolve3(process.cwd(), ".intend", "store");
|
|
298
374
|
const cas = new FileSystemCAS(casDir);
|
|
299
375
|
let successCount = 0;
|
|
@@ -425,6 +501,8 @@ async function handleBuild(args2) {
|
|
|
425
501
|
options.apiKey = args2[i + 1];
|
|
426
502
|
if (args2[i] === "--provider")
|
|
427
503
|
options.provider = args2[i + 1];
|
|
504
|
+
if (args2[i] === "--model")
|
|
505
|
+
options.model = args2[i + 1];
|
|
428
506
|
if (args2[i] === "--watch")
|
|
429
507
|
options.watch = true;
|
|
430
508
|
if (args2[i] === "--force")
|
|
@@ -449,6 +527,8 @@ async function handleWatch(args2) {
|
|
|
449
527
|
options.apiKey = args2[i + 1];
|
|
450
528
|
if (args2[i] === "--provider")
|
|
451
529
|
options.provider = args2[i + 1];
|
|
530
|
+
if (args2[i] === "--model")
|
|
531
|
+
options.model = args2[i + 1];
|
|
452
532
|
}
|
|
453
533
|
await watchCommand(options);
|
|
454
534
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intend-it/cli",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.3",
|
|
4
4
|
"description": "CLI for the Intend programming language",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
],
|
|
30
30
|
"license": "MIT",
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@intend-it/parser": "^1.1.
|
|
33
|
-
"@intend-it/core": "^2.0.
|
|
32
|
+
"@intend-it/parser": "^1.1.3",
|
|
33
|
+
"@intend-it/core": "^2.0.3",
|
|
34
34
|
"picocolors": "^1.1.1",
|
|
35
35
|
"ora": "^8.1.1"
|
|
36
36
|
},
|