@qlucent/fishi 0.14.5 → 0.14.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.
Files changed (2) hide show
  1. package/dist/index.js +105 -3
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1017,9 +1017,102 @@ async function initCommand(description, options) {
1017
1017
  }]);
1018
1018
  sandboxMode = useSandbox ? "docker" : "process";
1019
1019
  } else {
1020
- console.log(chalk.yellow(" Docker not found. Using process-level sandbox (limited isolation)."));
1021
- console.log(chalk.gray(" Install Docker for full agent isolation: https://docs.docker.com/get-docker/"));
1020
+ console.log(chalk.yellow(" Docker not found."));
1021
+ console.log(chalk.gray(" Docker provides full agent isolation (recommended for security)."));
1022
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 automatically (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 { execSync: execSyncInstall } = await import("child_process");
1035
+ const platform = process.platform;
1036
+ let installCmd = "";
1037
+ let platformName = "";
1038
+ if (platform === "win32") {
1039
+ installCmd = "winget install Docker.DockerDesktop --accept-package-agreements --accept-source-agreements";
1040
+ platformName = "Windows (winget)";
1041
+ } else if (platform === "darwin") {
1042
+ installCmd = "brew install --cask docker";
1043
+ platformName = "macOS (Homebrew)";
1044
+ } else {
1045
+ try {
1046
+ execSyncInstall("which apt-get", { stdio: "ignore" });
1047
+ installCmd = "sudo apt-get update && sudo apt-get install -y docker.io docker-compose-v2";
1048
+ platformName = "Linux (apt)";
1049
+ } catch {
1050
+ try {
1051
+ execSyncInstall("which dnf", { stdio: "ignore" });
1052
+ installCmd = "sudo dnf install -y docker docker-compose";
1053
+ platformName = "Linux (dnf)";
1054
+ } catch {
1055
+ try {
1056
+ execSyncInstall("which yum", { stdio: "ignore" });
1057
+ installCmd = "sudo yum install -y docker docker-compose";
1058
+ platformName = "Linux (yum)";
1059
+ } catch {
1060
+ console.log(chalk.red(" Could not detect package manager. Install Docker manually:"));
1061
+ console.log(chalk.gray(" https://docs.docker.com/get-docker/"));
1062
+ console.log(chalk.gray(" Then run `fishi init` again."));
1063
+ console.log("");
1064
+ return;
1065
+ }
1066
+ }
1067
+ }
1068
+ }
1069
+ console.log("");
1070
+ console.log(chalk.cyan(` Detected: ${platformName}`));
1071
+ console.log(chalk.gray(` Running: ${installCmd}`));
1072
+ console.log("");
1073
+ const installSpinner = ora("Installing Docker...").start();
1074
+ try {
1075
+ execSyncInstall(installCmd, { stdio: "inherit", timeout: 3e5 });
1076
+ installSpinner.succeed("Docker installed");
1077
+ console.log("");
1078
+ if (platform === "linux") {
1079
+ try {
1080
+ execSyncInstall("sudo systemctl start docker", { stdio: "ignore" });
1081
+ execSyncInstall("sudo systemctl enable docker", { stdio: "ignore" });
1082
+ execSyncInstall(`sudo usermod -aG docker ${process.env.USER || "root"}`, { stdio: "ignore" });
1083
+ } catch {
1084
+ }
1085
+ }
1086
+ const readySpinner = ora("Waiting for Docker to start...").start();
1087
+ let dockerReady = false;
1088
+ for (let i = 0; i < 30; i++) {
1089
+ try {
1090
+ execSyncInstall("docker info", { stdio: "ignore", timeout: 5e3 });
1091
+ dockerReady = true;
1092
+ break;
1093
+ } catch {
1094
+ await new Promise((resolve) => setTimeout(resolve, 2e3));
1095
+ }
1096
+ }
1097
+ if (dockerReady) {
1098
+ readySpinner.succeed("Docker is ready");
1099
+ sandboxMode = "docker";
1100
+ } else {
1101
+ readySpinner.warn("Docker installed but not running yet");
1102
+ console.log(chalk.gray(" Start Docker Desktop manually, then run `fishi upgrade` to switch to Docker mode."));
1103
+ console.log(chalk.gray(" Continuing with process-level sandbox for now."));
1104
+ }
1105
+ console.log("");
1106
+ } catch (err) {
1107
+ installSpinner.fail("Docker installation failed");
1108
+ console.log(chalk.gray(" Install manually: https://docs.docker.com/get-docker/"));
1109
+ console.log(chalk.gray(" Continuing with process-level sandbox."));
1110
+ console.log("");
1111
+ }
1112
+ } else {
1113
+ console.log(chalk.gray(" Continuing with process-level sandbox (limited isolation)."));
1114
+ console.log("");
1115
+ }
1023
1116
  }
1024
1117
  }
1025
1118
  let brownfieldAnalysis = null;
@@ -2499,8 +2592,17 @@ function fixDenyRules(settings) {
2499
2592
  settings.permissions.deny = settings.permissions.deny.filter((rule) => {
2500
2593
  if (rule.includes(":(){ :|:& };:")) return false;
2501
2594
  if (/^Bash\(\s*\)$/.test(rule)) return false;
2595
+ if (rule === "Bash(npm *)" || rule === "Bash(yarn *)") return false;
2502
2596
  return true;
2503
2597
  });
2598
+ if (settings.permissions?.allow) {
2599
+ if (!settings.permissions.allow.includes("Bash(npm *)")) {
2600
+ settings.permissions.allow.push("Bash(npm *)");
2601
+ }
2602
+ if (!settings.permissions.allow.includes("Bash(yarn *)")) {
2603
+ settings.permissions.allow.push("Bash(yarn *)");
2604
+ }
2605
+ }
2504
2606
  return settings.permissions.deny.length !== original;
2505
2607
  }
2506
2608
  async function upgradeCommand() {
@@ -2608,7 +2710,7 @@ async function upgradeCommand() {
2608
2710
  var program = new Command();
2609
2711
  program.name("fishi").description(
2610
2712
  chalk15.cyan("\u{1F41F} FISHI") + " \u2014 AI-Powered Software Delivery Pipeline\n Autonomous AI development with human governance"
2611
- ).version("0.14.4");
2713
+ ).version("0.14.7");
2612
2714
  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(
2613
2715
  "-c, --cost-mode <mode>",
2614
2716
  "Cost mode: performance | balanced | economy",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qlucent/fishi",
3
- "version": "0.14.5",
3
+ "version": "0.14.8",
4
4
  "description": "FISHI — Your AI Dev Team That Actually Ships. Autonomous agent framework for Claude Code.",
5
5
  "license": "MIT",
6
6
  "type": "module",