@fenglimg/fabric-cli 1.3.1 → 1.4.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/{bootstrap-3PUKUYTY.js → bootstrap-B6RCVJZJ.js} +2 -2
- package/dist/{chunk-VOQKQ6W2.js → chunk-BEKSXO5N.js} +10 -2
- package/dist/{chunk-XFSQM3LJ.js → chunk-BVTMVW5M.js} +1 -1
- package/dist/{chunk-TKTWHAKV.js → chunk-XQYY2U2C.js} +1 -1
- package/dist/{config-GINBGANU.js → config-EC5L2QNI.js} +2 -2
- package/dist/index.js +5 -5
- package/dist/{init-T3LGMGAO.js → init-QC2MLFHR.js} +770 -253
- package/dist/{update-AN3FYF2O.js → update-FY2WKWPB.js} +2 -2
- package/package.json +4 -3
- package/templates/codex-hooks/fabric-session-start.cjs +19 -0
- package/templates/codex-hooks/fabric-stop-reminder.cjs +18 -0
- package/templates/codex-skills/fabric-init/SKILL.md +27 -0
|
@@ -2,16 +2,16 @@
|
|
|
2
2
|
import {
|
|
3
3
|
buildFabricBootstrapGuide,
|
|
4
4
|
installBootstrap
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-XQYY2U2C.js";
|
|
6
6
|
import {
|
|
7
7
|
detectFramework
|
|
8
8
|
} from "./chunk-AZRKMFRY.js";
|
|
9
9
|
import {
|
|
10
10
|
installMcpClients
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-BVTMVW5M.js";
|
|
12
12
|
import {
|
|
13
13
|
detectClientSupports
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-BEKSXO5N.js";
|
|
15
15
|
import {
|
|
16
16
|
installHooks
|
|
17
17
|
} from "./chunk-YDZJRLHL.js";
|
|
@@ -34,6 +34,7 @@ import * as childProcess from "child_process";
|
|
|
34
34
|
import { chmodSync, copyFileSync, existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, renameSync, rmSync, statSync as statSync2, writeFileSync } from "fs";
|
|
35
35
|
import { dirname, isAbsolute as isAbsolute2, join as join2, parse, resolve as resolve2 } from "path";
|
|
36
36
|
import { fileURLToPath } from "url";
|
|
37
|
+
import { cancel, confirm, group, intro, isCancel, log, note, outro, select } from "@clack/prompts";
|
|
37
38
|
import { defineCommand } from "citty";
|
|
38
39
|
|
|
39
40
|
// src/scanner/forensic.ts
|
|
@@ -856,7 +857,7 @@ function readProjectName(target) {
|
|
|
856
857
|
return basename(target);
|
|
857
858
|
}
|
|
858
859
|
function getCliVersion() {
|
|
859
|
-
return true ? "1.
|
|
860
|
+
return true ? "1.4.0" : "unknown";
|
|
860
861
|
}
|
|
861
862
|
function sortRecord(record) {
|
|
862
863
|
return Object.fromEntries(Object.entries(record).sort(([left], [right]) => left.localeCompare(right)));
|
|
@@ -869,8 +870,14 @@ function toPosixPath(path) {
|
|
|
869
870
|
var CLAUDE_INIT_SKILL_TEMPLATE = "templates/claude-skills/agents-md-init/SKILL.md";
|
|
870
871
|
var CLAUDE_INIT_REMINDER_HOOK_TEMPLATE = "templates/claude-hooks/agents-md-init-reminder.cjs";
|
|
871
872
|
var CLAUDE_INIT_REMINDER_COMMAND = ".claude/hooks/agents-md-init-reminder.cjs";
|
|
873
|
+
var CODEX_INIT_SKILL_TEMPLATE = "templates/codex-skills/fabric-init/SKILL.md";
|
|
874
|
+
var CODEX_SESSION_START_HOOK_TEMPLATE = "templates/codex-hooks/fabric-session-start.cjs";
|
|
875
|
+
var CODEX_STOP_HOOK_TEMPLATE = "templates/codex-hooks/fabric-stop-reminder.cjs";
|
|
876
|
+
var CODEX_SESSION_START_COMMAND = ".codex/hooks/fabric-session-start.cjs";
|
|
877
|
+
var CODEX_STOP_COMMAND = ".codex/hooks/fabric-stop-reminder.cjs";
|
|
872
878
|
var LOCAL_FABRIC_SERVER_PATH = join2("node_modules", "@fenglimg", "fabric-server", "dist", "index.js");
|
|
873
879
|
var FABRIC_SERVER_PACKAGE = "@fenglimg/fabric-server";
|
|
880
|
+
var INIT_WIZARD_GROUP_CANCELLED = /* @__PURE__ */ Symbol("init-wizard-group-cancelled");
|
|
874
881
|
var initCommand = defineCommand({
|
|
875
882
|
meta: {
|
|
876
883
|
name: "init",
|
|
@@ -891,6 +898,21 @@ var initCommand = defineCommand({
|
|
|
891
898
|
description: t("cli.init.args.force.description"),
|
|
892
899
|
default: false
|
|
893
900
|
},
|
|
901
|
+
yes: {
|
|
902
|
+
type: "boolean",
|
|
903
|
+
description: t("cli.init.args.yes.description"),
|
|
904
|
+
default: false
|
|
905
|
+
},
|
|
906
|
+
plan: {
|
|
907
|
+
type: "boolean",
|
|
908
|
+
description: t("cli.init.args.plan.description"),
|
|
909
|
+
default: false
|
|
910
|
+
},
|
|
911
|
+
reapply: {
|
|
912
|
+
type: "boolean",
|
|
913
|
+
description: t("cli.init.args.reapply.description"),
|
|
914
|
+
default: false
|
|
915
|
+
},
|
|
894
916
|
bootstrap: {
|
|
895
917
|
type: "boolean",
|
|
896
918
|
default: true,
|
|
@@ -918,178 +940,727 @@ var initCommand = defineCommand({
|
|
|
918
940
|
}
|
|
919
941
|
},
|
|
920
942
|
async run({ args }) {
|
|
921
|
-
|
|
922
|
-
const resolution = resolveDevMode(args.target, process.cwd());
|
|
923
|
-
const target = normalizeTarget2(resolution.target);
|
|
924
|
-
const mcpInstallMode = resolveMcpInstallMode(args["mcp-install"]);
|
|
925
|
-
const options = {
|
|
926
|
-
force: args.force,
|
|
927
|
-
skipBootstrap: args.bootstrap === false ? true : args.skipBootstrap,
|
|
928
|
-
skipMcp: args.mcp === false ? true : args.skipMcp,
|
|
929
|
-
skipHooks: args.hooks === false ? true : args.skipHooks
|
|
930
|
-
};
|
|
931
|
-
logger(`init target source: ${resolution.source}`);
|
|
932
|
-
for (const step of resolution.chain) {
|
|
933
|
-
logger(step);
|
|
934
|
-
}
|
|
935
|
-
const supports = detectClientSupports(target);
|
|
936
|
-
const interactive = args.interactive !== false && isInteractiveInit();
|
|
937
|
-
if (options.force) {
|
|
938
|
-
writeStderr(t("cli.init.force.warning", { path: target }));
|
|
939
|
-
}
|
|
940
|
-
if (interactive) {
|
|
941
|
-
printInitPlanSummary(target, options, mcpInstallMode, supports);
|
|
942
|
-
}
|
|
943
|
-
const created = initFabric(target, options);
|
|
944
|
-
console.log(formatInitPathAction(created.bootstrapPath, created.bootstrapAction));
|
|
945
|
-
console.log(formatInitPathAction(created.metaPath, created.metaAction));
|
|
946
|
-
console.log(formatInitPathAction(created.humanLockPath, created.humanLockAction));
|
|
947
|
-
console.log(formatInitPathAction(created.forensicPath, created.forensicAction));
|
|
948
|
-
writeStderr(
|
|
949
|
-
formatOptionalInitPathAction(created.claudeSkillPath, created.claudeSkillAction)
|
|
950
|
-
);
|
|
951
|
-
writeStderr(
|
|
952
|
-
formatOptionalInitPathAction(created.claudeHookPath, created.claudeHookAction)
|
|
953
|
-
);
|
|
954
|
-
writeStderr(formatClaudeSettingsAction(created.claudeSettingsPath, created.claudeSettingsAction));
|
|
955
|
-
const stageResults = [];
|
|
956
|
-
if (options.skipBootstrap) {
|
|
957
|
-
stageResults.push({ name: "bootstrap", disposition: "skipped" });
|
|
958
|
-
} else {
|
|
959
|
-
console.log(formatInitStageHeader(t("cli.init.stages.bootstrap")));
|
|
960
|
-
try {
|
|
961
|
-
const result = await installBootstrap(target, { force: options.force });
|
|
962
|
-
if (result.details.length === 0) {
|
|
963
|
-
console.log(formatInitStageResult("bootstrap", "skipped", 0, 0, t("cli.bootstrap.install.no-targets")));
|
|
964
|
-
stageResults.push({ name: "bootstrap", disposition: "skipped" });
|
|
965
|
-
} else {
|
|
966
|
-
console.log(
|
|
967
|
-
formatInitStageResult("bootstrap", "completed", result.installed.length, result.skipped.length)
|
|
968
|
-
);
|
|
969
|
-
stageResults.push({ name: "bootstrap", disposition: "ran" });
|
|
970
|
-
}
|
|
971
|
-
} catch (error) {
|
|
972
|
-
writeStderr(formatInitStageFailure("bootstrap", error));
|
|
973
|
-
stageResults.push({ name: "bootstrap", disposition: "failed" });
|
|
974
|
-
}
|
|
975
|
-
}
|
|
976
|
-
if (options.skipMcp) {
|
|
977
|
-
stageResults.push({ name: "mcp", disposition: "skipped" });
|
|
978
|
-
} else {
|
|
979
|
-
console.log(formatInitStageHeader(t("cli.init.stages.mcp")));
|
|
980
|
-
try {
|
|
981
|
-
let localServerPath;
|
|
982
|
-
if (mcpInstallMode === "local") {
|
|
983
|
-
const manager = detectPackageManager(target);
|
|
984
|
-
writeStderr(t("cli.init.mcp.install.local"));
|
|
985
|
-
writeStderr(t("cli.init.mcp.local.installing", { manager }));
|
|
986
|
-
installLocalFabricServer(target, manager);
|
|
987
|
-
writeStderr(t("cli.init.mcp.local.installed"));
|
|
988
|
-
localServerPath = LOCAL_FABRIC_SERVER_PATH;
|
|
989
|
-
} else {
|
|
990
|
-
writeStderr(t("cli.init.mcp.install.global"));
|
|
991
|
-
}
|
|
992
|
-
const result = await installMcpClients(target, {
|
|
993
|
-
force: options.force,
|
|
994
|
-
localServerPath
|
|
995
|
-
});
|
|
996
|
-
if (result.details.length === 0) {
|
|
997
|
-
console.log(formatInitStageResult("mcp", "skipped", 0, 0, t("cli.config.install.no-configs")));
|
|
998
|
-
stageResults.push({ name: "mcp", disposition: "skipped" });
|
|
999
|
-
} else {
|
|
1000
|
-
console.log(formatInitStageResult("mcp", "completed", result.installed.length, result.skipped.length));
|
|
1001
|
-
stageResults.push({ name: "mcp", disposition: "ran" });
|
|
1002
|
-
}
|
|
1003
|
-
} catch (error) {
|
|
1004
|
-
writeStderr(formatInitStageFailure("mcp", error));
|
|
1005
|
-
stageResults.push({ name: "mcp", disposition: "failed" });
|
|
1006
|
-
}
|
|
1007
|
-
}
|
|
1008
|
-
if (options.skipHooks) {
|
|
1009
|
-
stageResults.push({ name: "hooks", disposition: "skipped" });
|
|
1010
|
-
} else {
|
|
1011
|
-
console.log(formatInitStageHeader(t("cli.init.stages.hooks")));
|
|
1012
|
-
try {
|
|
1013
|
-
const result = await installHooks(target, { force: options.force });
|
|
1014
|
-
console.log(formatInitStageResult("hooks", "completed", result.installed.length, result.skipped.length));
|
|
1015
|
-
stageResults.push({ name: "hooks", disposition: "ran" });
|
|
1016
|
-
} catch (error) {
|
|
1017
|
-
writeStderr(formatInitStageFailure("hooks", error));
|
|
1018
|
-
stageResults.push({ name: "hooks", disposition: "failed" });
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
if (shouldPrintHooksNextStep(options, stageResults)) {
|
|
1022
|
-
console.log(
|
|
1023
|
-
t("cli.init.next-step", {
|
|
1024
|
-
label: nextLabel(),
|
|
1025
|
-
message: paint.muted(t("cli.init.next-step.message"))
|
|
1026
|
-
})
|
|
1027
|
-
);
|
|
1028
|
-
}
|
|
1029
|
-
console.log(
|
|
1030
|
-
t("cli.init.reason-message", {
|
|
1031
|
-
label: reasonLabel(),
|
|
1032
|
-
message: paint.muted(formatInitReasonMessage(supports))
|
|
1033
|
-
})
|
|
1034
|
-
);
|
|
1035
|
-
printInitStageSummary(stageResults);
|
|
1036
|
-
printInitCapabilitySummary(supports, stageResults, options);
|
|
943
|
+
await runInitCommand(args);
|
|
1037
944
|
}
|
|
1038
945
|
});
|
|
1039
946
|
var init_default = initCommand;
|
|
1040
|
-
function
|
|
947
|
+
async function runInitCommand(args) {
|
|
948
|
+
const logger = createDebugLogger(args.debug);
|
|
949
|
+
const resolution = resolveDevMode(args.target, process.cwd());
|
|
950
|
+
const intent = resolveInitCliIntent(args, resolution.target);
|
|
951
|
+
logger(`init target source: ${resolution.source}`);
|
|
952
|
+
for (const step of resolution.chain) {
|
|
953
|
+
logger(step);
|
|
954
|
+
}
|
|
955
|
+
if (intent.options.planOnly) {
|
|
956
|
+
writeStderr(t("cli.init.compat.plan"));
|
|
957
|
+
}
|
|
958
|
+
if (args.interactive === false) {
|
|
959
|
+
writeStderr(t("cli.init.compat.interactive"));
|
|
960
|
+
}
|
|
961
|
+
if (args.bootstrap === false || args.mcp === false || args.hooks === false) {
|
|
962
|
+
writeStderr(t("cli.init.compat.legacy-stage-flags"));
|
|
963
|
+
}
|
|
964
|
+
const supports = detectClientSupports(intent.target);
|
|
965
|
+
const basePlan = buildInitExecutionPlan({
|
|
966
|
+
target: intent.target,
|
|
967
|
+
options: intent.options,
|
|
968
|
+
mcpInstallMode: intent.mcpInstallMode,
|
|
969
|
+
interactive: intent.interactiveSummary && !intent.wizardEnabled,
|
|
970
|
+
supports
|
|
971
|
+
});
|
|
972
|
+
const plan = intent.wizardEnabled ? await resolveInitExecutionPlanWithWizard(basePlan, args, createDefaultInitWizardAdapter()) : basePlan;
|
|
973
|
+
if (plan === null) {
|
|
974
|
+
writeStderr(t("cli.init.wizard.cancelled"));
|
|
975
|
+
throw new Error(t("cli.init.wizard.cancelled"));
|
|
976
|
+
}
|
|
977
|
+
return executeInitExecutionPlan(plan);
|
|
978
|
+
}
|
|
979
|
+
function resolveInitCliIntent(args, targetInput) {
|
|
980
|
+
const target = normalizeTarget2(targetInput);
|
|
981
|
+
const mcpInstallMode = resolveMcpInstallMode(args["mcp-install"]);
|
|
982
|
+
const terminalInteractive = isInteractiveInit();
|
|
983
|
+
const planOnly = args.plan === true;
|
|
984
|
+
const reapply = args.reapply === true;
|
|
985
|
+
const options = {
|
|
986
|
+
force: reapply ? true : args.force,
|
|
987
|
+
skipBootstrap: args.bootstrap === false ? true : args.skipBootstrap,
|
|
988
|
+
skipMcp: args.mcp === false ? true : args.skipMcp,
|
|
989
|
+
skipHooks: args.hooks === false ? true : args.skipHooks,
|
|
990
|
+
planOnly,
|
|
991
|
+
reapply
|
|
992
|
+
};
|
|
993
|
+
return {
|
|
994
|
+
target,
|
|
995
|
+
options,
|
|
996
|
+
mcpInstallMode,
|
|
997
|
+
interactiveSummary: args.interactive !== false && terminalInteractive,
|
|
998
|
+
wizardEnabled: shouldUseInitWizard(args, terminalInteractive) && !planOnly
|
|
999
|
+
};
|
|
1000
|
+
}
|
|
1001
|
+
function buildInitExecutionPlan(input) {
|
|
1002
|
+
const options = input.options ?? {};
|
|
1003
|
+
const scaffold = buildInitFabricPlan(input.target, options);
|
|
1004
|
+
const supports = input.supports ?? detectClientSupports(input.target);
|
|
1005
|
+
const mcpInstallMode = input.mcpInstallMode ?? "global";
|
|
1006
|
+
const stages = [
|
|
1007
|
+
{ name: "bootstrap", skipped: Boolean(options.skipBootstrap) },
|
|
1008
|
+
{
|
|
1009
|
+
name: "mcp",
|
|
1010
|
+
skipped: Boolean(options.skipMcp),
|
|
1011
|
+
installMode: mcpInstallMode,
|
|
1012
|
+
localServerPath: mcpInstallMode === "local" ? LOCAL_FABRIC_SERVER_PATH : void 0,
|
|
1013
|
+
packageManager: mcpInstallMode === "local" ? detectPackageManager(input.target) : void 0
|
|
1014
|
+
},
|
|
1015
|
+
{ name: "hooks", skipped: Boolean(options.skipHooks) }
|
|
1016
|
+
];
|
|
1017
|
+
return {
|
|
1018
|
+
target: input.target,
|
|
1019
|
+
options,
|
|
1020
|
+
mcpInstallMode,
|
|
1021
|
+
interactive: input.interactive ?? false,
|
|
1022
|
+
supports,
|
|
1023
|
+
scaffold,
|
|
1024
|
+
stages,
|
|
1025
|
+
steps: [
|
|
1026
|
+
{ name: "preflight" },
|
|
1027
|
+
{ name: "scaffold" },
|
|
1028
|
+
...stages.map((stage) => ({ name: stage.name, skipped: stage.skipped })),
|
|
1029
|
+
{ name: "post-setup" }
|
|
1030
|
+
]
|
|
1031
|
+
};
|
|
1032
|
+
}
|
|
1033
|
+
async function executeInitExecutionPlan(plan) {
|
|
1034
|
+
if (plan.options.force) {
|
|
1035
|
+
writeStderr(t("cli.init.force.warning", { path: plan.target }));
|
|
1036
|
+
}
|
|
1037
|
+
if (plan.options.reapply && !plan.options.planOnly && !plan.interactive) {
|
|
1038
|
+
writeStderr(formatInitModeBanner(plan.options));
|
|
1039
|
+
}
|
|
1040
|
+
if (plan.interactive) {
|
|
1041
|
+
printInitPlanSummary(plan.target, plan.options, plan.mcpInstallMode, plan.supports);
|
|
1042
|
+
}
|
|
1043
|
+
if (plan.options.planOnly) {
|
|
1044
|
+
printInitPlanPreview(plan);
|
|
1045
|
+
return {
|
|
1046
|
+
plan,
|
|
1047
|
+
created: buildPlanOnlyScaffoldResult(plan.scaffold),
|
|
1048
|
+
stageResults: plan.stages.map((stage) => ({ name: stage.name, disposition: "skipped" })),
|
|
1049
|
+
finalSupports: plan.supports
|
|
1050
|
+
};
|
|
1051
|
+
}
|
|
1052
|
+
let created = null;
|
|
1053
|
+
const stageResults = [];
|
|
1054
|
+
let finalSupports = plan.supports;
|
|
1055
|
+
for (const step of plan.steps) {
|
|
1056
|
+
switch (step.name) {
|
|
1057
|
+
case "preflight":
|
|
1058
|
+
break;
|
|
1059
|
+
case "scaffold":
|
|
1060
|
+
created = executeInitFabricPlan(plan.scaffold);
|
|
1061
|
+
printInitScaffoldResult(created);
|
|
1062
|
+
break;
|
|
1063
|
+
case "bootstrap":
|
|
1064
|
+
case "mcp":
|
|
1065
|
+
case "hooks":
|
|
1066
|
+
stageResults.push(await executeInitStagePlan(plan, step.name));
|
|
1067
|
+
break;
|
|
1068
|
+
case "post-setup":
|
|
1069
|
+
finalSupports = detectClientSupports(plan.target);
|
|
1070
|
+
printInitPostSetup(plan, stageResults, finalSupports);
|
|
1071
|
+
break;
|
|
1072
|
+
default:
|
|
1073
|
+
exhaustiveInitExecutionStep(step);
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
return {
|
|
1077
|
+
plan,
|
|
1078
|
+
created: created ?? unreachableInitScaffold(),
|
|
1079
|
+
stageResults,
|
|
1080
|
+
finalSupports
|
|
1081
|
+
};
|
|
1082
|
+
}
|
|
1083
|
+
function buildInitFabricPlan(target, options) {
|
|
1041
1084
|
assertExistingDirectory2(target);
|
|
1042
1085
|
const fabricDir = join2(target, ".fabric");
|
|
1043
1086
|
const bootstrapPath = join2(fabricDir, "bootstrap", "README.md");
|
|
1044
1087
|
const forensicPath = join2(fabricDir, "forensic.json");
|
|
1045
1088
|
const claudeSkillPath = join2(target, ".claude", "skills", "agents-md-init", "SKILL.md");
|
|
1089
|
+
const codexSkillPath = join2(target, ".agents", "skills", "fabric-init", "SKILL.md");
|
|
1090
|
+
const codexSessionStartHookPath = join2(target, ".codex", "hooks", "fabric-session-start.cjs");
|
|
1091
|
+
const codexStopHookPath = join2(target, ".codex", "hooks", "fabric-stop-reminder.cjs");
|
|
1092
|
+
const codexHooksConfigPath = join2(target, ".codex", "hooks.json");
|
|
1046
1093
|
const claudeHookPath = join2(target, ".claude", "hooks", "agents-md-init-reminder.cjs");
|
|
1047
1094
|
const claudeSettingsPath = join2(target, ".claude", "settings.json");
|
|
1048
1095
|
const metaPath = join2(fabricDir, "agents.meta.json");
|
|
1049
1096
|
const humanLockPath = join2(fabricDir, "human-lock.json");
|
|
1050
|
-
|
|
1051
|
-
const bootstrapAction =
|
|
1052
|
-
const metaAction =
|
|
1053
|
-
const humanLockAction =
|
|
1054
|
-
const forensicAction =
|
|
1097
|
+
const replaceFabricDir = shouldReplaceWritableDirectory(fabricDir, options);
|
|
1098
|
+
const bootstrapAction = planFreshPath(bootstrapPath, options);
|
|
1099
|
+
const metaAction = planFreshPath(metaPath, options);
|
|
1100
|
+
const humanLockAction = planFreshPath(humanLockPath, options);
|
|
1101
|
+
const forensicAction = planFreshPath(forensicPath, options);
|
|
1055
1102
|
const forensicReport = buildForensicReport(target);
|
|
1056
1103
|
const humanLockTemplate = readFileSync2(findTemplatePath("templates/fabric/human-lock.json"), "utf8");
|
|
1057
1104
|
const bootstrapContent = buildFabricBootstrapGuide(target);
|
|
1058
1105
|
const bootstrapHash = sha256(bootstrapContent);
|
|
1059
1106
|
const meta = createInitialMeta(bootstrapHash);
|
|
1060
|
-
mkdirSync(fabricDir, { recursive: true });
|
|
1061
|
-
mkdirSync(dirname(bootstrapPath), { recursive: true });
|
|
1062
|
-
writeNewFile(bootstrapPath, bootstrapContent, options);
|
|
1063
|
-
writeNewFile(metaPath, `${JSON.stringify(meta, null, 2)}
|
|
1064
|
-
`, options);
|
|
1065
|
-
writeNewFile(humanLockPath, humanLockTemplate.endsWith("\n") ? humanLockTemplate : `${humanLockTemplate}
|
|
1066
|
-
`, options);
|
|
1067
|
-
writeNewFile(forensicPath, `${JSON.stringify(forensicReport, null, 2)}
|
|
1068
|
-
`, options);
|
|
1069
|
-
const claudeSkillAction = copyTemplateIfMissing(findTemplatePath(CLAUDE_INIT_SKILL_TEMPLATE), claudeSkillPath, options);
|
|
1070
|
-
const claudeHookAction = copyExecutableTemplateIfMissing(
|
|
1071
|
-
findTemplatePath(CLAUDE_INIT_REMINDER_HOOK_TEMPLATE),
|
|
1072
|
-
claudeHookPath,
|
|
1073
|
-
options
|
|
1074
|
-
);
|
|
1075
|
-
const claudeSettingsAction = mergeClaudeStopHook(claudeSettingsPath, options);
|
|
1076
1107
|
return {
|
|
1108
|
+
target,
|
|
1109
|
+
options,
|
|
1110
|
+
fabricDir,
|
|
1111
|
+
replaceFabricDir,
|
|
1077
1112
|
bootstrapPath,
|
|
1078
1113
|
bootstrapAction,
|
|
1114
|
+
bootstrapContent,
|
|
1079
1115
|
metaPath,
|
|
1080
1116
|
metaAction,
|
|
1117
|
+
meta,
|
|
1081
1118
|
humanLockPath,
|
|
1082
1119
|
humanLockAction,
|
|
1120
|
+
humanLockContent: humanLockTemplate.endsWith("\n") ? humanLockTemplate : `${humanLockTemplate}
|
|
1121
|
+
`,
|
|
1083
1122
|
forensicPath,
|
|
1084
1123
|
forensicAction,
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1124
|
+
forensicReport,
|
|
1125
|
+
claudeSkill: buildOptionalTemplateWritePlan(claudeSkillPath, findTemplatePath(CLAUDE_INIT_SKILL_TEMPLATE), options),
|
|
1126
|
+
codexSkill: buildOptionalTemplateWritePlan(codexSkillPath, findTemplatePath(CODEX_INIT_SKILL_TEMPLATE), options),
|
|
1127
|
+
codexSessionStartHook: buildOptionalTemplateWritePlan(
|
|
1128
|
+
codexSessionStartHookPath,
|
|
1129
|
+
findTemplatePath(CODEX_SESSION_START_HOOK_TEMPLATE),
|
|
1130
|
+
options,
|
|
1131
|
+
true
|
|
1132
|
+
),
|
|
1133
|
+
codexStopHook: buildOptionalTemplateWritePlan(
|
|
1134
|
+
codexStopHookPath,
|
|
1135
|
+
findTemplatePath(CODEX_STOP_HOOK_TEMPLATE),
|
|
1136
|
+
options,
|
|
1137
|
+
true
|
|
1138
|
+
),
|
|
1139
|
+
codexHooksConfig: buildCodexHooksConfigPlan(codexHooksConfigPath, options),
|
|
1140
|
+
claudeHook: buildOptionalTemplateWritePlan(
|
|
1141
|
+
claudeHookPath,
|
|
1142
|
+
findTemplatePath(CLAUDE_INIT_REMINDER_HOOK_TEMPLATE),
|
|
1143
|
+
options,
|
|
1144
|
+
true
|
|
1145
|
+
),
|
|
1146
|
+
claudeSettings: buildClaudeSettingsWritePlan(claudeSettingsPath, options)
|
|
1147
|
+
};
|
|
1148
|
+
}
|
|
1149
|
+
function executeInitFabricPlan(plan) {
|
|
1150
|
+
if (plan.replaceFabricDir) {
|
|
1151
|
+
rmSync(plan.fabricDir, { force: true });
|
|
1152
|
+
}
|
|
1153
|
+
mkdirSync(plan.fabricDir, { recursive: true });
|
|
1154
|
+
mkdirSync(dirname(plan.bootstrapPath), { recursive: true });
|
|
1155
|
+
preparePlannedPath(plan.bootstrapPath, plan.bootstrapAction);
|
|
1156
|
+
writeFileSync(plan.bootstrapPath, plan.bootstrapContent, "utf8");
|
|
1157
|
+
preparePlannedPath(plan.metaPath, plan.metaAction);
|
|
1158
|
+
writeFileSync(plan.metaPath, `${JSON.stringify(plan.meta, null, 2)}
|
|
1159
|
+
`, "utf8");
|
|
1160
|
+
preparePlannedPath(plan.humanLockPath, plan.humanLockAction);
|
|
1161
|
+
writeFileSync(plan.humanLockPath, plan.humanLockContent, "utf8");
|
|
1162
|
+
preparePlannedPath(plan.forensicPath, plan.forensicAction);
|
|
1163
|
+
writeFileSync(plan.forensicPath, `${JSON.stringify(plan.forensicReport, null, 2)}
|
|
1164
|
+
`, "utf8");
|
|
1165
|
+
applyOptionalTemplateWritePlan(plan.claudeSkill);
|
|
1166
|
+
applyOptionalTemplateWritePlan(plan.codexSkill);
|
|
1167
|
+
applyOptionalTemplateWritePlan(plan.codexSessionStartHook);
|
|
1168
|
+
applyOptionalTemplateWritePlan(plan.codexStopHook);
|
|
1169
|
+
applyJsonWritePlan(plan.codexHooksConfig);
|
|
1170
|
+
applyOptionalTemplateWritePlan(plan.claudeHook);
|
|
1171
|
+
applyClaudeSettingsWritePlan(plan.claudeSettings);
|
|
1172
|
+
return {
|
|
1173
|
+
bootstrapPath: plan.bootstrapPath,
|
|
1174
|
+
bootstrapAction: plan.bootstrapAction,
|
|
1175
|
+
metaPath: plan.metaPath,
|
|
1176
|
+
metaAction: plan.metaAction,
|
|
1177
|
+
humanLockPath: plan.humanLockPath,
|
|
1178
|
+
humanLockAction: plan.humanLockAction,
|
|
1179
|
+
forensicPath: plan.forensicPath,
|
|
1180
|
+
forensicAction: plan.forensicAction,
|
|
1181
|
+
claudeSkillPath: plan.claudeSkill.path,
|
|
1182
|
+
claudeSkillAction: plan.claudeSkill.action,
|
|
1183
|
+
codexSkillPath: plan.codexSkill.path,
|
|
1184
|
+
codexSkillAction: plan.codexSkill.action,
|
|
1185
|
+
codexSessionStartHookPath: plan.codexSessionStartHook.path,
|
|
1186
|
+
codexSessionStartHookAction: plan.codexSessionStartHook.action,
|
|
1187
|
+
codexStopHookPath: plan.codexStopHook.path,
|
|
1188
|
+
codexStopHookAction: plan.codexStopHook.action,
|
|
1189
|
+
codexHooksConfigPath: plan.codexHooksConfig.path,
|
|
1190
|
+
codexHooksConfigAction: plan.codexHooksConfig.action,
|
|
1191
|
+
claudeHookPath: plan.claudeHook.path,
|
|
1192
|
+
claudeHookAction: plan.claudeHook.action,
|
|
1193
|
+
claudeSettingsPath: plan.claudeSettings.path,
|
|
1194
|
+
claudeSettingsAction: plan.claudeSettings.action
|
|
1195
|
+
};
|
|
1196
|
+
}
|
|
1197
|
+
function initFabric(target, options) {
|
|
1198
|
+
return executeInitFabricPlan(buildInitFabricPlan(target, options));
|
|
1199
|
+
}
|
|
1200
|
+
function shouldUseInitWizard(args, terminalInteractive = isInteractiveInit()) {
|
|
1201
|
+
return terminalInteractive && args.interactive !== false && args.yes !== true;
|
|
1202
|
+
}
|
|
1203
|
+
async function resolveInitExecutionPlanWithWizard(basePlan, args, wizardAdapter) {
|
|
1204
|
+
const selection = await wizardAdapter.run({
|
|
1205
|
+
target: basePlan.target,
|
|
1206
|
+
options: basePlan.options,
|
|
1207
|
+
supports: basePlan.supports,
|
|
1208
|
+
mcpInstallMode: basePlan.mcpInstallMode,
|
|
1209
|
+
lockedStages: collectLockedWizardStages(args)
|
|
1210
|
+
});
|
|
1211
|
+
if (selection === null) {
|
|
1212
|
+
return null;
|
|
1213
|
+
}
|
|
1214
|
+
return buildInitExecutionPlan({
|
|
1215
|
+
target: basePlan.target,
|
|
1216
|
+
options: {
|
|
1217
|
+
...basePlan.options,
|
|
1218
|
+
skipBootstrap: !selection.bootstrap,
|
|
1219
|
+
skipMcp: !selection.mcp,
|
|
1220
|
+
skipHooks: !selection.hooks
|
|
1221
|
+
},
|
|
1222
|
+
mcpInstallMode: selection.mcp ? selection.mcpInstallMode : basePlan.mcpInstallMode,
|
|
1223
|
+
interactive: false,
|
|
1224
|
+
supports: basePlan.supports
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1227
|
+
function unreachableInitScaffold() {
|
|
1228
|
+
throw new Error("Init scaffold step did not execute");
|
|
1229
|
+
}
|
|
1230
|
+
function exhaustiveInitExecutionStep(value) {
|
|
1231
|
+
throw new Error(`Unsupported init execution step: ${JSON.stringify(value)}`);
|
|
1232
|
+
}
|
|
1233
|
+
function exhaustiveInitStagePlan(value) {
|
|
1234
|
+
throw new Error(`Unsupported init stage plan: ${JSON.stringify(value)}`);
|
|
1235
|
+
}
|
|
1236
|
+
function printInitScaffoldResult(created) {
|
|
1237
|
+
console.log(formatInitPathAction(created.bootstrapPath, created.bootstrapAction));
|
|
1238
|
+
console.log(formatInitPathAction(created.metaPath, created.metaAction));
|
|
1239
|
+
console.log(formatInitPathAction(created.humanLockPath, created.humanLockAction));
|
|
1240
|
+
console.log(formatInitPathAction(created.forensicPath, created.forensicAction));
|
|
1241
|
+
writeStderr(formatOptionalInitPathAction(created.claudeSkillPath, created.claudeSkillAction));
|
|
1242
|
+
writeStderr(formatOptionalInitPathAction(created.codexSkillPath, created.codexSkillAction));
|
|
1243
|
+
writeStderr(
|
|
1244
|
+
formatOptionalInitPathAction(created.codexSessionStartHookPath, created.codexSessionStartHookAction)
|
|
1245
|
+
);
|
|
1246
|
+
writeStderr(
|
|
1247
|
+
formatOptionalInitPathAction(created.codexStopHookPath, created.codexStopHookAction)
|
|
1248
|
+
);
|
|
1249
|
+
writeStderr(formatCodexHooksAction(created.codexHooksConfigPath, created.codexHooksConfigAction));
|
|
1250
|
+
writeStderr(formatOptionalInitPathAction(created.claudeHookPath, created.claudeHookAction));
|
|
1251
|
+
writeStderr(formatClaudeSettingsAction(created.claudeSettingsPath, created.claudeSettingsAction));
|
|
1252
|
+
}
|
|
1253
|
+
function printInitPostSetup(plan, stageResults, finalSupports) {
|
|
1254
|
+
if (shouldPrintHooksNextStep(plan.options, stageResults)) {
|
|
1255
|
+
console.log(
|
|
1256
|
+
t("cli.init.next-step", {
|
|
1257
|
+
label: nextLabel(),
|
|
1258
|
+
message: paint.muted(t("cli.init.next-step.message"))
|
|
1259
|
+
})
|
|
1260
|
+
);
|
|
1261
|
+
}
|
|
1262
|
+
console.log(
|
|
1263
|
+
t("cli.init.reason-message", {
|
|
1264
|
+
label: reasonLabel(),
|
|
1265
|
+
message: paint.muted(formatInitReasonMessage(finalSupports))
|
|
1266
|
+
})
|
|
1267
|
+
);
|
|
1268
|
+
printInitStageSummary(stageResults);
|
|
1269
|
+
printInitCapabilitySummary(finalSupports, stageResults, plan.options);
|
|
1270
|
+
}
|
|
1271
|
+
function printInitPlanPreview(plan) {
|
|
1272
|
+
console.log(t("cli.init.plan.preview-title"));
|
|
1273
|
+
printInitPlanSummary(plan.target, plan.options, plan.mcpInstallMode, plan.supports);
|
|
1274
|
+
console.log(
|
|
1275
|
+
t("cli.init.plan.preview-result", {
|
|
1276
|
+
mode: plan.options.reapply ? t("cli.init.mode.reapply") : t("cli.init.mode.default"),
|
|
1277
|
+
bootstrap: yesNoLabel(!plan.options.skipBootstrap),
|
|
1278
|
+
mcp: yesNoLabel(!plan.options.skipMcp),
|
|
1279
|
+
hooks: yesNoLabel(!plan.options.skipHooks)
|
|
1280
|
+
})
|
|
1281
|
+
);
|
|
1282
|
+
}
|
|
1283
|
+
function buildPlanOnlyScaffoldResult(plan) {
|
|
1284
|
+
return {
|
|
1285
|
+
bootstrapPath: plan.bootstrapPath,
|
|
1286
|
+
bootstrapAction: plan.bootstrapAction,
|
|
1287
|
+
metaPath: plan.metaPath,
|
|
1288
|
+
metaAction: plan.metaAction,
|
|
1289
|
+
humanLockPath: plan.humanLockPath,
|
|
1290
|
+
humanLockAction: plan.humanLockAction,
|
|
1291
|
+
forensicPath: plan.forensicPath,
|
|
1292
|
+
forensicAction: plan.forensicAction,
|
|
1293
|
+
claudeSkillPath: plan.claudeSkill.path,
|
|
1294
|
+
claudeSkillAction: plan.claudeSkill.action,
|
|
1295
|
+
codexSkillPath: plan.codexSkill.path,
|
|
1296
|
+
codexSkillAction: plan.codexSkill.action,
|
|
1297
|
+
codexSessionStartHookPath: plan.codexSessionStartHook.path,
|
|
1298
|
+
codexSessionStartHookAction: plan.codexSessionStartHook.action,
|
|
1299
|
+
codexStopHookPath: plan.codexStopHook.path,
|
|
1300
|
+
codexStopHookAction: plan.codexStopHook.action,
|
|
1301
|
+
codexHooksConfigPath: plan.codexHooksConfig.path,
|
|
1302
|
+
codexHooksConfigAction: plan.codexHooksConfig.action,
|
|
1303
|
+
claudeHookPath: plan.claudeHook.path,
|
|
1304
|
+
claudeHookAction: plan.claudeHook.action,
|
|
1305
|
+
claudeSettingsPath: plan.claudeSettings.path,
|
|
1306
|
+
claudeSettingsAction: plan.claudeSettings.action
|
|
1307
|
+
};
|
|
1308
|
+
}
|
|
1309
|
+
async function executeInitStagePlan(plan, stageName) {
|
|
1310
|
+
const stage = plan.stages.find((entry) => entry.name === stageName);
|
|
1311
|
+
if (stage === void 0) {
|
|
1312
|
+
throw new Error(`Missing init stage plan: ${stageName}`);
|
|
1313
|
+
}
|
|
1314
|
+
if (stage.skipped) {
|
|
1315
|
+
return { name: stageName, disposition: "skipped" };
|
|
1316
|
+
}
|
|
1317
|
+
console.log(formatInitStageHeader(t(`cli.init.stages.${stageName}`)));
|
|
1318
|
+
try {
|
|
1319
|
+
switch (stage.name) {
|
|
1320
|
+
case "bootstrap": {
|
|
1321
|
+
const result = await installBootstrap(plan.target, { force: plan.options.force });
|
|
1322
|
+
if (result.details.length === 0) {
|
|
1323
|
+
console.log(formatInitStageResult("bootstrap", "skipped", 0, 0, t("cli.bootstrap.install.no-targets")));
|
|
1324
|
+
return { name: "bootstrap", disposition: "skipped" };
|
|
1325
|
+
}
|
|
1326
|
+
console.log(
|
|
1327
|
+
formatInitStageResult("bootstrap", "completed", result.installed.length, result.skipped.length)
|
|
1328
|
+
);
|
|
1329
|
+
return { name: "bootstrap", disposition: "ran" };
|
|
1330
|
+
}
|
|
1331
|
+
case "mcp": {
|
|
1332
|
+
if (stage.installMode === "local") {
|
|
1333
|
+
const manager = stage.packageManager ?? detectPackageManager(plan.target);
|
|
1334
|
+
writeStderr(t("cli.init.mcp.install.local"));
|
|
1335
|
+
writeStderr(t("cli.init.mcp.local.installing", { manager }));
|
|
1336
|
+
installLocalFabricServer(plan.target, manager);
|
|
1337
|
+
writeStderr(t("cli.init.mcp.local.installed"));
|
|
1338
|
+
} else {
|
|
1339
|
+
writeStderr(t("cli.init.mcp.install.global"));
|
|
1340
|
+
}
|
|
1341
|
+
const result = await installMcpClients(plan.target, {
|
|
1342
|
+
force: plan.options.force,
|
|
1343
|
+
localServerPath: stage.localServerPath
|
|
1344
|
+
});
|
|
1345
|
+
if (result.details.length === 0) {
|
|
1346
|
+
console.log(formatInitStageResult("mcp", "skipped", 0, 0, t("cli.config.install.no-configs")));
|
|
1347
|
+
return { name: "mcp", disposition: "skipped" };
|
|
1348
|
+
}
|
|
1349
|
+
console.log(formatInitStageResult("mcp", "completed", result.installed.length, result.skipped.length));
|
|
1350
|
+
return { name: "mcp", disposition: "ran" };
|
|
1351
|
+
}
|
|
1352
|
+
case "hooks": {
|
|
1353
|
+
const result = await installHooks(plan.target, { force: plan.options.force });
|
|
1354
|
+
console.log(formatInitStageResult("hooks", "completed", result.installed.length, result.skipped.length));
|
|
1355
|
+
return { name: "hooks", disposition: "ran" };
|
|
1356
|
+
}
|
|
1357
|
+
default:
|
|
1358
|
+
return exhaustiveInitStagePlan(stage);
|
|
1359
|
+
}
|
|
1360
|
+
} catch (error) {
|
|
1361
|
+
writeStderr(formatInitStageFailure(stageName, error));
|
|
1362
|
+
return { name: stageName, disposition: "failed" };
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
function shouldReplaceWritableDirectory(path, options) {
|
|
1366
|
+
if (!existsSync2(path)) {
|
|
1367
|
+
return false;
|
|
1368
|
+
}
|
|
1369
|
+
if (statSync2(path).isDirectory()) {
|
|
1370
|
+
return false;
|
|
1371
|
+
}
|
|
1372
|
+
if (!options?.force) {
|
|
1373
|
+
throw new Error(t("cli.init.errors.abort-existing", { path }));
|
|
1374
|
+
}
|
|
1375
|
+
return true;
|
|
1376
|
+
}
|
|
1377
|
+
function planFreshPath(path, options) {
|
|
1378
|
+
if (!existsSync2(path)) {
|
|
1379
|
+
return "created";
|
|
1380
|
+
}
|
|
1381
|
+
if (!options?.force) {
|
|
1382
|
+
throw new Error(t("cli.init.errors.abort-existing", { path }));
|
|
1383
|
+
}
|
|
1384
|
+
return "overwritten";
|
|
1385
|
+
}
|
|
1386
|
+
function preparePlannedPath(path, action) {
|
|
1387
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
1388
|
+
if (action === "overwritten" && existsSync2(path)) {
|
|
1389
|
+
rmSync(path, { recursive: true, force: true });
|
|
1390
|
+
}
|
|
1391
|
+
}
|
|
1392
|
+
function buildOptionalTemplateWritePlan(path, templatePath, options, executable = false) {
|
|
1393
|
+
const existed = existsSync2(path);
|
|
1394
|
+
if (existed && !options?.force) {
|
|
1395
|
+
return { path, action: "skipped", templatePath, executable };
|
|
1396
|
+
}
|
|
1397
|
+
return {
|
|
1398
|
+
path,
|
|
1399
|
+
action: existed ? "overwritten" : "created",
|
|
1400
|
+
templatePath,
|
|
1401
|
+
executable
|
|
1402
|
+
};
|
|
1403
|
+
}
|
|
1404
|
+
function applyOptionalTemplateWritePlan(plan) {
|
|
1405
|
+
if (plan.action === "skipped") {
|
|
1406
|
+
return;
|
|
1407
|
+
}
|
|
1408
|
+
mkdirSync(dirname(plan.path), { recursive: true });
|
|
1409
|
+
copyFileSync(plan.templatePath, plan.path);
|
|
1410
|
+
if (plan.executable) {
|
|
1411
|
+
chmodSync(plan.path, 493);
|
|
1412
|
+
}
|
|
1413
|
+
}
|
|
1414
|
+
function buildCodexHooksConfigValue() {
|
|
1415
|
+
return {
|
|
1416
|
+
hooks: {
|
|
1417
|
+
SessionStart: [
|
|
1418
|
+
{
|
|
1419
|
+
matcher: "*",
|
|
1420
|
+
hooks: [{ type: "command", command: CODEX_SESSION_START_COMMAND }]
|
|
1421
|
+
}
|
|
1422
|
+
],
|
|
1423
|
+
Stop: [
|
|
1424
|
+
{
|
|
1425
|
+
matcher: "*",
|
|
1426
|
+
hooks: [{ type: "command", command: CODEX_STOP_COMMAND }]
|
|
1427
|
+
}
|
|
1428
|
+
]
|
|
1429
|
+
}
|
|
1430
|
+
};
|
|
1431
|
+
}
|
|
1432
|
+
function buildCodexHooksConfigPlan(configPath, options) {
|
|
1433
|
+
const action = !existsSync2(configPath) ? "created" : options?.force ? "overwritten" : "skipped";
|
|
1434
|
+
return {
|
|
1435
|
+
path: configPath,
|
|
1436
|
+
action,
|
|
1437
|
+
value: buildCodexHooksConfigValue()
|
|
1438
|
+
};
|
|
1439
|
+
}
|
|
1440
|
+
function applyJsonWritePlan(plan) {
|
|
1441
|
+
if (plan.action === "skipped") {
|
|
1442
|
+
return;
|
|
1443
|
+
}
|
|
1444
|
+
mkdirSync(dirname(plan.path), { recursive: true });
|
|
1445
|
+
writeJsonAtomically(plan.path, plan.value);
|
|
1446
|
+
}
|
|
1447
|
+
function buildClaudeSettingsWritePlan(settingsPath, options) {
|
|
1448
|
+
let settings;
|
|
1449
|
+
let action = "updated";
|
|
1450
|
+
if (!existsSync2(settingsPath)) {
|
|
1451
|
+
settings = {};
|
|
1452
|
+
action = "created";
|
|
1453
|
+
} else {
|
|
1454
|
+
try {
|
|
1455
|
+
const parsed = JSON.parse(readFileSync2(settingsPath, "utf8"));
|
|
1456
|
+
if (!isRecord(parsed)) {
|
|
1457
|
+
writeStderr(t("cli.init.claude-settings.invalid-object", { label: skippedLabel(), path: settingsPath }));
|
|
1458
|
+
return { path: settingsPath, action: "skipped-invalid", value: null };
|
|
1459
|
+
}
|
|
1460
|
+
settings = parsed;
|
|
1461
|
+
} catch (error) {
|
|
1462
|
+
const reason = error instanceof Error ? error.message : "unknown parse error";
|
|
1463
|
+
writeStderr(t("cli.init.claude-settings.invalid-json", { label: skippedLabel(), path: settingsPath, reason }));
|
|
1464
|
+
return { path: settingsPath, action: "skipped-invalid", value: null };
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
if (settings.hooks !== void 0 && !isRecord(settings.hooks)) {
|
|
1468
|
+
writeStderr(t("cli.init.claude-settings.invalid-hooks", { label: skippedLabel(), path: settingsPath }));
|
|
1469
|
+
return { path: settingsPath, action: "skipped-invalid", value: null };
|
|
1470
|
+
}
|
|
1471
|
+
const hooks = settings.hooks ?? {};
|
|
1472
|
+
const stopHooksValue = hooks.Stop;
|
|
1473
|
+
if (stopHooksValue !== void 0 && !Array.isArray(stopHooksValue)) {
|
|
1474
|
+
writeStderr(t("cli.init.claude-settings.invalid-stop-array", { label: skippedLabel(), path: settingsPath }));
|
|
1475
|
+
return { path: settingsPath, action: "skipped-invalid", value: null };
|
|
1476
|
+
}
|
|
1477
|
+
const stopHooks = Array.isArray(stopHooksValue) ? stopHooksValue : [];
|
|
1478
|
+
const hasExistingFabricHook = hasClaudeInitReminderHook(stopHooks);
|
|
1479
|
+
if (hasExistingFabricHook && !options?.force) {
|
|
1480
|
+
return { path: settingsPath, action: "skipped", value: null };
|
|
1481
|
+
}
|
|
1482
|
+
const nextStopHooks = hasExistingFabricHook && options?.force ? removeClaudeInitReminderHook(stopHooks) : [...stopHooks];
|
|
1483
|
+
nextStopHooks.push({
|
|
1484
|
+
matcher: "*",
|
|
1485
|
+
hooks: [
|
|
1486
|
+
{
|
|
1487
|
+
type: "command",
|
|
1488
|
+
command: CLAUDE_INIT_REMINDER_COMMAND
|
|
1489
|
+
}
|
|
1490
|
+
]
|
|
1491
|
+
});
|
|
1492
|
+
const nextSettings = {
|
|
1493
|
+
...settings,
|
|
1494
|
+
hooks: {
|
|
1495
|
+
...hooks,
|
|
1496
|
+
Stop: nextStopHooks
|
|
1497
|
+
}
|
|
1498
|
+
};
|
|
1499
|
+
return {
|
|
1500
|
+
path: settingsPath,
|
|
1501
|
+
action: hasExistingFabricHook && options?.force ? "overwritten" : action,
|
|
1502
|
+
value: nextSettings
|
|
1503
|
+
};
|
|
1504
|
+
}
|
|
1505
|
+
function applyClaudeSettingsWritePlan(plan) {
|
|
1506
|
+
if (plan.value === null) {
|
|
1507
|
+
return;
|
|
1508
|
+
}
|
|
1509
|
+
mkdirSync(dirname(plan.path), { recursive: true });
|
|
1510
|
+
writeJsonAtomically(plan.path, plan.value);
|
|
1511
|
+
}
|
|
1512
|
+
function createDefaultInitWizardAdapter() {
|
|
1513
|
+
return {
|
|
1514
|
+
async run(context) {
|
|
1515
|
+
intro(t("cli.init.wizard.intro"));
|
|
1516
|
+
note(
|
|
1517
|
+
t("cli.init.wizard.overview.body", {
|
|
1518
|
+
target: context.target,
|
|
1519
|
+
mode: formatInitModeBadge(context.options)
|
|
1520
|
+
}),
|
|
1521
|
+
t("cli.init.wizard.overview.title")
|
|
1522
|
+
);
|
|
1523
|
+
printInitPlanSummary(context.target, context.options, context.mcpInstallMode, context.supports);
|
|
1524
|
+
log.step(t("cli.init.wizard.step.target"));
|
|
1525
|
+
const continueWithTarget = await confirm({
|
|
1526
|
+
message: t("cli.init.wizard.target.confirm", { target: context.target }),
|
|
1527
|
+
initialValue: true
|
|
1528
|
+
});
|
|
1529
|
+
if (isCancel(continueWithTarget) || !continueWithTarget) {
|
|
1530
|
+
emitInitWizardCancellation();
|
|
1531
|
+
return null;
|
|
1532
|
+
}
|
|
1533
|
+
log.step(t("cli.init.wizard.step.plan"));
|
|
1534
|
+
let groupedSelection;
|
|
1535
|
+
try {
|
|
1536
|
+
groupedSelection = await group(
|
|
1537
|
+
{
|
|
1538
|
+
bootstrap: async () => context.lockedStages.includes("bootstrap") ? false : confirmInGroup({
|
|
1539
|
+
message: t("cli.init.wizard.stage.bootstrap", {
|
|
1540
|
+
defaultValue: formatPromptDefault(!context.options.skipBootstrap)
|
|
1541
|
+
}),
|
|
1542
|
+
initialValue: !context.options.skipBootstrap
|
|
1543
|
+
}),
|
|
1544
|
+
mcp: async () => context.lockedStages.includes("mcp") ? false : confirmInGroup({
|
|
1545
|
+
message: t("cli.init.wizard.stage.mcp", {
|
|
1546
|
+
defaultValue: formatPromptDefault(!context.options.skipMcp)
|
|
1547
|
+
}),
|
|
1548
|
+
initialValue: !context.options.skipMcp
|
|
1549
|
+
}),
|
|
1550
|
+
mcpInstallMode: async ({ results }) => results.mcp ? selectMcpInstallModeInGroup({
|
|
1551
|
+
message: t("cli.init.wizard.mcp-install", { defaultValue: context.mcpInstallMode }),
|
|
1552
|
+
initialValue: context.mcpInstallMode,
|
|
1553
|
+
options: [
|
|
1554
|
+
{ value: "global", label: "global", hint: t("cli.init.mcp.install.global") },
|
|
1555
|
+
{ value: "local", label: "local", hint: t("cli.init.mcp.install.local") }
|
|
1556
|
+
]
|
|
1557
|
+
}) : context.mcpInstallMode,
|
|
1558
|
+
hooks: async () => context.lockedStages.includes("hooks") ? false : confirmInGroup({
|
|
1559
|
+
message: t("cli.init.wizard.stage.hooks", {
|
|
1560
|
+
defaultValue: formatPromptDefault(!context.options.skipHooks)
|
|
1561
|
+
}),
|
|
1562
|
+
initialValue: !context.options.skipHooks
|
|
1563
|
+
})
|
|
1564
|
+
},
|
|
1565
|
+
{
|
|
1566
|
+
onCancel() {
|
|
1567
|
+
throw INIT_WIZARD_GROUP_CANCELLED;
|
|
1568
|
+
}
|
|
1569
|
+
}
|
|
1570
|
+
);
|
|
1571
|
+
} catch (error) {
|
|
1572
|
+
if (error === INIT_WIZARD_GROUP_CANCELLED) {
|
|
1573
|
+
emitInitWizardCancellation();
|
|
1574
|
+
return null;
|
|
1575
|
+
}
|
|
1576
|
+
throw error;
|
|
1577
|
+
}
|
|
1578
|
+
if (groupedSelection === null) {
|
|
1579
|
+
emitInitWizardCancellation();
|
|
1580
|
+
return null;
|
|
1581
|
+
}
|
|
1582
|
+
const previewOptions = {
|
|
1583
|
+
...context.options,
|
|
1584
|
+
skipBootstrap: !groupedSelection.bootstrap,
|
|
1585
|
+
skipMcp: !groupedSelection.mcp,
|
|
1586
|
+
skipHooks: !groupedSelection.hooks
|
|
1587
|
+
};
|
|
1588
|
+
log.step(t("cli.init.wizard.step.review"));
|
|
1589
|
+
printInitPlanSummary(context.target, previewOptions, groupedSelection.mcpInstallMode, context.supports);
|
|
1590
|
+
const confirmed = await confirm({
|
|
1591
|
+
message: t("cli.init.wizard.execute.confirm"),
|
|
1592
|
+
initialValue: true
|
|
1593
|
+
});
|
|
1594
|
+
if (isCancel(confirmed) || !confirmed) {
|
|
1595
|
+
emitInitWizardCancellation();
|
|
1596
|
+
return null;
|
|
1597
|
+
}
|
|
1598
|
+
outro(t("cli.init.wizard.outro"));
|
|
1599
|
+
return groupedSelection;
|
|
1600
|
+
}
|
|
1091
1601
|
};
|
|
1092
1602
|
}
|
|
1603
|
+
function emitInitWizardCancellation() {
|
|
1604
|
+
cancel(t("cli.init.wizard.cancelled"));
|
|
1605
|
+
}
|
|
1606
|
+
async function confirmInGroup(options) {
|
|
1607
|
+
const result = await confirm(options);
|
|
1608
|
+
if (isCancel(result)) {
|
|
1609
|
+
throw INIT_WIZARD_GROUP_CANCELLED;
|
|
1610
|
+
}
|
|
1611
|
+
return result;
|
|
1612
|
+
}
|
|
1613
|
+
async function selectMcpInstallModeInGroup(options) {
|
|
1614
|
+
const result = await select({
|
|
1615
|
+
message: options.message,
|
|
1616
|
+
initialValue: options.initialValue,
|
|
1617
|
+
options: options.options
|
|
1618
|
+
});
|
|
1619
|
+
if (isCancel(result)) {
|
|
1620
|
+
throw INIT_WIZARD_GROUP_CANCELLED;
|
|
1621
|
+
}
|
|
1622
|
+
return result;
|
|
1623
|
+
}
|
|
1624
|
+
function collectLockedWizardStages(args) {
|
|
1625
|
+
const lockedStages = [];
|
|
1626
|
+
if (args.bootstrap === false) {
|
|
1627
|
+
lockedStages.push("bootstrap");
|
|
1628
|
+
}
|
|
1629
|
+
if (args.mcp === false) {
|
|
1630
|
+
lockedStages.push("mcp");
|
|
1631
|
+
}
|
|
1632
|
+
if (args.hooks === false) {
|
|
1633
|
+
lockedStages.push("hooks");
|
|
1634
|
+
}
|
|
1635
|
+
return lockedStages;
|
|
1636
|
+
}
|
|
1637
|
+
function formatPromptDefault(value) {
|
|
1638
|
+
return value ? "Y/n" : "y/N";
|
|
1639
|
+
}
|
|
1640
|
+
function formatInitModeBanner(options) {
|
|
1641
|
+
if (options.planOnly && options.reapply) {
|
|
1642
|
+
return t("cli.init.plan.mode-banner.plan-reapply");
|
|
1643
|
+
}
|
|
1644
|
+
if (options.planOnly) {
|
|
1645
|
+
return t("cli.init.plan.mode-banner.plan");
|
|
1646
|
+
}
|
|
1647
|
+
if (options.reapply) {
|
|
1648
|
+
return t("cli.init.plan.mode-banner.reapply");
|
|
1649
|
+
}
|
|
1650
|
+
return t("cli.init.plan.mode-banner.default");
|
|
1651
|
+
}
|
|
1652
|
+
function formatInitModeBadge(options) {
|
|
1653
|
+
if (options.planOnly && options.reapply) {
|
|
1654
|
+
return t("cli.init.mode.badge.plan-reapply");
|
|
1655
|
+
}
|
|
1656
|
+
if (options.planOnly) {
|
|
1657
|
+
return t("cli.init.mode.badge.plan");
|
|
1658
|
+
}
|
|
1659
|
+
if (options.reapply) {
|
|
1660
|
+
return t("cli.init.mode.badge.reapply");
|
|
1661
|
+
}
|
|
1662
|
+
return t("cli.init.mode.badge.default");
|
|
1663
|
+
}
|
|
1093
1664
|
function normalizeTarget2(targetInput) {
|
|
1094
1665
|
return isAbsolute2(targetInput) ? targetInput : resolve2(process.cwd(), targetInput);
|
|
1095
1666
|
}
|
|
@@ -1168,102 +1739,6 @@ function templateCandidatesFrom(start, relativePath) {
|
|
|
1168
1739
|
}
|
|
1169
1740
|
return candidates.reverse();
|
|
1170
1741
|
}
|
|
1171
|
-
function prepareFreshPath(path, options) {
|
|
1172
|
-
if (!existsSync2(path)) {
|
|
1173
|
-
return "created";
|
|
1174
|
-
}
|
|
1175
|
-
if (!options?.force) {
|
|
1176
|
-
throw new Error(t("cli.init.errors.abort-existing", { path }));
|
|
1177
|
-
}
|
|
1178
|
-
rmSync(path, { recursive: true, force: true });
|
|
1179
|
-
return "overwritten";
|
|
1180
|
-
}
|
|
1181
|
-
function prepareWritableDirectory(path, options) {
|
|
1182
|
-
if (!existsSync2(path) || statSync2(path).isDirectory()) {
|
|
1183
|
-
return;
|
|
1184
|
-
}
|
|
1185
|
-
if (!options?.force) {
|
|
1186
|
-
throw new Error(t("cli.init.errors.abort-existing", { path }));
|
|
1187
|
-
}
|
|
1188
|
-
rmSync(path, { force: true });
|
|
1189
|
-
}
|
|
1190
|
-
function writeNewFile(path, content, options) {
|
|
1191
|
-
const existed = existsSync2(path);
|
|
1192
|
-
if (existed && !options?.force) {
|
|
1193
|
-
throw new Error(t("cli.init.errors.abort-existing", { path }));
|
|
1194
|
-
}
|
|
1195
|
-
writeFileSync(path, content, "utf8");
|
|
1196
|
-
return existed ? "overwritten" : "created";
|
|
1197
|
-
}
|
|
1198
|
-
function copyTemplateIfMissing(templatePath, targetPath, options) {
|
|
1199
|
-
mkdirSync(dirname(targetPath), { recursive: true });
|
|
1200
|
-
const existed = existsSync2(targetPath);
|
|
1201
|
-
if (existed && !options?.force) {
|
|
1202
|
-
return "skipped";
|
|
1203
|
-
}
|
|
1204
|
-
copyFileSync(templatePath, targetPath);
|
|
1205
|
-
return existed ? "overwritten" : "created";
|
|
1206
|
-
}
|
|
1207
|
-
function copyExecutableTemplateIfMissing(templatePath, targetPath, options) {
|
|
1208
|
-
const action = copyTemplateIfMissing(templatePath, targetPath, options);
|
|
1209
|
-
if (action !== "skipped") {
|
|
1210
|
-
chmodSync(targetPath, 493);
|
|
1211
|
-
}
|
|
1212
|
-
return action;
|
|
1213
|
-
}
|
|
1214
|
-
function mergeClaudeStopHook(settingsPath, options) {
|
|
1215
|
-
mkdirSync(dirname(settingsPath), { recursive: true });
|
|
1216
|
-
let settings;
|
|
1217
|
-
let action = "updated";
|
|
1218
|
-
if (!existsSync2(settingsPath)) {
|
|
1219
|
-
settings = {};
|
|
1220
|
-
action = "created";
|
|
1221
|
-
} else {
|
|
1222
|
-
try {
|
|
1223
|
-
const parsed = JSON.parse(readFileSync2(settingsPath, "utf8"));
|
|
1224
|
-
if (!isRecord(parsed)) {
|
|
1225
|
-
writeStderr(t("cli.init.claude-settings.invalid-object", { label: skippedLabel(), path: settingsPath }));
|
|
1226
|
-
return "skipped-invalid";
|
|
1227
|
-
}
|
|
1228
|
-
settings = parsed;
|
|
1229
|
-
} catch (error) {
|
|
1230
|
-
const reason = error instanceof Error ? error.message : "unknown parse error";
|
|
1231
|
-
writeStderr(t("cli.init.claude-settings.invalid-json", { label: skippedLabel(), path: settingsPath, reason }));
|
|
1232
|
-
return "skipped-invalid";
|
|
1233
|
-
}
|
|
1234
|
-
}
|
|
1235
|
-
if (settings.hooks !== void 0 && !isRecord(settings.hooks)) {
|
|
1236
|
-
writeStderr(t("cli.init.claude-settings.invalid-hooks", { label: skippedLabel(), path: settingsPath }));
|
|
1237
|
-
return "skipped-invalid";
|
|
1238
|
-
}
|
|
1239
|
-
const hooks = settings.hooks ?? {};
|
|
1240
|
-
const stopHooksValue = hooks.Stop;
|
|
1241
|
-
if (stopHooksValue !== void 0 && !Array.isArray(stopHooksValue)) {
|
|
1242
|
-
writeStderr(t("cli.init.claude-settings.invalid-stop-array", { label: skippedLabel(), path: settingsPath }));
|
|
1243
|
-
return "skipped-invalid";
|
|
1244
|
-
}
|
|
1245
|
-
const stopHooks = Array.isArray(stopHooksValue) ? stopHooksValue : [];
|
|
1246
|
-
const hasExistingFabricHook = hasClaudeInitReminderHook(stopHooks);
|
|
1247
|
-
if (hasExistingFabricHook && !options?.force) {
|
|
1248
|
-
return "skipped";
|
|
1249
|
-
}
|
|
1250
|
-
const nextStopHooks = hasExistingFabricHook && options?.force ? removeClaudeInitReminderHook(stopHooks) : [...stopHooks];
|
|
1251
|
-
nextStopHooks.push({
|
|
1252
|
-
matcher: "*",
|
|
1253
|
-
hooks: [
|
|
1254
|
-
{
|
|
1255
|
-
type: "command",
|
|
1256
|
-
command: CLAUDE_INIT_REMINDER_COMMAND
|
|
1257
|
-
}
|
|
1258
|
-
]
|
|
1259
|
-
});
|
|
1260
|
-
settings.hooks = {
|
|
1261
|
-
...hooks,
|
|
1262
|
-
Stop: nextStopHooks
|
|
1263
|
-
};
|
|
1264
|
-
writeJsonAtomically(settingsPath, settings);
|
|
1265
|
-
return hasExistingFabricHook && options?.force ? "overwritten" : action;
|
|
1266
|
-
}
|
|
1267
1742
|
function hasClaudeInitReminderHook(stopHooks) {
|
|
1268
1743
|
return stopHooks.some((entry) => isClaudeInitReminderStopEntry(entry));
|
|
1269
1744
|
}
|
|
@@ -1306,10 +1781,10 @@ function formatClaudeSettingsAction(settingsPath, action) {
|
|
|
1306
1781
|
function formatInitStageHeader(message) {
|
|
1307
1782
|
return `${nextLabel()} ${paint.muted(message)}`;
|
|
1308
1783
|
}
|
|
1309
|
-
function formatInitStageResult(stage, status, installedCount, skippedCount,
|
|
1784
|
+
function formatInitStageResult(stage, status, installedCount, skippedCount, note2) {
|
|
1310
1785
|
const label = status === "completed" ? completedStageLabel() : skippedStageLabel();
|
|
1311
1786
|
const counts = `installed=${installedCount} skipped=${skippedCount}`;
|
|
1312
|
-
const suffix =
|
|
1787
|
+
const suffix = note2 ? ` ${paint.muted(`(${note2})`)}` : "";
|
|
1313
1788
|
return `${label} ${stage}: ${counts}${suffix}`;
|
|
1314
1789
|
}
|
|
1315
1790
|
function formatInitStageFailure(stage, error) {
|
|
@@ -1332,10 +1807,11 @@ function shouldPrintHooksNextStep(options, stageResults) {
|
|
|
1332
1807
|
return Boolean(options.skipHooks) || stageResults.some((stage) => stage.name === "hooks" && stage.disposition === "failed");
|
|
1333
1808
|
}
|
|
1334
1809
|
function isInteractiveInit() {
|
|
1335
|
-
return Boolean(process.stdout.isTTY) && Boolean(process.stderr.isTTY);
|
|
1810
|
+
return Boolean(process.stdin.isTTY) && Boolean(process.stdout.isTTY) && Boolean(process.stderr.isTTY);
|
|
1336
1811
|
}
|
|
1337
1812
|
function printInitPlanSummary(target, options, mcpInstallMode, supports) {
|
|
1338
1813
|
console.log(t("cli.init.plan.title"));
|
|
1814
|
+
console.log(formatInitModeBanner(options));
|
|
1339
1815
|
console.log(t("cli.init.plan.target", { target }));
|
|
1340
1816
|
console.log(
|
|
1341
1817
|
t("cli.init.plan.actions", {
|
|
@@ -1387,21 +1863,42 @@ function printInitCapabilitySummary(supports, stageResults, options) {
|
|
|
1387
1863
|
console.log(formatCapabilityTableRow(row, widths));
|
|
1388
1864
|
}
|
|
1389
1865
|
}
|
|
1866
|
+
function formatCodexHooksAction(configPath, action) {
|
|
1867
|
+
switch (action) {
|
|
1868
|
+
case "created":
|
|
1869
|
+
return t("cli.init.codex-hooks.created", { label: createdLabel(), path: configPath });
|
|
1870
|
+
case "overwritten":
|
|
1871
|
+
return t("cli.init.codex-hooks.updated", { label: overwrittenLabel(), path: configPath });
|
|
1872
|
+
case "skipped":
|
|
1873
|
+
return t("cli.init.codex-hooks.skipped", { label: skippedLabel(), path: configPath });
|
|
1874
|
+
default:
|
|
1875
|
+
return t("cli.init.codex-hooks.updated", { label: updatedLabel(), path: configPath });
|
|
1876
|
+
}
|
|
1877
|
+
}
|
|
1390
1878
|
function toCapabilityRow(support, stageResults, options) {
|
|
1391
1879
|
const stage = (name) => stageResults.find((entry) => entry.name === name)?.disposition ?? null;
|
|
1392
1880
|
const bootstrap = support.capabilities.bootstrap ? capabilityStatus(options.skipBootstrap ? "skipped" : stage("bootstrap")) : t("cli.init.capabilities.status.na");
|
|
1393
1881
|
const mcp = support.capabilities.mcp ? capabilityStatus(options.skipMcp ? "skipped" : stage("mcp")) : t("cli.init.capabilities.status.na");
|
|
1394
|
-
const hook = support
|
|
1395
|
-
const skill = support
|
|
1882
|
+
const hook = capabilityInstallStatus(support, "hook");
|
|
1883
|
+
const skill = capabilityInstallStatus(support, "skill");
|
|
1396
1884
|
return {
|
|
1397
1885
|
client: support.label,
|
|
1398
1886
|
bootstrap,
|
|
1399
1887
|
mcp,
|
|
1400
1888
|
hook,
|
|
1401
1889
|
skill,
|
|
1402
|
-
followUp: support.capabilities.skill ? t("cli.init.capabilities.follow-up.
|
|
1890
|
+
followUp: hasInstalledCapability(support, "skill") ? t("cli.init.capabilities.follow-up.ready") : support.capabilities.skill ? t("cli.init.capabilities.follow-up.install") : t("cli.init.capabilities.follow-up.manual")
|
|
1403
1891
|
};
|
|
1404
1892
|
}
|
|
1893
|
+
function capabilityInstallStatus(support, capability) {
|
|
1894
|
+
if (!support.capabilities[capability]) {
|
|
1895
|
+
return t("cli.init.capabilities.status.na");
|
|
1896
|
+
}
|
|
1897
|
+
return hasInstalledCapability(support, capability) ? t("cli.init.capabilities.status.installed") : t("cli.init.capabilities.status.supported");
|
|
1898
|
+
}
|
|
1899
|
+
function hasInstalledCapability(support, capability) {
|
|
1900
|
+
return support.installedCapabilities?.[capability] === true;
|
|
1901
|
+
}
|
|
1405
1902
|
function capabilityStatus(disposition) {
|
|
1406
1903
|
switch (disposition) {
|
|
1407
1904
|
case "ran":
|
|
@@ -1437,8 +1934,21 @@ function formatCapabilityDivider(widths) {
|
|
|
1437
1934
|
].join(" ");
|
|
1438
1935
|
}
|
|
1439
1936
|
function formatInitReasonMessage(supports) {
|
|
1440
|
-
|
|
1441
|
-
|
|
1937
|
+
const detected = supports.filter((support) => support.detected);
|
|
1938
|
+
const installedSkillClients = detected.filter((support) => hasInstalledCapability(support, "skill"));
|
|
1939
|
+
const hasClaudeSkill = installedSkillClients.some((support) => support.clientKind === "ClaudeCodeCLI");
|
|
1940
|
+
const hasCodexSkill = installedSkillClients.some((support) => support.clientKind === "CodexCLI");
|
|
1941
|
+
if (hasClaudeSkill && hasCodexSkill) {
|
|
1942
|
+
return t("cli.init.reason-message.multi-body");
|
|
1943
|
+
}
|
|
1944
|
+
if (hasClaudeSkill) {
|
|
1945
|
+
return t("cli.init.reason-message.claude-body");
|
|
1946
|
+
}
|
|
1947
|
+
if (hasCodexSkill) {
|
|
1948
|
+
return t("cli.init.reason-message.codex-body");
|
|
1949
|
+
}
|
|
1950
|
+
if (detected.some((support) => support.capabilities.skill)) {
|
|
1951
|
+
return t("cli.init.reason-message.installable-body");
|
|
1442
1952
|
}
|
|
1443
1953
|
return t("cli.init.reason-message.manual-body");
|
|
1444
1954
|
}
|
|
@@ -1492,8 +2002,15 @@ function sha256(content) {
|
|
|
1492
2002
|
return `sha256:${createHash("sha256").update(content).digest("hex")}`;
|
|
1493
2003
|
}
|
|
1494
2004
|
export {
|
|
2005
|
+
buildInitExecutionPlan,
|
|
2006
|
+
buildInitFabricPlan,
|
|
2007
|
+
createDefaultInitWizardAdapter,
|
|
1495
2008
|
init_default as default,
|
|
1496
2009
|
detectPackageManager,
|
|
2010
|
+
executeInitExecutionPlan,
|
|
2011
|
+
executeInitFabricPlan,
|
|
1497
2012
|
initCommand,
|
|
1498
|
-
initFabric
|
|
2013
|
+
initFabric,
|
|
2014
|
+
resolveInitExecutionPlanWithWizard,
|
|
2015
|
+
shouldUseInitWizard
|
|
1499
2016
|
};
|