124 lines
4.5 KiB
PHP
124 lines
4.5 KiB
PHP
<?php
|
|
/**
|
|
* ambre-internal-memory.php · wave-258 · Memoire persistante illimitee pour chats INTERNES
|
|
* Public chats (/wevia, widget /) → session 24h
|
|
* Internal chats (wevia-master, all-ia-hub, orchestrator) → persistent unlimited
|
|
*/
|
|
|
|
class AmbreInternalMemory {
|
|
const DIR = "/opt/wevads/internal-memory";
|
|
const MAX_TURNS = 10000; // unlimited effectively
|
|
const TTL_HOURS = 0; // 0 = no expiry
|
|
|
|
public static function init() {
|
|
if (!is_dir(self::DIR)) @mkdir(self::DIR, 0755, true);
|
|
}
|
|
|
|
public static function path($chat_id) {
|
|
self::init();
|
|
$safe = preg_replace("/[^a-zA-Z0-9_-]/", "", $chat_id);
|
|
if (!$safe) $safe = "default";
|
|
return self::DIR . "/" . $safe . ".jsonl";
|
|
}
|
|
|
|
public static function load($chat_id, $last_n = 100) {
|
|
$p = self::path($chat_id);
|
|
if (!file_exists($p)) return [];
|
|
$lines = @file($p, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
|
if (!$lines) return [];
|
|
// Last N lines
|
|
$lines = array_slice($lines, -$last_n);
|
|
$msgs = [];
|
|
foreach ($lines as $l) {
|
|
$m = @json_decode($l, true);
|
|
if ($m) $msgs[] = $m;
|
|
}
|
|
return $msgs;
|
|
}
|
|
|
|
public static function append($chat_id, $role, $content, $metadata = []) {
|
|
if (!$chat_id || !$role || !$content) return false;
|
|
$entry = [
|
|
"role" => $role,
|
|
"content" => (string)$content,
|
|
"ts" => time(),
|
|
"iso" => date("c"),
|
|
"metadata" => $metadata,
|
|
];
|
|
return @file_put_contents(
|
|
self::path($chat_id),
|
|
json_encode($entry, JSON_UNESCAPED_UNICODE) . "\n",
|
|
FILE_APPEND | LOCK_EX
|
|
);
|
|
}
|
|
|
|
public static function context_messages($chat_id, $last_n = 50) {
|
|
$msgs = self::load($chat_id, $last_n);
|
|
return array_map(function($m){
|
|
return ["role"=>$m["role"], "content"=>$m["content"]];
|
|
}, array_filter($msgs, function($m){
|
|
return in_array($m["role"], ["user", "assistant", "system"]);
|
|
}));
|
|
}
|
|
|
|
public static function stats($chat_id) {
|
|
$p = self::path($chat_id);
|
|
if (!file_exists($p)) return ["exists"=>false, "turns"=>0, "size"=>0];
|
|
$lines = @file($p, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
|
return [
|
|
"exists" => true,
|
|
"turns" => count($lines ?: []),
|
|
"size_bytes" => filesize($p),
|
|
"path" => $p,
|
|
"first" => ($lines && $lines[0]) ? @json_decode($lines[0], true)["iso"] ?? "?" : "?",
|
|
"last" => ($lines && end($lines)) ? @json_decode(end($lines), true)["iso"] ?? "?" : "?",
|
|
];
|
|
}
|
|
|
|
public static function list_chats() {
|
|
self::init();
|
|
$out = [];
|
|
foreach (glob(self::DIR . "/*.jsonl") as $f) {
|
|
$bn = basename($f, ".jsonl");
|
|
$lines = @file($f, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
|
|
$out[] = [
|
|
"chat_id" => $bn,
|
|
"turns" => count($lines ?: []),
|
|
"size_kb" => round(filesize($f)/1024, 1),
|
|
"mtime" => date("c", filemtime($f)),
|
|
];
|
|
}
|
|
return $out;
|
|
}
|
|
}
|
|
|
|
// If called directly via HTTP, act as API
|
|
if (php_sapi_name() !== "cli" && basename($_SERVER["SCRIPT_FILENAME"] ?? "") === "ambre-internal-memory.php") {
|
|
header("Content-Type: application/json; charset=utf-8");
|
|
$raw = file_get_contents("php://input");
|
|
$in = json_decode($raw, true) ?: $_GET;
|
|
$action = $in["action"] ?? "stats";
|
|
$chat_id = $in["chat_id"] ?? "";
|
|
|
|
switch ($action) {
|
|
case "append":
|
|
$result = AmbreInternalMemory::append($chat_id, $in["role"] ?? "user", $in["content"] ?? "", $in["metadata"] ?? []);
|
|
echo json_encode(["ok"=>(bool)$result, "written"=>$result]);
|
|
break;
|
|
case "load":
|
|
echo json_encode(["ok"=>true, "messages"=>AmbreInternalMemory::load($chat_id, intval($in["n"] ?? 100))]);
|
|
break;
|
|
case "context":
|
|
echo json_encode(["ok"=>true, "messages"=>AmbreInternalMemory::context_messages($chat_id, intval($in["n"] ?? 50))]);
|
|
break;
|
|
case "stats":
|
|
echo json_encode(["ok"=>true, "stats"=>AmbreInternalMemory::stats($chat_id)]);
|
|
break;
|
|
case "list":
|
|
echo json_encode(["ok"=>true, "chats"=>AmbreInternalMemory::list_chats()]);
|
|
break;
|
|
default:
|
|
echo json_encode(["error"=>"unknown action. Use: append|load|context|stats|list"]);
|
|
}
|
|
}
|