Initial commit of current engine library state.

This commit is contained in:
Tonoxis
2023-04-18 02:42:48 -04:00
commit db250b97bc
9 changed files with 416 additions and 0 deletions

4
.gitignore vendored Normal file
View File

@@ -0,0 +1,4 @@
composer.lock
bin/
obj/
vendor/

32
CamsAIEngine.msbuildproj Executable file
View File

@@ -0,0 +1,32 @@
<Project Sdk="Peachpie.NET.Sdk/1.2.0-r15367">
<PropertyGroup>
<OutputType>library</OutputType>
<TargetFramework>net7.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<ComposerAutoload>true</ComposerAutoload>
<PackageId>CamsAI</PackageId>
<Authors>Toxus</Authors>
<Product>CamsAI</Product>
<AssemblyName>CamsAI</AssemblyName>
</PropertyGroup>
<ItemGroup>
<Compile Include="**/*.php" />
</ItemGroup>
<ItemGroup>
<Compile Remove="**/test/**/*.php" />
<Compile Remove="**/tests/**/*.php" />
</ItemGroup>
<ItemGroup>
<Compile Remove="vendor\lfischer\open-weather-map-api\src\RequestAdapter\Guzzle.php" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="HADotNet.Core" Version="1.6.0" />
<PackageReference Include="Peachpie.Library.Scripting" Version="1.2.0-r15367" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AIML\Aiml\Aiml.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Update="Peachpie.App" Version="1.2.0-r15367" />
</ItemGroup>
</Project>

19
composer.json Executable file
View File

@@ -0,0 +1,19 @@
{
"name": "toxus/camsai",
"type": "library",
"autoload": {
"psr-4": {
"CamsAI\\": "src/",
"lfischer\\": "vendor/lfischer/open-weather-map-api"
}
},
"authors": [
{
"name": "ShadowEO",
"email": "dreamcaster23@gmail.com"
}
],
"require": {
"lfischer/open-weather-map-api": "^1.0"
}
}

52
src/CamsAI/CamSensory.class.php Executable file
View File

@@ -0,0 +1,52 @@
<?php
// TODO: Look at .NET based Home Assistant Libraries
namespace CamsAI;
class SensoryEngine
{
protected $sensors;
protected $currentAction;
private $linfo;
private $linfo_parser;
function __construct() {
// Get System Information
$this->linfo = new \Linfo\Linfo;
$this->linfo_parser = $linfo->getParser();
$this->sensors = array(
"disk-space"=>array(
"free"=>"",
"total"=>"",
"used"=>""
),
"serial-number"=>"",
"operating-system"=>$this->linfo_parser->getDistro()['name'],
"home-assistant"=>array(),
"free-memory"=>$this->linfo_parser->getRAM()['free'],
"total-memory"=>$this->linfo_parser->getRAM()['total'],
"processor-arch"=>$this->linfo_parser->getCPUArchitecture(),
"processor"=>$this->linfo_parser->getCPU()[0]['Model']
);
}
function updateSensors() {
$this->sensors = array(
"disk-space"=>array(
"free"=>"",
"total"=>"",
"used"=>""
),
"serial-number"=>"",
"operating-system"=>$this->linfo_parser->getDistro()['name'],
"home-assistant"=>array(),
"free-memory"=>$this->linfo_parser->getRAM()['free'],
"total-memory"=>$this->linfo_parser->getRAM()['total'],
"processor-arch"=>$this->linfo_parser->getCPUArchitecture(),
"processor"=>$this->linfo_parser->getCPU()[0]['Model']
);
}
}

169
src/CamsAI/Engine.class.php Executable file
View File

@@ -0,0 +1,169 @@
<?php
use Aiml;
use System\Reflection\Assembly;
use lfischer\OpenWeatherMap\API;
include_once("src\CamsAI\SraixServices\Weather.SraiX.php");
include_once("src\CamsAI\SraixServices\HomeAssistant.SraiX.php");
include_once("vendor/autoload.php");
namespace CamsAI;
/**
* C.A.M.S AI Engine DLL Class
*/
class Engine
{
public $bot;
public $user;
private $currentPlatform;
function __construct($pBotConfig, $Username = null) {
// System.Reflection.Assembly.GetCallingAssembly().GetName().Version
$Version = \System\Reflection\Assembly::GetCallingAssembly()->GetName()->Version->toString();
\System\Diagnostics\Debug::WriteLine("[CAMS AI Engine] AI Engine Version: ".$Version."; System Boot");
if(empty($pBotConfig))
{
$pBotConfig = __DIR__."/bot";
}
// Let's check the platform it's currently running on
$Platform = php_uname('s');
if($Platform == "Windows NT") {
define("CURRENT_PLATFORM", "Win32NT");
} elseif($Platform == "Linux") {
$unameOutput = shell_exec("uname -a");
if(strpos($unameOutput, 'Ubuntu') !== false) {
define("CURRENT_PLATFORM", "Ubuntu");
} elseif(strpos($unameOutput, 'Debian') !== false) {
define("CURRENT_PLATFORM", "Debian");
} else {
define("CURRENT_PLATFORM", "UnknownUnix");
}
} else {
define("CURRENT_PLATFORM", "Unknown");
}
\System\Diagnostics\Debug::WriteLine("[CAMS AI Engine] Detected Platform: ".CURRENT_PLATFORM);
// Set the current platform as a bot predicate
\System\Diagnostics\Debug::WriteLine("[CAMS AI Engine] Bot directory:".$pBotConfig);
// Load the AI AIML and configuration
$this->bot = new \Aiml\Bot($pBotConfig);
$this->bot->LoadConfig();
$this->bot->LoadAIML();
$this->bot->SraixServices->Add("CamsAI.SraixServices.Weather", new \CamsAI\SraixServices\Weather());
$this->bot->SraixServices->Add("CamsAI.SraixServices.HomeAssistant", new \CamsAI\SraixServices\HomeAssistant());
// If $Username is empty, get the username from the system environment
if(empty($Username)) {
$Username = get_current_user();
}
// Initialize the User object for the AI
$this->user = new \Aiml\User($Username, $this->bot);
// Import saved system predicates
if(file_exists($pBotConfig."/system_predicates.json")) {
$predicates = json_decode(file_get_contents($pBotConfig."/system_predicates.json"), true);
// We'll want to unset some dynamic predicates
unset($predicates['currentPlatform']);
unset($predicates['freeDiskSpacePercentage']);
unset($predicates['freeMemoryPercentage']);
$predicates['emotionalState'] = "normal";
array_merge($this->bot->Config->BotProperties, $predicates);
}
// Set the current platform as a bot predicate
$this->bot->Config->BotProperties->Add("currentPlatform", CURRENT_PLATFORM);
// Restore the user's predicates
if(file_exists($pBotConfig."/".$Username."_predicates.json")) {
$predicates = json_decode(file_get_contents($pBotConfig."/".$Username."_predicates.json"));
$this->user->Predicates = $predicates;
}
register_shutdown_function(array("CamsAI", "saveBotPredicates"));
register_shutdown_function(array("CamsAI", "saveUserPredicates"));
//var_dump(get_declared_classes());
$response = $this->SendChatRequest("XSYSTEM_EVENT AI_BOOT", $this->user);
if($response['message']->Sentences[0] != $this->bot->Config->DefaultResponse) {
\System\Diagnostics\Debug::WriteLine("[CAMS AI SYSTEM BOOT] ".$response['message']);
echo("AI> ".$response['message']."\r\n");
} else {
\System\Diagnostics\Debug::WriteLine("[CAMS AI SYSTEM BOOT] No \"XSYSTEM_EVENT AI_BOOT\" pattern in the bot's AIML.'");
}
}
function SendChatRequest($ChatRequestPattern, $User, $OobCallback = array("CamsAI\Engine","parseOOB")) {
$response = $this->bot->Chat($ChatRequestPattern, $User, $trace);
$oobPresent = preg_match("/<oob>(.*?)<\/oob>/i", $response, $oob);
if($oobPresent)
{
// Parse the OOB tags and then remove them from the response.
$this->parseOOB($oob[0], $OobCallback);
$response = str_replace($oob[0], "", $response);
}
$response = array("message" => $response,
"oobPresent" => $oobPresent,
"oobTags" => $oob);
return $response;
}
public function saveUserPredicates() {
\System\Diagnostics\Debug::WriteLine("Saving User Predicates...");
$predicates = json_encode($this->user->Predicates);
if(empty($predicates)) {
throw new Exception("Cannot access user predicates");
}
file_put_contents($predicates, $pBotConfig."/".$Username."_predicates.json");
}
public function saveBotPredicates()
{
\System\Diagnostics\Debug::WriteLine("Saving Bot Predicates...");
$predicates = json_encode($this->bot->Predicates);
if(empty($predicates)) {
throw new Exception("Cannot access bot predicates.");
}
file_put_contents($predicates, $pBotConfig."/system_predicates.json");
}
static function parseOOB($OobXML, $OobCallback = null)
{
$xml = simplexml_load_string($OobXML);
foreach ($xml as $tag => $value)
{
// Created handler for XML
\System\Diagnostics\Debug::WriteLine("[Engine Internal OOB Parser] Tag Detected: ". $tag. "\r\n");
switch($tag)
{
case "openApplication":
$descriptorspec = array();
proc_open($value, $descriptorspec, $pipes, null, null, array("bypass_shell",true));
break;
case "openUri":
$Process = new \System\Diagnostics\ProcessStartInfo($value);
$Process->UseShellExecute = true;
\System\Diagnostics\Process::Start($Process);
case "apiCall":
// We're eventually going to replace this with a tononixAPI call
\System\Diagnostics\Debug::WriteLine("[Engine Internal OOB Parser] apiCall: $value");
$request = (string)$value;
\System\Diagnostics\Debug::WriteLine("[Engine Internal API Call] $result");
break;
default:
if($OobCallback == null)
{
\System\Diagnostics\Debug::WriteLine("[Engine Internal OOB Parser] Tag $tag is unsupported by Engine.");
} else {
\System\Diagnostics\Debug::WriteLine("[Engine Internal OOB Parser] Tag $tag is unsupported by Engine, sending to requested callback: ". $OobCallback);
$OobCallback($OobXML);
}
}
}
}
}

View File

@@ -0,0 +1,18 @@
<?php
use Aiml;
namespace CamsAI\SraixServices;
class HomeAssistant implements \Aiml\ISraixService
{
function __construct()
{
}
function Process(String $text, $attributes, \Aiml\RequestProcess $RequestProcess)
{
return true;
}
}

View File

@@ -0,0 +1,49 @@
<?php
use \Aiml;
namespace CamsAI\SraixServices;
class PolkitInterop implements \Aiml\ISraixService
{
private $authority;
private $subject;
private $identity;
function __construct()
{
$system_name = php_uname('s');
if($system_name == "Linux")
{
$this->authority = Authority::get_sync(null, null);
$this->subject = new Subject();
$this->subject->set_unix_user(getmyuid());
$this->identity = Identity::from_unix_user(getmyuid());
} else {
//throw new Exception("This system does not support PolicyKit.");
}
}
function Process(String $text, $attributes, \Aiml\RequestProcess $RequestProcess)
{
$text = explode($text, "=:=");
switch($text[0])
{
case "chpasswd":
var_dump($RequestProcess);
var_dump($text);
var_dump($attributes);
die("Debug Only");
$passwords = Variant::new("(ss)", $oldpassword, $newpasswd);
$result = $authority->chpasswd($identity, $passwords, ['SHA512'], $subject, Authority::CHECK_AUTHORIZATION_FLAGS_ALLOW_USER_INTERACTION, null);
if ($result->get_is_authorized()) {
return "I have successfully updated your system password.";
} else {
$error = $result->get_error();
if ($error !== null) {
throw new Exception("Polkit ran into an error: $error");
}
}
}
}
}

View File

@@ -0,0 +1,63 @@
<?php
use \Aiml;
use \lfischer\openWeatherMap\API;
use lfischer\openWeatherMap\RequestAdapter\Curl;
namespace CamsAI\SraixServices;
class Weather implements \Aiml\ISraixService
{
function __construct()
{
}
function Process(String $text, $attributes, \Aiml\RequestProcess $RequestProcess)
{
$Location = $RequestProcess->User->Predicates['Location'];
$APIKey = $RequestProcess->Bot->Properties['OWM-API'];
$Country = $RequestProcess->User->Predicates['Country'] ?: "United States";
$Location = $Location." ".$Country;
switch($text)
{
case "CURRENT TEMPERATURE":
$weather = (new \lfischer\openWeatherMap\API($APIKey))
->getCurrentWeather()
->setMode(\lfischer\openWeatherMap\Parameter\Mode::JSON)
->setUnit(\lfischer\openWeatherMap\Parameter\Unit::IMPERIAL)
->setLanguage(\lfischer\openWeatherMap\Parameter\Language::ENGLISH)
->byCityName($Location);
var_dump($weather);
return;
break;
case "CURRENT WEATHER":
$weather = (new \lfischer\openWeatherMap\API($APIKey))
->setRequestAdapter(new \lfischer\openWeatherMap\RequestAdapter\Curl())
->getCurrentWeather()
->setMode(\lfischer\openWeatherMap\Parameter\Mode::JSON)
->setUnit(\lfischer\openWeatherMap\Parameter\Unit::IMPERIAL)
->setLanguage(\lfischer\openWeatherMap\Parameter\Language::ENGLISH)
->byCityName($Location);
var_dump($weather);
return;
break;
case "CURRENT FORECAST":
$weather = (new \lfischer\openWeatherMap\API($APIKey))
->setRequestAdapter(new \lfisher\openWeatherMap\RequestAdapter\Curl())
->getDailyForecast()
->setMode(\lfischer\openWeatherMap\Parameter\Mode::JSON)
->setUnit(\lfischer\openWeatherMap\Parameter\Unit::IMPERIAL)
->setLanguage(\lfischer\openWeatherMap\Parameter\Language::ENGLISH)
->byCityName($Location);
var_dump($weather);
return;
$Forecast = "The forecast for ". $weatherForecast->time->day() ." is ". $weatherForecast->description->__toString() . " with a high of ". $weatherForecast->temperature->max->__toString() . " and a low of ". $weatherForecast->temperature->min->__toString().".";
return $Forecast;
break;
}
}
}

10
todo.txt Normal file
View File

@@ -0,0 +1,10 @@
2023-03-01 Write default OOB parse logic and tag support.
2023-03-01 Write method to import extra AIML documents on top of main brain.
2023-03-01 Save user/bot predicates on every request, restore on AI bootup.
2023-03-01 Write event system to send events to the AI modules.
2023-03-01 Write Maintenance AI to manage the system and update AI predicates with system information. +MaintAI
2023-03-01 Write todo.txt management support @Optional @OoS
2023-03-01 Write OOB Plugin System @OoS @Optional
2023-03-01 Add more scripting support than simply JavaScript. Perhaps in an SraiX service to avoid bloating the engine further. @OoS @Optional
2023-03-01 Add JoinAPI tag support to allow the AI to send commands to Android devices using Tasker and Join.
2023-03-01 Write crontab-like scheduler for the maintenance AI to fire events/commands at the Maintenance AI from schedule. +MaintAI