@qlucent/fishi 0.6.0 → 0.7.0
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 +77 -4
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
-
import
|
|
5
|
+
import chalk9 from "chalk";
|
|
6
6
|
|
|
7
7
|
// src/commands/init.ts
|
|
8
8
|
import chalk from "chalk";
|
|
@@ -10,7 +10,7 @@ import ora from "ora";
|
|
|
10
10
|
import inquirer from "inquirer";
|
|
11
11
|
import path3 from "path";
|
|
12
12
|
import fs3 from "fs";
|
|
13
|
-
import { detectConflicts, createBackup } from "@qlucent/fishi-core";
|
|
13
|
+
import { detectConflicts, createBackup, detectDocker } from "@qlucent/fishi-core";
|
|
14
14
|
|
|
15
15
|
// src/analyzers/detector.ts
|
|
16
16
|
import fs from "fs";
|
|
@@ -1005,6 +1005,23 @@ async function initCommand(description, options) {
|
|
|
1005
1005
|
} else {
|
|
1006
1006
|
initOptions = await runWizard(options);
|
|
1007
1007
|
}
|
|
1008
|
+
const dockerAvailable = detectDocker();
|
|
1009
|
+
let sandboxMode = "process";
|
|
1010
|
+
if (options.interactive !== false) {
|
|
1011
|
+
if (dockerAvailable) {
|
|
1012
|
+
const { useSandbox } = await inquirer.prompt([{
|
|
1013
|
+
type: "confirm",
|
|
1014
|
+
name: "useSandbox",
|
|
1015
|
+
message: "Docker detected. Use Docker sandbox for agent isolation? (Recommended)",
|
|
1016
|
+
default: true
|
|
1017
|
+
}]);
|
|
1018
|
+
sandboxMode = useSandbox ? "docker" : "process";
|
|
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/"));
|
|
1022
|
+
console.log("");
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1008
1025
|
let brownfieldAnalysis = null;
|
|
1009
1026
|
if (detection.type === "brownfield" || detection.type === "hybrid") {
|
|
1010
1027
|
console.log("");
|
|
@@ -1148,6 +1165,21 @@ async function initCommand(description, options) {
|
|
|
1148
1165
|
const report = generateBrownfieldReport(brownfieldAnalysis);
|
|
1149
1166
|
fs3.writeFileSync(reportPath, report, "utf-8");
|
|
1150
1167
|
}
|
|
1168
|
+
const sandboxYaml = `
|
|
1169
|
+
sandbox:
|
|
1170
|
+
mode: ${sandboxMode}
|
|
1171
|
+
docker_available: ${dockerAvailable}
|
|
1172
|
+
`;
|
|
1173
|
+
const fishiYamlPath = path3.join(targetDir, ".fishi", "fishi.yaml");
|
|
1174
|
+
if (fs3.existsSync(fishiYamlPath)) {
|
|
1175
|
+
fs3.appendFileSync(fishiYamlPath, sandboxYaml, "utf-8");
|
|
1176
|
+
}
|
|
1177
|
+
const { getSandboxPolicyTemplate, getDockerfileTemplate } = await import("@qlucent/fishi-core");
|
|
1178
|
+
fs3.writeFileSync(path3.join(targetDir, ".fishi", "sandbox-policy.yaml"), getSandboxPolicyTemplate(), "utf-8");
|
|
1179
|
+
if (sandboxMode === "docker") {
|
|
1180
|
+
fs3.mkdirSync(path3.join(targetDir, ".fishi", "docker"), { recursive: true });
|
|
1181
|
+
fs3.writeFileSync(path3.join(targetDir, ".fishi", "docker", "Dockerfile"), getDockerfileTemplate(), "utf-8");
|
|
1182
|
+
}
|
|
1151
1183
|
scaffoldSpinner.succeed("FISHI framework scaffolded successfully!");
|
|
1152
1184
|
console.log("");
|
|
1153
1185
|
console.log(chalk.bold(" Created:"));
|
|
@@ -1158,6 +1190,7 @@ async function initCommand(description, options) {
|
|
|
1158
1190
|
console.log(chalk.gray(` \u{1F4C4} .claude/CLAUDE.md \u2014 Project instructions`));
|
|
1159
1191
|
console.log(chalk.gray(` \u{1F4C4} .claude/settings.json \u2014 Hooks & permissions`));
|
|
1160
1192
|
console.log(chalk.gray(` \u{1F4C4} .mcp.json \u2014 MCP server config`));
|
|
1193
|
+
console.log(chalk.gray(` \u{1F512} Sandbox: ${sandboxMode} mode${sandboxMode === "docker" ? " (full isolation)" : " (limited isolation)"}`));
|
|
1161
1194
|
if (brownfieldAnalysis) {
|
|
1162
1195
|
console.log(chalk.gray(` \u{1F4C4} .fishi/memory/brownfield-analysis.md \u2014 Codebase analysis report`));
|
|
1163
1196
|
console.log("");
|
|
@@ -1898,11 +1931,50 @@ async function dashboardCommand(options) {
|
|
|
1898
1931
|
});
|
|
1899
1932
|
}
|
|
1900
1933
|
|
|
1934
|
+
// src/commands/sandbox.ts
|
|
1935
|
+
import chalk8 from "chalk";
|
|
1936
|
+
import fs10 from "fs";
|
|
1937
|
+
import path10 from "path";
|
|
1938
|
+
import { detectDocker as detectDocker2, readSandboxConfig, readSandboxPolicy } from "@qlucent/fishi-core";
|
|
1939
|
+
async function sandboxCommand(action) {
|
|
1940
|
+
const targetDir = process.cwd();
|
|
1941
|
+
if (!fs10.existsSync(path10.join(targetDir, ".fishi"))) {
|
|
1942
|
+
console.log(chalk8.yellow(" No FISHI project found. Run `fishi init` first."));
|
|
1943
|
+
return;
|
|
1944
|
+
}
|
|
1945
|
+
if (action === "status") {
|
|
1946
|
+
const config = readSandboxConfig(targetDir);
|
|
1947
|
+
const dockerNow = detectDocker2();
|
|
1948
|
+
console.log("");
|
|
1949
|
+
console.log(chalk8.cyan.bold(" FISHI Sandbox Status"));
|
|
1950
|
+
console.log("");
|
|
1951
|
+
console.log(chalk8.white(" Mode: ") + (config.mode === "docker" ? chalk8.green("Docker") : chalk8.yellow("Process")));
|
|
1952
|
+
console.log(chalk8.white(" Docker available: ") + (dockerNow ? chalk8.green("yes") : chalk8.red("no")));
|
|
1953
|
+
if (config.mode === "docker" && !dockerNow) {
|
|
1954
|
+
console.log(chalk8.red(" Warning: Docker mode configured but Docker not available!"));
|
|
1955
|
+
}
|
|
1956
|
+
console.log("");
|
|
1957
|
+
const policy = readSandboxPolicy(targetDir);
|
|
1958
|
+
console.log(chalk8.white.bold(" Policy"));
|
|
1959
|
+
console.log(chalk8.gray(` Timeout: ${policy.timeout}s`));
|
|
1960
|
+
console.log(chalk8.gray(` Memory limit: ${policy.memory}`));
|
|
1961
|
+
console.log(chalk8.gray(` CPU limit: ${policy.cpus}`));
|
|
1962
|
+
console.log(chalk8.gray(` Network allow: ${policy.networkAllow.join(", ")}`));
|
|
1963
|
+
console.log(chalk8.gray(` Env passthrough: ${policy.envPassthrough.length > 0 ? policy.envPassthrough.join(", ") : "(none)"}`));
|
|
1964
|
+
console.log("");
|
|
1965
|
+
} else if (action === "policy") {
|
|
1966
|
+
const policy = readSandboxPolicy(targetDir);
|
|
1967
|
+
console.log(JSON.stringify(policy, null, 2));
|
|
1968
|
+
} else {
|
|
1969
|
+
console.log(chalk8.yellow(` Unknown action: ${action}. Use: status, policy`));
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
|
|
1901
1973
|
// src/index.ts
|
|
1902
1974
|
var program = new Command();
|
|
1903
1975
|
program.name("fishi").description(
|
|
1904
|
-
|
|
1905
|
-
).version("0.
|
|
1976
|
+
chalk9.cyan("\u{1F41F} FISHI") + " \u2014 Your AI Dev Team That Actually Ships\n Autonomous agent framework for Claude Code"
|
|
1977
|
+
).version("0.7.0");
|
|
1906
1978
|
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(
|
|
1907
1979
|
"-c, --cost-mode <mode>",
|
|
1908
1980
|
"Cost mode: performance | balanced | economy",
|
|
@@ -1914,4 +1986,5 @@ program.command("reset").description("Rollback to a previous checkpoint").argume
|
|
|
1914
1986
|
program.command("validate").description("Validate scaffold integrity \u2014 checks files, frontmatter, cross-references, pipeline, and permissions").action(validateCommand);
|
|
1915
1987
|
program.command("monitor").description("Agent observability \u2014 TUI dashboard showing agent activity, tokens, gates").option("-w, --watch", "Watch mode \u2014 auto-refresh on changes").action(monitorCommand);
|
|
1916
1988
|
program.command("dashboard").description("Agent observability \u2014 web dashboard at http://localhost:4269").option("-p, --port <port>", "Port number", "4269").action(dashboardCommand);
|
|
1989
|
+
program.command("sandbox").description("Sandbox status and policy management").argument("<action>", "Action: status | policy").action(sandboxCommand);
|
|
1917
1990
|
program.parse();
|