@hasna/terminal 1.3.6 → 1.3.8
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/ai.js +13 -9
- package/dist/cli.js +16 -1
- package/package.json +1 -1
- package/src/ai.ts +11 -8
- package/src/cli.tsx +15 -1
package/dist/ai.js
CHANGED
|
@@ -211,23 +211,27 @@ export async function translateToCommand(nl, perms, sessionEntries, onToken) {
|
|
|
211
211
|
let cleaned = text.trim();
|
|
212
212
|
// Remove ALL markdown code blocks and their content markers
|
|
213
213
|
cleaned = cleaned.replace(/```(?:bash|sh|shell)?\n?/g, "").replace(/```/g, "");
|
|
214
|
-
// Split into lines and find the FIRST one that looks like a
|
|
214
|
+
// Split into lines and find the FIRST one that looks like a SHELL COMMAND
|
|
215
215
|
const lines = cleaned.split("\n");
|
|
216
216
|
let command = "";
|
|
217
217
|
for (const line of lines) {
|
|
218
218
|
const t = line.trim();
|
|
219
219
|
if (!t)
|
|
220
220
|
continue;
|
|
221
|
-
// Skip
|
|
222
|
-
if (/^(Based on|I |This |The |Let me|Here|Note:|Since|Looking|To |However|BLOCKED:|If |You |We |For )/.test(t))
|
|
221
|
+
// Skip lines that are clearly English prose, not commands
|
|
222
|
+
if (/^(Based on|I |This |The |Let me|Here|Note:|Since|Looking|To |However|BLOCKED:|If |You |We |For |It |A |An |That )/.test(t))
|
|
223
223
|
continue;
|
|
224
|
-
if (/^[A-Z][a-z].*[
|
|
225
|
-
continue;
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
224
|
+
if (/^[A-Z][a-z].*[.;:!?,]/.test(t))
|
|
225
|
+
continue; // English sentence with punctuation anywhere
|
|
226
|
+
if (t.split(" ").length > 15 && !/[|&;><$]/.test(t))
|
|
227
|
+
continue; // Long line without shell operators = prose
|
|
228
|
+
// Must start with a plausible command character (lowercase, /, ., $, or common tool)
|
|
229
|
+
if (/^[a-z./$~(]/.test(t) || /^[A-Z]+[_=]/.test(t)) {
|
|
230
|
+
command = t;
|
|
231
|
+
break;
|
|
232
|
+
}
|
|
229
233
|
}
|
|
230
|
-
cleaned = command ||
|
|
234
|
+
cleaned = command || lines[0]?.trim() || cleaned;
|
|
231
235
|
cacheSet(nl, cleaned);
|
|
232
236
|
return cleaned;
|
|
233
237
|
}
|
package/dist/cli.js
CHANGED
|
@@ -421,6 +421,21 @@ else if (args.length > 0) {
|
|
|
421
421
|
command = await translateToCommand(prompt, perms, []);
|
|
422
422
|
}
|
|
423
423
|
catch (e) {
|
|
424
|
+
// If BLOCKED, try fallback: read README or package.json for conceptual questions
|
|
425
|
+
if (e.message?.startsWith("BLOCKED:")) {
|
|
426
|
+
try {
|
|
427
|
+
const { existsSync, readFileSync } = await import("fs");
|
|
428
|
+
if (existsSync("README.md")) {
|
|
429
|
+
const readme = readFileSync("README.md", "utf8").slice(0, 3000);
|
|
430
|
+
const processed = await processOutput("cat README.md", readme, prompt);
|
|
431
|
+
if (processed.aiProcessed) {
|
|
432
|
+
console.log(processed.summary);
|
|
433
|
+
process.exit(0);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
catch { }
|
|
438
|
+
}
|
|
424
439
|
console.error(e.message);
|
|
425
440
|
process.exit(1);
|
|
426
441
|
}
|
|
@@ -434,7 +449,7 @@ else if (args.length > 0) {
|
|
|
434
449
|
if (isIrreversible(command)) {
|
|
435
450
|
console.error(`⚠ IRREVERSIBLE: $ ${command}`);
|
|
436
451
|
console.error(` This command may kill processes, push code, or delete data.`);
|
|
437
|
-
console.error(` Run
|
|
452
|
+
console.error(` Run directly in your shell if you're sure: ${command}`);
|
|
438
453
|
process.exit(1);
|
|
439
454
|
}
|
|
440
455
|
// Show what we're running
|
package/package.json
CHANGED
package/src/ai.ts
CHANGED
|
@@ -253,20 +253,23 @@ export async function translateToCommand(
|
|
|
253
253
|
let cleaned = text.trim();
|
|
254
254
|
// Remove ALL markdown code blocks and their content markers
|
|
255
255
|
cleaned = cleaned.replace(/```(?:bash|sh|shell)?\n?/g, "").replace(/```/g, "");
|
|
256
|
-
// Split into lines and find the FIRST one that looks like a
|
|
256
|
+
// Split into lines and find the FIRST one that looks like a SHELL COMMAND
|
|
257
257
|
const lines = cleaned.split("\n");
|
|
258
258
|
let command = "";
|
|
259
259
|
for (const line of lines) {
|
|
260
260
|
const t = line.trim();
|
|
261
261
|
if (!t) continue;
|
|
262
|
-
// Skip
|
|
263
|
-
if (/^(Based on|I |This |The |Let me|Here|Note:|Since|Looking|To |However|BLOCKED:|If |You |We |For )/.test(t)) continue;
|
|
264
|
-
if (/^[A-Z][a-z].*[
|
|
265
|
-
|
|
266
|
-
command
|
|
267
|
-
|
|
262
|
+
// Skip lines that are clearly English prose, not commands
|
|
263
|
+
if (/^(Based on|I |This |The |Let me|Here|Note:|Since|Looking|To |However|BLOCKED:|If |You |We |For |It |A |An |That )/.test(t)) continue;
|
|
264
|
+
if (/^[A-Z][a-z].*[.;:!?,]/.test(t)) continue; // English sentence with punctuation anywhere
|
|
265
|
+
if (t.split(" ").length > 15 && !/[|&;><$]/.test(t)) continue; // Long line without shell operators = prose
|
|
266
|
+
// Must start with a plausible command character (lowercase, /, ., $, or common tool)
|
|
267
|
+
if (/^[a-z./$~(]/.test(t) || /^[A-Z]+[_=]/.test(t)) {
|
|
268
|
+
command = t;
|
|
269
|
+
break;
|
|
270
|
+
}
|
|
268
271
|
}
|
|
269
|
-
cleaned = command ||
|
|
272
|
+
cleaned = command || lines[0]?.trim() || cleaned;
|
|
270
273
|
|
|
271
274
|
cacheSet(nl, cleaned);
|
|
272
275
|
return cleaned;
|
package/src/cli.tsx
CHANGED
|
@@ -402,6 +402,20 @@ else if (args.length > 0) {
|
|
|
402
402
|
try {
|
|
403
403
|
command = await translateToCommand(prompt, perms, []);
|
|
404
404
|
} catch (e: any) {
|
|
405
|
+
// If BLOCKED, try fallback: read README or package.json for conceptual questions
|
|
406
|
+
if (e.message?.startsWith("BLOCKED:")) {
|
|
407
|
+
try {
|
|
408
|
+
const { existsSync, readFileSync } = await import("fs");
|
|
409
|
+
if (existsSync("README.md")) {
|
|
410
|
+
const readme = readFileSync("README.md", "utf8").slice(0, 3000);
|
|
411
|
+
const processed = await processOutput("cat README.md", readme, prompt);
|
|
412
|
+
if (processed.aiProcessed) {
|
|
413
|
+
console.log(processed.summary);
|
|
414
|
+
process.exit(0);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
} catch {}
|
|
418
|
+
}
|
|
405
419
|
console.error(e.message);
|
|
406
420
|
process.exit(1);
|
|
407
421
|
}
|
|
@@ -414,7 +428,7 @@ else if (args.length > 0) {
|
|
|
414
428
|
if (isIrreversible(command)) {
|
|
415
429
|
console.error(`⚠ IRREVERSIBLE: $ ${command}`);
|
|
416
430
|
console.error(` This command may kill processes, push code, or delete data.`);
|
|
417
|
-
console.error(` Run
|
|
431
|
+
console.error(` Run directly in your shell if you're sure: ${command}`);
|
|
418
432
|
process.exit(1);
|
|
419
433
|
}
|
|
420
434
|
|