@qlucent/fishi 0.14.4 → 0.14.6
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 +69 -25
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1017,8 +1017,37 @@ async function initCommand(description, options) {
|
|
|
1017
1017
|
}]);
|
|
1018
1018
|
sandboxMode = useSandbox ? "docker" : "process";
|
|
1019
1019
|
} else {
|
|
1020
|
-
console.log(chalk.yellow(" Docker not found.
|
|
1021
|
-
console.log(chalk.gray("
|
|
1020
|
+
console.log(chalk.yellow(" Docker not found."));
|
|
1021
|
+
console.log(chalk.gray(" Docker provides full agent isolation (recommended for security)."));
|
|
1022
|
+
console.log("");
|
|
1023
|
+
const { installDocker } = await inquirer.prompt([{
|
|
1024
|
+
type: "list",
|
|
1025
|
+
name: "installDocker",
|
|
1026
|
+
message: "How would you like to proceed?",
|
|
1027
|
+
choices: [
|
|
1028
|
+
{ name: "Install Docker (opens install page \u2014 recommended)", value: "install" },
|
|
1029
|
+
{ name: "Continue without Docker (process-level isolation only)", value: "skip" }
|
|
1030
|
+
],
|
|
1031
|
+
default: "install"
|
|
1032
|
+
}]);
|
|
1033
|
+
if (installDocker === "install") {
|
|
1034
|
+
const dockerUrl = "https://docs.docker.com/get-docker/";
|
|
1035
|
+
console.log("");
|
|
1036
|
+
console.log(chalk.cyan(` Opening: ${dockerUrl}`));
|
|
1037
|
+
console.log(chalk.gray(" Install Docker, then run `fishi init` again."));
|
|
1038
|
+
console.log("");
|
|
1039
|
+
try {
|
|
1040
|
+
const { execSync: execSyncOpen } = await import("child_process");
|
|
1041
|
+
const platform = process.platform;
|
|
1042
|
+
if (platform === "win32") execSyncOpen(`start ${dockerUrl}`, { stdio: "ignore" });
|
|
1043
|
+
else if (platform === "darwin") execSyncOpen(`open ${dockerUrl}`, { stdio: "ignore" });
|
|
1044
|
+
else execSyncOpen(`xdg-open ${dockerUrl}`, { stdio: "ignore" });
|
|
1045
|
+
} catch {
|
|
1046
|
+
console.log(chalk.gray(` Visit: ${dockerUrl}`));
|
|
1047
|
+
}
|
|
1048
|
+
return;
|
|
1049
|
+
}
|
|
1050
|
+
console.log(chalk.gray(" Continuing with process-level sandbox (limited isolation)."));
|
|
1022
1051
|
console.log("");
|
|
1023
1052
|
}
|
|
1024
1053
|
}
|
|
@@ -2468,14 +2497,41 @@ import ora4 from "ora";
|
|
|
2468
2497
|
import path16 from "path";
|
|
2469
2498
|
import fs16 from "fs";
|
|
2470
2499
|
import {
|
|
2471
|
-
getSettingsJsonTemplate,
|
|
2472
2500
|
getSoulMdTemplate,
|
|
2473
2501
|
getAgentsMdTemplate,
|
|
2474
2502
|
getSandboxPolicyTemplate,
|
|
2475
2503
|
getMonitorEmitterScript,
|
|
2476
2504
|
getFileLockHookScript
|
|
2477
2505
|
} from "@qlucent/fishi-core";
|
|
2478
|
-
var CURRENT_VERSION = "0.14.
|
|
2506
|
+
var CURRENT_VERSION = "0.14.4";
|
|
2507
|
+
function fixHooksFormat(settings) {
|
|
2508
|
+
if (!settings.hooks) return false;
|
|
2509
|
+
let fixed = false;
|
|
2510
|
+
for (const [event, entries] of Object.entries(settings.hooks)) {
|
|
2511
|
+
if (!Array.isArray(entries)) continue;
|
|
2512
|
+
for (let i = 0; i < entries.length; i++) {
|
|
2513
|
+
const entry = entries[i];
|
|
2514
|
+
if (entry.command && !entry.hooks) {
|
|
2515
|
+
entries[i] = {
|
|
2516
|
+
matcher: entry.matcher || "",
|
|
2517
|
+
hooks: [{ type: "command", command: entry.command }]
|
|
2518
|
+
};
|
|
2519
|
+
fixed = true;
|
|
2520
|
+
}
|
|
2521
|
+
}
|
|
2522
|
+
}
|
|
2523
|
+
return fixed;
|
|
2524
|
+
}
|
|
2525
|
+
function fixDenyRules(settings) {
|
|
2526
|
+
if (!settings.permissions?.deny) return false;
|
|
2527
|
+
const original = settings.permissions.deny.length;
|
|
2528
|
+
settings.permissions.deny = settings.permissions.deny.filter((rule) => {
|
|
2529
|
+
if (rule.includes(":(){ :|:& };:")) return false;
|
|
2530
|
+
if (/^Bash\(\s*\)$/.test(rule)) return false;
|
|
2531
|
+
return true;
|
|
2532
|
+
});
|
|
2533
|
+
return settings.permissions.deny.length !== original;
|
|
2534
|
+
}
|
|
2479
2535
|
async function upgradeCommand() {
|
|
2480
2536
|
const targetDir = process.cwd();
|
|
2481
2537
|
console.log("");
|
|
@@ -2493,30 +2549,18 @@ async function upgradeCommand() {
|
|
|
2493
2549
|
if (fs16.existsSync(settingsPath)) {
|
|
2494
2550
|
try {
|
|
2495
2551
|
const existing = JSON.parse(fs16.readFileSync(settingsPath, "utf-8"));
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
if (Array.isArray(entries)) {
|
|
2500
|
-
for (const entry of entries) {
|
|
2501
|
-
if (entry.command && !entry.hooks) {
|
|
2502
|
-
needsFix = true;
|
|
2503
|
-
break;
|
|
2504
|
-
}
|
|
2505
|
-
}
|
|
2506
|
-
}
|
|
2507
|
-
if (needsFix) break;
|
|
2508
|
-
}
|
|
2509
|
-
}
|
|
2510
|
-
if (needsFix) {
|
|
2552
|
+
const hooksFixed = fixHooksFormat(existing);
|
|
2553
|
+
const denyFixed = fixDenyRules(existing);
|
|
2554
|
+
if (hooksFixed || denyFixed) {
|
|
2511
2555
|
const backupDir = path16.join(targetDir, ".fishi", "backup", "upgrade-" + (/* @__PURE__ */ new Date()).toISOString().replace(/:/g, "-").replace(/\.\d+Z$/, ""));
|
|
2512
2556
|
fs16.mkdirSync(backupDir, { recursive: true });
|
|
2513
2557
|
fs16.copyFileSync(settingsPath, path16.join(backupDir, "settings.json"));
|
|
2514
|
-
fs16.writeFileSync(settingsPath,
|
|
2515
|
-
updated.push(".claude/settings.json (hooks format
|
|
2558
|
+
fs16.writeFileSync(settingsPath, JSON.stringify(existing, null, 2) + "\n", "utf-8");
|
|
2559
|
+
if (hooksFixed) updated.push(".claude/settings.json (hooks format: matcher+command \u2192 matcher+hooks array)");
|
|
2560
|
+
if (denyFixed) updated.push(".claude/settings.json (removed invalid deny rules)");
|
|
2516
2561
|
}
|
|
2517
2562
|
} catch {
|
|
2518
|
-
|
|
2519
|
-
updated.push(".claude/settings.json (replaced \u2014 was corrupted)");
|
|
2563
|
+
updated.push(".claude/settings.json (could not parse \u2014 please fix manually)");
|
|
2520
2564
|
}
|
|
2521
2565
|
}
|
|
2522
2566
|
const soulPath = path16.join(targetDir, "SOUL.md");
|
|
@@ -2577,7 +2621,7 @@ async function upgradeCommand() {
|
|
|
2577
2621
|
console.log("");
|
|
2578
2622
|
}
|
|
2579
2623
|
if (created.length > 0) {
|
|
2580
|
-
console.log(chalk14.white.bold(" Created (new in
|
|
2624
|
+
console.log(chalk14.white.bold(" Created (new in latest):"));
|
|
2581
2625
|
for (const c of created) console.log(chalk14.cyan(` ${c}`));
|
|
2582
2626
|
console.log("");
|
|
2583
2627
|
}
|
|
@@ -2593,7 +2637,7 @@ async function upgradeCommand() {
|
|
|
2593
2637
|
var program = new Command();
|
|
2594
2638
|
program.name("fishi").description(
|
|
2595
2639
|
chalk15.cyan("\u{1F41F} FISHI") + " \u2014 AI-Powered Software Delivery Pipeline\n Autonomous AI development with human governance"
|
|
2596
|
-
).version("0.14.
|
|
2640
|
+
).version("0.14.5");
|
|
2597
2641
|
program.command("init").description("Initialize FISHI in the current directory").argument("[description]", "Project description (skip wizard with zero-config)").option("-l, --language <lang>", "Primary language (e.g., typescript, python)").option("-f, --framework <framework>", "Framework (e.g., nextjs, express, django)").option(
|
|
2598
2642
|
"-c, --cost-mode <mode>",
|
|
2599
2643
|
"Cost mode: performance | balanced | economy",
|