Initial commit of current engine library state.
This commit is contained in:
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
composer.lock
|
||||
bin/
|
||||
obj/
|
||||
vendor/
|
||||
32
CamsAIEngine.msbuildproj
Executable file
32
CamsAIEngine.msbuildproj
Executable 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
19
composer.json
Executable 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
52
src/CamsAI/CamSensory.class.php
Executable 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
169
src/CamsAI/Engine.class.php
Executable 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);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
18
src/CamsAI/SraiXServices/HomeAssistant.SraiX.php
Executable file
18
src/CamsAI/SraiXServices/HomeAssistant.SraiX.php
Executable 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;
|
||||
}
|
||||
|
||||
}
|
||||
49
src/CamsAI/SraiXServices/PolkitInterop.SraiX.php
Executable file
49
src/CamsAI/SraiXServices/PolkitInterop.SraiX.php
Executable 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
63
src/CamsAI/SraiXServices/Weather.SraiX.php
Executable file
63
src/CamsAI/SraiXServices/Weather.SraiX.php
Executable 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
10
todo.txt
Normal 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
|
||||
Reference in New Issue
Block a user