Compare commits

..

32 Commits
v0.4 ... master

Author SHA1 Message Date
8c36816800
(Re-)Enable Agent Build 2025-02-12 11:59:41 +01:00
c73d6c3967
Prevent Agent-Image from rebuild
All checks were successful
Build and push Docker images on git tags / build (push) Successful in 30m57s
2025-02-12 11:15:16 +01:00
ee95b67a83
Add Shared Files Listing to Management 2025-02-12 11:14:20 +01:00
536d90d5e6
Update docs after implement #4
All checks were successful
Build and push Docker images on git tags / build (push) Successful in 29m53s
2024-12-21 19:01:02 +01:00
42a4449472
Implement #4 2024-12-21 18:57:39 +01:00
4e98292160
Fix Push Script
All checks were successful
Build and push Docker images on git tags / build (push) Successful in 38s
2024-11-20 13:08:28 +01:00
aae167cf11
Fix DB issues with Python 3.12
All checks were successful
Build and push Docker images on git tags / build (push) Successful in 40m1s
2024-11-20 12:03:38 +01:00
cc4bb9a7e8
Fix #1
All checks were successful
Build and push Docker image at git tag / build (push) Successful in 55s
2024-10-31 16:25:37 +01:00
e7910021dd
Fix #2 2024-10-31 15:14:52 +01:00
784488e05b
Add single task 2024-10-30 21:11:36 +01:00
f2f9819d27
Schema Idea
All checks were successful
Build and push Docker image at git tag / build (push) Successful in 44s
2024-10-30 21:07:54 +01:00
786a230e78
Run single tasks 2024-10-30 20:24:12 +01:00
f2b9df7611
Py Access to Management 2024-10-30 19:27:56 +01:00
cfe3dbd5bb
Access Messages via API from Python 2024-10-30 18:02:05 +01:00
01db00b3b4
More Optim. 2024-10-30 16:10:53 +01:00
53bc4ac219
Optim. Repo Structure 2024-10-30 15:32:08 +01:00
414c18ef08
Finally fix push GPU image
All checks were successful
Build and push Docker image at git tag / build (push) Successful in 38s
2024-10-30 15:15:25 +01:00
419eb97916
Fix Image Push
All checks were successful
Build and push Docker image at git tag / build (push) Successful in 39s
2024-10-30 15:07:51 +01:00
b38acc1f0f
Try to fix push error
All checks were successful
Build and push Docker image at git tag / build (push) Successful in 37s
2024-10-30 15:04:39 +01:00
3fb3602163
Update Docs 2024-10-30 00:01:49 +01:00
63784119d2
Update Docs
All checks were successful
Build and push Docker image at git tag / build (push) Successful in 38m31s
2024-10-29 23:58:46 +01:00
533b9fed6d
Agent should work 2024-10-29 23:57:04 +01:00
17d96cd069
Basic MGMT should work 2024-10-29 18:09:27 +01:00
98198f105b
Update Docs 2024-10-29 16:51:37 +01:00
fac784e013
Management Message Processing 2024-10-29 16:47:58 +01:00
04ccd488f8
Web Interface ok 2024-10-29 15:22:32 +01:00
86adf41308
New Riddle (w/o Data!!) 2024-10-09 20:48:06 +02:00
6de994626b
Update Docs 2024-10-09 19:04:28 +02:00
5e0945f9ae
Accept Messages 2024-10-09 19:04:19 +02:00
4199b1c347
Table works 2024-10-09 15:13:40 +02:00
a4d0803d20
Basic Table
All checks were successful
Build and push Docker image at git tag / build (push) Successful in 1m44s
2024-10-08 21:00:14 +02:00
e376956def
Fix DB && Logs to Stdout in Docker
All checks were successful
Build and push Docker image at git tag / build (push) Successful in 1m54s
2024-10-08 14:11:57 +02:00
72 changed files with 11635 additions and 1373 deletions

View File

@ -1,4 +1,4 @@
name: Build and push Docker image at git tag
name: Build and push Docker images on git tags
on:
push:
tags:
@ -24,8 +24,8 @@ jobs:
- name: Build the Management
run: bash ./build-mgmt.sh -no-updates
#- name: Build the Agent
# run: bash ./build-agent.sh -no-updates
- name: Build the Agent
run: bash ./build-agent.sh -no-updates
- name: Docker login
uses: docker/login-action@v3

2
.gitignore vendored
View File

@ -1,7 +1,9 @@
__pycache__
# data of containers
/data/*
# ignore local venv
/bin/
/lib/
/include/

View File

@ -1,25 +1,39 @@
> [!NOTE]
> In diesem Repository befinden sich die Implementierung des Management und der Agenten-Plattform. Sowie Skripte zur Erstellung der Docker-Images.
> [!WARNING]
> Um die Plattform zu benutzen, bitte das [Agent-Template](https://git.chai.uni-hamburg.de/UMS-Agenten/Agent-Template) benutzen!
# Agenten-Plattform
## Management
- `./docker-mgmt/`
- `./ums/management/`
- `./web/`
- `./build-mgmt.sh`
Verzeichnisse insb.:
- `./utils/mgmt/` Docker container configs
- `./ums/management/` Python source
- `./web/` Jinja templates and web root
- `./build-mgmt.sh` Container build script
## Basic Agent
- `./docker-agent/`
- `./ums/agent/`
Verzeichnisse insb.:
- `./utils/agent/` Docker container configs
- `./ums/agent/` Python source
- `./build-agent.sh` Container build script
## Development
### Run via Docker
- `docker compose up`
### VS Code Autocomplete ...
### CLI Examples
- Requests to management
- `docker compose exec management python -m ums.example` (runs file `ums/example/__main__.py`)
- Run single task in agent
- `docker compose exec agent_all python -m ums.agent -h`
### VS Code Autocomplete
(In VS Code)
- `python3 -m venv .` (only once)
- `source ./bin/activate`
- `pip install requests fastapi pdoc` (only once)

50
build-agent.sh Executable file
View File

@ -0,0 +1,50 @@
#/bin/bash
# Agenten Plattform
#
# (c) 2024 Magnus Bender
# Institute of Humanities-Centered Artificial Intelligence (CHAI)
# Universitaet Hamburg
# https://www.chai.uni-hamburg.de/~bender
#
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
# https://stackoverflow.com/a/4774063
SCRIPTPATH="$(cd -- "$(dirname "$0")" >/dev/null 2>&1; pwd -P)"
source "$SCRIPTPATH/vars.sh"
requirements="requirements-frozen.txt"
if [ "$1" != "-no-updates" ]; then
echo "Update the depencendies in requirements.txt? [may break app] (y/n)"
read newlockfile
if [ "$newlockfile" == "y" ]; then
requirements="requirements.txt"
fi;
fi;
for platform in $PLATFORMS; do
if [ "$platform" == "gpu" ]; then
platform="amd64"
tag="gpu-amd64"
else
tag="cpu-$platform"
fi;
docker build \
--pull \
--platform "linux/$platform" \
--file "$SCRIPTPATH/utils/agent/Dockerfile" \
--build-arg FROM_IMAGE="$IMAGE_REGISTRY/$IMAGE_OWNER/$IMAGE_AGENT_BASE:$tag" \
--build-arg PIP_REQ_FILE="$requirements" \
--tag "$IMAGE_REGISTRY/$IMAGE_OWNER/$IMAGE_NAME_AGENT:$tag" \
"$SCRIPTPATH"
done;
if [ "$requirements" == "requirements.txt" ]; then
# extract requirements-frozen.txt
cid=$(docker create "$IMAGE_REGISTRY/$IMAGE_OWNER/$IMAGE_NAME_AGENT:cpu-arm64")
docker cp "$cid:/ums-agenten/requirements-frozen.txt" "$SCRIPTPATH/utils/agent/requirements-frozen.txt"
docker rm "$cid"
fi;

View File

@ -29,7 +29,7 @@ for platform in $PLATFORMS; do
docker build \
--pull \
--platform "linux/$platform" \
--file "$SCRIPTPATH/docker-mgmt/Dockerfile" \
--file "$SCRIPTPATH/utils/mgmt/Dockerfile" \
--build-arg H_UID=1050 \
--build-arg PIP_REQ_FILE="$requirements" \
--build-arg H_GID=1050 \
@ -41,6 +41,6 @@ done;
if [ "$requirements" == "requirements.txt" ]; then
# extract requirements-frozen.txt
cid=$(docker create "$IMAGE_REGISTRY/$IMAGE_OWNER/$IMAGE_NAME_MGMT:arm64")
docker cp "$cid:/ums-agenten/requirements.txt" "$SCRIPTPATH/docker-mgmt/requirements-frozen.txt"
docker cp "$cid:/ums-agenten/requirements.txt" "$SCRIPTPATH/utils/mgmt/requirements-frozen.txt"
docker rm "$cid"
fi;

View File

@ -19,9 +19,14 @@ services:
ports:
- 8000:80
environment:
- AGENTS_PROCESS=http://agent_process_1:3001,http://agent_process_2:3001
- AGENTS_SOLVE=http://agent_solve_1:3001
- AGENTS_GATEKEEPER=http://agent_gatekeeper_1:3001
- SOLUTION_MAX_TRIALS=5
- MESSAGE_MAX_CONTACTS=100
- REQUIRE_FULL_EXTRACT=true
- REQUIRE_FULL_SOLVE=true
- MANAGEMENT_URL=http://management
- AGENTS_PROCESS=http://agent_all:8000
- AGENTS_SOLVE=http://agent_all:8000
- AGENTS_GATEKEEPER=http://agent_all:8000
volumes:
- ./data/share/:/ums-agenten/share/
- ./data/persist-management/:/ums-agenten/persist/
@ -31,3 +36,21 @@ services:
# enable auto reloading (for development)
entrypoint: bash -c "nginx; SERVE=true uvicorn ums.management.main:app --uds /tmp/uvicorn.sock --proxy-headers --reload"
agent_all:
image: git.chai.uni-hamburg.de/ums-agenten/base-agent:cpu-arm64
#image: git.chai.uni-hamburg.de/ums-agenten/base-agent:cpu-amd64
#image: git.chai.uni-hamburg.de/ums-agenten/base-agent:gpu-amd64
ports:
- 8001:8000
environment:
- AGENTS_LIST=ums.example.example:AGENT_CLASSES
- MANAGEMENT_URL=http://management
volumes:
- ./data/share/:/ums-agenten/share/
- ./data/persist-all/:/ums-agenten/persist/
# bind code from host to container (for development)
- ./ums/:/ums-agenten/plattform/ums/:ro
- ./web/:/ums-agenten/plattform/web/
# enable auto reloading (for development)
entrypoint: bash -c "SERVE=true uvicorn ums.agent.main:app --host 0.0.0.0 --port 8000 --reload"

View File

@ -10,7 +10,7 @@
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
pdoc ./ums/ \
pdoc ./ums/ ./ums/example/__main__.py \
--output-directory ./web/public/docs/ \
--no-browser \
--docformat google \

View File

@ -20,14 +20,15 @@ day_tag=$(date '+%Y-%m-%d')
images_a=$(docker image ls "$IMAGE_REGISTRY/$IMAGE_OWNER/$IMAGE_NAME_AGENT" --format '{{.Repository}}:{{.Tag}}')
images_b=$(docker image ls "$IMAGE_REGISTRY/$IMAGE_OWNER/$IMAGE_NAME_MGMT" --format '{{.Repository}}:{{.Tag}}')
echo "$images_a\n$images_b" | while read image_url ;
echo "$images_a
$images_b" | while read image_url ;
do
image_name="${image_url##*/}"
image_name="${image_name%%:*}"
image_tag="${image_url##*:}"
if [[ "$image_tag" =~ ^((gpu)|(cpu)-)?((arm64)|(amd64))$ ]];
if [[ "$image_tag" =~ ^((gpu-)|(cpu-))?((arm64)|(amd64))$ ]];
then
echo "Push:"

View File

@ -6,4 +6,29 @@
# https://www.chai.uni-hamburg.de/~bender
#
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
# https://www.gnu.org/licenses/gpl-3.0.txt
"""
The package `ums` contains the Agenten-Plattform, the implementations of the agents shall be created in the package `src`, see [Agent-Template](https://git.chai.uni-hamburg.de/UMS-Agenten/Agent-Template).
> Side note: The classes with comments may be useful when implementing the agents.
> The classes without comments may be safe to ignore and are (only) used internally.
- `ums.agent`
- Contains the implementation of an agent for handling requests by the implementations in `src`.
- Check for running single tasks without using management.
- `ums.example`
- Contains a very simple examples for all types of agents.
- See `ums.example.example`
- `ums.management`
- Contains the implementation of the management.
- Take a look at the web gui of the management, possibly at <http://localhost:8080/> or <http://localhost:8000/>
- `ums.utils`
- Contains various utilities.
- `ums.utils.const.SHARE_PATH` The path for shared files between all agents
- `ums.utils.const.PERSIST_PATH` The path to store persistent data of an agent
- `ums.utils.request.ManagementRequest` Run request to the management (only necessary in special cases, most requests done automatically by platform)
- `ums.utils.schema` The schema (types) used in the files storing extracted data from plain data
- `ums.utils.types` The types used in the communication between agent and management
"""

View File

@ -6,4 +6,48 @@
# https://www.chai.uni-hamburg.de/~bender
#
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
# https://www.gnu.org/licenses/gpl-3.0.txt
"""
## Run as Agent
The env. variable `AGENTS_LIST` is used to identify the agents classes/ task handlers.
It must contain he the package name and a variable name in this package divided by `:`.
Then, the variable contains a list of agent classes (subclasses of `ums.agent.agent.BasicAgent`)
For example `AGENTS_LIST=ums.example.example:AGENT_CLASSES`, then in file `./ums/example/example.py` a variable `AGENT_CLASSES` exists.
One line in this file, e.g., is `AGENT_CLASSES = [MyExtractAudioAgent, MyExtractImageAgent]`.
When starting the Docker container of the agent, the classes specified in `AGENTS_LIST` are loaded and if the agent receives a task, the task is sent to the agent classes' `handle` methods.
## Run Single Task
For development it might be cumbersome to always require a running management container and sending messages.
Hence, tasks can be run manually from the terminal (still in the container and using the agent classes), but without having a management.
This also uses the `AGENTS_LIST` env. variable, but the tasks are sent via command line:
There are three ways to send a task (if the agent's Docker container is running):
- `docker compose exec agent_all python -m ums.agent -d`
- Run a dummy task
- Possibly `agent_all` needs to be changed to the service name (see `docker-compose.yml`) of the agent's Docker container
- `cat ./msg.json | docker compose exec -T agent_all python -m ums.agent -i`
- Send the task (json of `AgentMessage`) via STDIN from file `./msg.json` to the agent
- `docker compose exec agent_all python -m ums.agent -f msg.json`
- Get the task from the json file, the files are searched for by full name, in the shared, and the persistent directory.
If the Agent's Docker container is not running, a temporary container can be started.
For the dummy message, the command would be `docker compose run --rm --entrypoint "" agent_all python -m ums.agent -d`.
(Again, change `agent_all` for the service name in `docker-compose.yml`.)
"""
from ums.agent.agent import (
AgentCapability,
BasicAgent,
ExtractAgent,
ExtractAudioAgent, ExtractImageAgent, ExtractTextAgent,
SolveAgent,
GatekeeperAgent
)

65
ums/agent/__main__.py Normal file
View File

@ -0,0 +1,65 @@
# Agenten Plattform
#
# (c) 2024 Magnus Bender
# Institute of Humanities-Centered Artificial Intelligence (CHAI)
# Universitaet Hamburg
# https://www.chai.uni-hamburg.de/~bender
#
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
import argparse, sys, os, json
from ums.agent.process import MessageProcessor
from ums.utils import AgentMessage, Riddle, SHARE_PATH, PERSIST_PATH
class _FakeBackgroundTask():
def add_task(self, call, *args):
call(*args)
if __name__ == "__main__":
parser = argparse.ArgumentParser(description='Agenten Plattform Run Single Task')
parser.add_argument('-f', '--file', help="fetch the message (riddle) from this json file")
parser.add_argument('-d', '--dummy', help="use a dummy message (riddle)", action="store_true")
parser.add_argument('-i', '--stdin', help="get the message (riddle) from STDIN", action="store_true")
args = parser.parse_args()
message = None
if args.dummy:
message = AgentMessage(
id="dummy",
riddle=Riddle(context="Its a dummy.", question="No question!")
)
message.status.extract.required = False
elif args.stdin:
text = ''.join(sys.stdin.readlines())
message = AgentMessage.model_validate_json(text)
elif args.file:
if os.path.isfile(args.file):
f_name = args.file
elif os.path.isfile(os.path.join(SHARE_PATH, args.file)):
f_name = os.path.join(SHARE_PATH, args.file)
elif os.path.isfile(os.path.join(PERSIST_PATH, args.file)):
f_name = os.path.join(PERSIST_PATH, args.file)
else:
print()
print(f"\tFile {args.file} not found!")
print()
f_name = None
if not f_name is None:
message = AgentMessage.model_validate(
json.load(open(f_name, 'r'))
)
if message is None:
parser.print_help()
else:
mp = MessageProcessor(disable_messages=True)
response = mp.new_message(message, _FakeBackgroundTask())
print("\tResponse:")
print(response.model_dump_json(indent=2))

326
ums/agent/agent.py Normal file
View File

@ -0,0 +1,326 @@
# Agenten Plattform
#
# (c) 2024 Magnus Bender
# Institute of Humanities-Centered Artificial Intelligence (CHAI)
# Universitaet Hamburg
# https://www.chai.uni-hamburg.de/~bender
#
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
import random, os, json, time
from abc import abstractmethod, ABC
from enum import Enum
from typing import List, Callable
from pydantic import validate_call
from ums.utils import (
RiddleInformation, AgentMessage, RiddleDataType, RiddleData, Riddle,
RiddleStatus, RiddleSolution,
ExtractedData,
logger
)
class AgentCapability(Enum):
"""
The three different capabilities an agent can have.
"""
EXTRACT="extract"
SOLVE="solve"
GATEKEEPER="gatekeeper"
class BasicAgent(ABC):
"""
A basic agent, each agent will be a subclass of this class.
"""
@staticmethod
@abstractmethod
def agent_capability() -> AgentCapability:
"""
Represents the capabilities of this agent, for messages/ tasks of this capability, the `handle` method will be called.
"""
pass
@validate_call
def __init__(self, message:AgentMessage, send_message:Callable[[AgentMessage], bool]):
self._send_message = send_message
self._sub_cnt = 0
self._message = message
self._response = message.model_copy(deep=True)
self._do_response = False
self._process()
self._respond()
@abstractmethod
def _process(self):
pass
def _respond(self):
# do a very short sleep
time.sleep(random.random())
# sending
send_it = lambda: self._send_message(self._response)
if self.before_response(self._response, send_it) and self._do_response:
send_it()
logger.debug(f"Response sent {self._response.id}")
else:
logger.debug(f"Stopped response {self._response.id}")
@validate_call
def before_response(self, response:AgentMessage, send_it:Callable[[], None]) -> bool:
"""
This method is called before the response is sent.
If the method returns `False` no response will be sent.
Thus, by overwriting this method, a response can be prevented.
The response to be sent is in `response` and `send_it` is a callable, which sends the response to the management if it gets called.
(Hence, one may stop sending the response and later call `send_it()` to send the response.)
"""
return True
@validate_call
def message(self) -> AgentMessage:
"""
Get the message this agent object is working on.
"""
return self._message;
@validate_call
def sub_riddle(self,
riddle:Riddle, data:List[RiddleData]=[], status:RiddleStatus=None
) -> AgentMessage|bool:
"""
Create a new sub-riddle for solving details of the current riddle.
For the sub-riddle, give a `riddle` and optionally, a selection of `data` items (default none) and a `status` (default `ums.utils.types.RiddleStatus()`).
By changing a status, different steps can be (de-)selected.
Return the message of the sub-riddle or `false` on error.
"""
if status is None:
status = RiddleStatus()
# new sub riddle id
self._sub_cnt += 1
new_id = "{}-sub-{}.{}".format(self._message.id, self._sub_cnt, int(random.random()*100))
self._message.sub_ids.append(new_id)
self._response.sub_ids.append(new_id)
# create the riddle's message
sub_msg = AgentMessage(
id=new_id,
riddle=riddle,
data=data,
status=status
)
logger.debug(f"Created sub-riddle {sub_msg.id}")
# send it
if self._send_message(sub_msg):
return sub_msg
else:
return False
@abstractmethod
def handle(self, *args:RiddleInformation) -> RiddleInformation:
"""
Handle a single task of the agent, the arguments and return value depends on the actual task (see subclass)!
**This is the method to implement!**
The full message is available via `message()`, a sub riddle can be created with `sub_riddle()`.
"""
pass
@validate_call
def get_extracted(self, data:RiddleData) -> ExtractedData|None:
"""
Loads the extracted data from the `data` item (i.e., from the file `data.file_extracted`).
Returns None if no extracted data found.
"""
if not data.file_extracted is None:
return ExtractedData.model_validate(
json.load(open(data.file_extracted, 'r'))
)
return None
class ExtractAgent(BasicAgent):
"""
An extraction agent.
"""
def agent_capability() -> AgentCapability:
return AgentCapability.EXTRACT
@staticmethod
@abstractmethod
def extract_type() -> RiddleDataType:
"""
Represents the data this agent can process.
"""
pass
def _process(self):
for i, data in enumerate(self._response.data):
if data.type == self.__class__.extract_type():
logger.debug(f"Start extraction '{data.file_plain}'")
result = self.handle(data)
logger.debug(f"End extraction '{data.file_plain}' ('{result.file_extracted}')")
if result.file_extracted is None:
logger.info(f"Riddle {self._response.id}: 'file_extracted' for data '{data.file_plain}' still empty after handling")
self._response.data[i] = result
self._do_response = True
self._response.status.extract.finished = True
@abstractmethod
@validate_call
def handle(self, data:RiddleData) -> RiddleData:
"""
Process the item `data`, create extraction file and return `data` with populated `data.file_extracted`.
"""
@validate_call
def store_extracted(self, data:RiddleData, extracted:ExtractedData, allow_overwrite:bool=True) -> str:
"""
Stores the newly extracted data (in `extracted`) from `data` (i.e., `data.file_plain`)
and returns the filename to use in `data.file_extracted`.
If there already exists an extracted file for this `data`, the file will be overwritten if `allow_overwrite=True`.
Generally the system will check, if the contents of the current file are equal to the contents to write.
File with equal content will not be written again.
"""
# get path and name
path_name = data.file_plain[:data.file_plain.rfind('.')]
candidate = "{}.json".format(path_name)
# data to write
data = extracted.model_dump_json()
# check for file
if os.path.isfile(candidate):
# get current content
with open(candidate, 'r') as f:
content = f.read()
# files equal -> no need to rewrite
if content == data:
return candidate
# not equal and overwrite not allowed
elif not allow_overwrite:
# get non-existent file name
cnt = 0
while os.path.isfile(candidate):
cnt += 1
candidate = "{}-{}.json".format(path_name, cnt)
# write file
with open(candidate, 'w+') as f:
f.write(data)
return candidate
class ExtractTextAgent(ExtractAgent):
"""
An extraction agent for text, create a subclass for your agent.
"""
def extract_type() -> RiddleDataType:
return RiddleDataType.TEXT
class ExtractAudioAgent(ExtractAgent):
"""
An extraction agent for audio, create a subclass for your agent.
"""
def extract_type() -> RiddleDataType:
return RiddleDataType.AUDIO
class ExtractImageAgent(ExtractAgent):
"""
An extraction agent for images, create a subclass for your agent.
"""
def extract_type() -> RiddleDataType:
return RiddleDataType.IMAGE
class SolveAgent(BasicAgent):
"""
A solve agent, create a subclass for your agent.
"""
def agent_capability() -> AgentCapability:
return AgentCapability.SOLVE
def _process(self):
logger.debug(f"Start solve: {self._response.id}")
solution = self.handle(self._response.riddle, self._response.data)
logger.debug(f"End solve: {self._response.id} ({solution.solution}, {solution.explanation})")
if len(solution.solution) == 0 or len(solution.explanation) == 0:
logger.info(f"Riddle {self._response.id}: Empty solution/ explanation after handling")
self._response.solution.append(solution)
self._response.status.solve.finished = True
self._do_response = True
@abstractmethod
@validate_call
def handle(self, riddle: Riddle, data: List[RiddleData]) -> RiddleSolution:
"""
Solve the `riddle` using `data` and return a single solution.
"""
class GatekeeperAgent(BasicAgent):
"""
A gatekeeper agent, create a subclass for your agent.
"""
def agent_capability() -> AgentCapability:
return AgentCapability.GATEKEEPER
def _process(self):
if len(self._response.solution) == 0:
self._response.solution.append(RiddleSolution(solution="", explanation=""))
logger.debug(f"Start validate: {self._response.id}")
solution = self.handle(self._response.solution, self._response.riddle)
for single_solution in solution:
logger.debug(f"End validate: {self._response.id} ({single_solution.review}, {single_solution.accepted})")
if single_solution.review is None or len(single_solution.review) == 0:
logger.info(f"Riddle {self._response.id}: Empty review after handling")
self._response.solution = solution
self._response.status.validate.finished = True
self._response.status.solved = any(single_solution.accepted for single_solution in solution)
self._do_response = True
@abstractmethod
@validate_call
def handle(self, solution:List[RiddleSolution], riddle:Riddle) -> List[RiddleSolution]:
"""
Check the `solution` (multiple if multiple solver involved) of `riddle` and return solutions with populated `solution[i].accepted` and `solution[i].review`.
"""

65
ums/agent/main.py Normal file
View File

@ -0,0 +1,65 @@
# Agenten Plattform
#
# (c) 2024 Magnus Bender
# Institute of Humanities-Centered Artificial Intelligence (CHAI)
# Universitaet Hamburg
# https://www.chai.uni-hamburg.de/~bender
#
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
import os
from fastapi import FastAPI, Request, BackgroundTasks
from fastapi.staticfiles import StaticFiles
from fastapi.responses import JSONResponse
from ums.agent.process import MessageProcessor
from ums.utils import AgentMessage, AgentResponse, const
class WebMain():
def __init__(self):
self.msg_process = MessageProcessor()
self._init_app()
self._add_routes()
def _init_app(self):
self.app = FastAPI(
title="Agenten Plattform",
description="Agenten Plattform Agent",
openapi_url="/api/schema.json",
docs_url='/api',
redoc_url=None
)
self.app.mount(
"/static",
StaticFiles(directory=os.path.join(const.PUBLIC_PATH, 'static')),
name="static"
)
self.app.mount(
"/docs",
StaticFiles(directory=os.path.join(const.PUBLIC_PATH, 'docs'), html=True),
name="docs"
)
def _add_routes(self):
@self.app.get("/", response_class=JSONResponse, summary="Link list")
def index():
return {
"title" : "Agenten Plattform Agent",
"./message" : "Messaged from the Management",
"./api" : "API Overview",
"./docs" : "Documentation"
}
@self.app.post("/message", summary="Send a message to this agent")
def message(request: Request, message:AgentMessage, background_tasks: BackgroundTasks) -> AgentResponse:
return self.msg_process.new_message(message, background_tasks)
if __name__ == "ums.agent.main" and os.environ.get('SERVE', 'false').lower() == 'true':
main = WebMain()
app = main.app

100
ums/agent/process.py Normal file
View File

@ -0,0 +1,100 @@
# Agenten Plattform
#
# (c) 2024 Magnus Bender
# Institute of Humanities-Centered Artificial Intelligence (CHAI)
# Universitaet Hamburg
# https://www.chai.uni-hamburg.de/~bender
#
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
import os, importlib
from typing import List
import requests
from fastapi import BackgroundTasks
from ums.agent.agent import BasicAgent, AgentCapability, ExtractAgent, SolveAgent, GatekeeperAgent
from ums.utils import AgentMessage, AgentResponse, logger
class MessageProcessor():
MANAGEMENT_URL = os.environ.get('MANAGEMENT_URL', 'http://127.0.0.1:80').strip().strip('/')
AGENTS_LIST = os.environ.get('AGENTS_LIST', 'ums.example.example:AGENT_CLASSES').strip()
def __init__(self, disable_messages:bool=False):
self.counts = 0
self.disable_messages = disable_messages
module_name, var_name = self.AGENTS_LIST.split(':')
agents_module = importlib.import_module(module_name)
self.agent_classes:List[BasicAgent] = getattr(agents_module, var_name)
self.extract_agents:List[ExtractAgent] = list(filter(
lambda ac: ac.agent_capability() == AgentCapability.EXTRACT,
self.agent_classes
))
self.solve_agents:List[SolveAgent] = list(filter(
lambda ac: ac.agent_capability() == AgentCapability.SOLVE,
self.agent_classes
))
self.gatekeeper_agents:List[GatekeeperAgent] = list(filter(
lambda ac: ac.agent_capability() == AgentCapability.GATEKEEPER,
self.agent_classes
))
def new_message(self, message:AgentMessage, background_tasks: BackgroundTasks) -> AgentResponse:
enqueued = False
if message.status.extract.required and not message.status.extract.finished:
# send to extract agents
if len(self.extract_agents) > 0:
data_types = set( d.type for d in message.data )
for ac in self.extract_agents:
if ac.extract_type() in data_types:
background_tasks.add_task(ac, message, self._send_message)
enqueued = True
elif message.status.solve.required and not message.status.solve.finished:
# send to solve agents
if len(self.solve_agents) > 0:
for sa in self.solve_agents:
background_tasks.add_task(sa, message, self._send_message)
enqueued = True
elif message.status.validate.required and not message.status.validate.finished:
# send to solve agents
if len(self.gatekeeper_agents) > 0:
for ga in self.gatekeeper_agents:
background_tasks.add_task(ga, message, self._send_message)
enqueued = True
logger.debug(
("Added to queue" if enqueued else "No agent found to queue message.") +
f"ID: {message.id} Count: {self.counts}"
)
self.counts += 1
return AgentResponse(
count=self.counts-1,
msg="Added to queue" if enqueued else "",
error=not enqueued,
error_msg=None if enqueued else "No agent found to queue message."
)
def _send_message(self, message:AgentMessage) -> bool:
if not self.disable_messages:
r = requests.post(
"{}/message".format(self.MANAGEMENT_URL),
data=message.model_dump_json(),
headers={"accept" : "application/json", "content-type" : "application/json"}
)
if r.status_code == 200:
return True
else:
logger.warning(f"Error sending message to management! {(r.text, r.headers)}")
return False
else:
print("\tMessages disabled: Requested to send message to management:")
print(message.model_dump_json(indent=2))

60
ums/example/__main__.py Normal file
View File

@ -0,0 +1,60 @@
# Agenten Plattform
#
# (c) 2024 Magnus Bender
# Institute of Humanities-Centered Artificial Intelligence (CHAI)
# Universitaet Hamburg
# https://www.chai.uni-hamburg.de/~bender
#
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
"""
See the source &rarr;
"""
if __name__ == "__main__":
from ums.utils import ManagementRequest
m_request = ManagementRequest()
# get infos from Management
print(
# message number 12
m_request.get_message(count=12)
)
print(
# first two messages of id "test"
m_request.list_messages(id="test", limit=2)
)
print(
# count messages with id "test"
m_request.total_messages(id="test")
)
from ums.utils import AgentMessage, Riddle, RiddleData, RiddleDataType, RiddleSolution
# send messages to management
# basic message
msg = AgentMessage(
id="example",
riddle=Riddle(context="Today is the 1. January 1970", question="What time is it?"),
data=[
RiddleData(
type=RiddleDataType.TEXT,
file_plain="./cv.txt" # make sure this file exists!
)
]
)
# disable some steps
msg.status.extract.required = False
msg.status.validate.required = False
print(
# send the message
m_request.send_message(msg)
)

79
ums/example/example.py Normal file
View File

@ -0,0 +1,79 @@
# Agenten Plattform
#
# (c) 2024 Magnus Bender
# Institute of Humanities-Centered Artificial Intelligence (CHAI)
# Universitaet Hamburg
# https://www.chai.uni-hamburg.de/~bender
#
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
import random
from typing import Callable, List
from ums.agent import ExtractAudioAgent, ExtractImageAgent, ExtractTextAgent, SolveAgent, GatekeeperAgent
from ums.utils import AgentMessage, Riddle, RiddleData, RiddleSolution, RiddleStatus, ExtractedData
"""
Examples for simple agents.
Each agent is represented by its own class. The handling of tasks is done by `handle()` in each agent.
Finally `AGENT_CLASSES` contains the classes of the agents in a list. Via environmental variables this list is specified to the ums.agent system.
"""
class MyExtractAudioAgent(ExtractAudioAgent):
def handle(self, data: RiddleData) -> RiddleData:
print("Audio Process:", data.file_plain)
return data
class MyExtractImageAgent(ExtractImageAgent):
def handle(self, data: RiddleData) -> RiddleData:
print("Image Process:", data.file_plain)
extracted = ExtractedData(other={"info":"just a test"})
data.file_extracted = self.store_extracted(data, extracted)
return data
class MyExtractTextAgent(ExtractTextAgent):
def before_response(self, response: AgentMessage, send_it: Callable[[], None]) -> bool:
print("The response will be:", response)
return True
def handle(self, data: RiddleData) -> RiddleData:
print("Text Process:", data.file_plain)
return data
class MySolveAgent(SolveAgent):
def handle(self, riddle: Riddle, data: List[RiddleData]) -> RiddleSolution:
for d in data:
print(self.get_extracted(d))
if self.message().id == "test":
status = RiddleStatus()
status.extract.required = False
self.sub_riddle(riddle=Riddle(context="Haha", question="Blubber"), status=status)
return RiddleSolution(solution="Huii", explanation=f"Blubb, {random.random()}")
class MyGatekeeperAgent(GatekeeperAgent):
def handle(self, solution: List[RiddleSolution], riddle: Riddle) -> RiddleSolution:
solution[0].accepted = True
solution[0].review = "Ok"
return solution
AGENT_CLASSES = [
MyExtractAudioAgent, MyExtractImageAgent, MyExtractTextAgent,
MySolveAgent,
MyGatekeeperAgent
]

View File

@ -15,44 +15,9 @@ from datetime import datetime
from threading import Lock
from typing import Generator
from pydantic import validate_call, BaseModel
from pydantic import validate_call, ValidationError
from ums.utils import PERSIST_PATH, AgentMessage
class RowObject(BaseModel):
"""
Object representing a database row.
"""
count : int
"""
The count (primary key) of the item.
"""
sender : str
"""
The sender of the message.
"""
recipient : str
"""
The recipient of the message
"""
time : int
"""
The time (unix timestamp) the message was received/ sent.
"""
message : AgentMessage
"""
The message received/ sent.
"""
processed : bool
"""
Did the management process the message, i.e., did the tasks necessary for this message (mostly only relevant for received messages).
"""
from ums.utils import PERSIST_PATH, AgentMessage, MessageDbRow
class DB():
@ -61,17 +26,18 @@ class DB():
def __init__(self):
self.db = sqlite3.connect(
os.path.join(PERSIST_PATH, 'messages.db'),
check_same_thread=False
)
check_same_thread=False,
autocommit=False
)
self.db.row_factory = sqlite3.Row
self.dblock = Lock()
atexit.register(lambda db : db.close(), self.db)
self.db_lock = Lock()
self._assure_tables()
def _assure_tables(self):
self.dblock.acquire()
self.db_lock.acquire()
with self.db:
self.db.execute("""CREATE TABLE IF NOT EXISTS Messages (
count INTEGER PRIMARY KEY AUTOINCREMENT,
@ -80,19 +46,20 @@ class DB():
recipient TEXT,
time TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
json BLOB,
processed BOOL DEFAULT FALSE
processed BOOL DEFAULT FALSE,
solution BOOL DEFAULT NULL
)""")
self.dblock.release()
self.db_lock.release()
@validate_call
def add_message(self, sender:str, recipient:str, message:AgentMessage, processed:bool=False) -> int:
self.dblock.acquire()
def add_message(self, sender:str, recipient:str, message:AgentMessage, processed:bool=False ) -> int:
self.db_lock.acquire()
with self.db:
self.db.execute(
"""INSERT INTO Messages (
id, sender, recipient, json, processed
id, sender, recipient, json, processed
) VALUES (
:id, :sender, :recipient, :json, :processed
:id, :sender, :recipient, :json, :processed
)""", {
"id" : message.id,
"sender" : sender,
@ -101,31 +68,44 @@ class DB():
"processed" : processed
})
new_count = self.db.execute("SELECT LAST_INSERT_ROWID() as last").fetchone()
self.dblock.release()
self.db_lock.release()
return new_count['last']
@validate_call
def set_processed(self, count:int, processed:bool=True) -> bool:
self.dblock.acquire()
self.db_lock.acquire()
with self.db:
try:
self.db.execute("UPDATE Messages SET processed = ? WHERE count = ?", (processed, count))
return True
except:
return False
self.dblock.release()
finally:
self.db_lock.release()
def __iter__(self) -> Generator[RowObject, None, None]:
@validate_call
def set_solution(self, count:int, solution:bool) -> bool:
self.db_lock.acquire()
with self.db:
try:
self.db.execute("UPDATE Messages SET solution = ? WHERE count = ?", (solution, count))
return True
except:
return False
finally:
self.db_lock.release()
def __iter__(self) -> Generator[MessageDbRow, None, None]:
yield from self.iterate()
@validate_call
def iterate(self,
id:str|None=None, sender:str|None=None, recipient:str|None=None,
processed:bool|None=None,
processed:bool|None=None, solution:bool|None=None,
time_after:int|None=None, time_before:int|None=None,
limit:int=20, offset:int=0
) -> Generator[RowObject, None, None]:
limit:int=20, offset:int=0, _count_only:bool=False
) -> Generator[MessageDbRow|int, None, None]:
where = []
params = {
@ -133,7 +113,11 @@ class DB():
"off": offset
}
for v,n in ((id,'id'), (sender,'sender'), (recipient,'recipient'), (processed,'processed')):
for v,n in (
(id,'id'),
(sender,'sender'), (recipient,'recipient'),
(processed,'processed'), (solution,'solution')
):
if not v is None:
where.append('{} = :{}'.format(n,n))
params[n] = v
@ -152,29 +136,60 @@ class DB():
where_clause = ""
with self.db:
for row in self.db.execute(
"SELECT * FROM Messages {} LIMIT :lim OFFSET :off".format(where_clause),
params
):
yield self._create_row_object(row)
if _count_only:
count = self.db.execute(
"SELECT COUNT(*) as count FROM Messages {}".format(where_clause),
params
).fetchone()
def _create_row_object(self, row:sqlite3.Row) -> RowObject:
return RowObject(
yield count['count']
else:
for row in self.db.execute(
"SELECT * FROM Messages {} ORDER BY time DESC, count DESC LIMIT :lim OFFSET :off".format(where_clause),
params
):
yield self._create_row_object(row, allow_lazy=True)
def __len__(self) -> int:
return self.len()
def len(self, **kwargs) -> int:
"""
See `DB.iterate` for possible values of `kwargs`.
"""
kwargs['_count_only'] = True
return next(self.iterate(**kwargs))
def _create_row_object(self, row:sqlite3.Row, allow_lazy:bool=True) -> MessageDbRow:
try:
message = AgentMessage.model_validate_json(
row['json'],
context={"require_file_exists": not allow_lazy}
)
except ValidationError as e:
if allow_lazy:
message = AgentMessage(
id="error",
riddle={"context":str(e),"question":"Failed to load from Database!"}
)
else:
raise e
return MessageDbRow(
count=row['count'],
sender=row['sender'],
recipient=row['recipient'],
time=int(datetime.strptime(row['time'], self._DB_TIME_FORMAT).timestamp()),
message=AgentMessage.model_construct(row['json']),
processed=row['processed']
message=message,
processed=row['processed'],
solution=row['solution']
)
def by_count(self, count:int) -> RowObject|None:
def by_count(self, count:int) -> MessageDbRow|None:
with self.db:
try:
return self._create_row_object(
self.db.execute("SELECT * FROM Messages WHERE count = ?", (count,)).fetchone()
)
except:
return None
return None

View File

@ -8,28 +8,99 @@
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
import re
from urllib.parse import urlencode
from fastapi import APIRouter, Request
from fastapi.responses import HTMLResponse, RedirectResponse
from fastapi.templating import Jinja2Templates
from ums.management.db import DB
from ums.utils import (AgentMessage, RiddleDataType,
list_shared_data, list_shared_schema, SHARE_PATH)
class Interface():
_PREFIX = "/app"
def __init__(self, template:Jinja2Templates, db:DB):
self.template = template
self.db = db
self.router = APIRouter(
prefix="/app",
tags=["app, gui"]
prefix=self._PREFIX,
tags=["gui"]
)
self._add_routes()
def _add_routes(self):
@self.router.get("/", summary="Test")
def corpus(request: Request):
print(self.db.by_count(3))
@self.router.get("/", response_class=RedirectResponse, summary="Redirect")
def index(request: Request) -> RedirectResponse:
return RedirectResponse(self._PREFIX + "/table")
@self.router.get("/table", response_class=HTMLResponse, summary="Table of messages")
def table(request: Request,
id:str|None=None, sender:str|None=None, recipient:str|None=None,
processed:bool|None=None, solution:bool|None=None,
time_after:int|str|None=None, time_before:int|str|None=None,
limit:int=10, offset:int=0, _count_only:bool=False
):
return {}
db_args = {
"limit" : limit,
"offset" : offset
}
convert_time = lambda t: self.template.env.globals["date2timestamp"](t) \
if not re.match(r'^\d+$', t) else int(t)
for v,n,f in (
(id,'id',str), (sender,'sender',str), (recipient,'recipient',str),
(processed,'processed', bool), (solution,'solution', bool),
(time_after, 'time_after', convert_time), (time_before, 'time_before', convert_time)
):
if not v is None:
db_args[n] = f(v)
if _count_only:
return self.db.len(**db_args)
else:
def pagination_link(**kwargs):
link_args = db_args.copy()
link_args.update(kwargs)
return urlencode(link_args)
return self.template.TemplateResponse(
'table.html',
{"request" : request,
"db" : self.db, "db_args" : db_args,
"pagination_link" : pagination_link
}
)
@self.router.get("/table/total", summary="Total number of messages in table")
def table_total(request: Request,
id:str|None=None, sender:str|None=None, recipient:str|None=None,
processed:bool|None=None, solution:bool|None=None,
time_after:int|str|None=None, time_before:int|str|None=None,
limit:int=10, offset:int=0
) -> int:
kwargs = locals().copy()
del kwargs['table']
kwargs['_count_only'] = True
return table(**kwargs)
@self.router.get("/new", response_class=HTMLResponse, summary="Add new riddle")
def new(request: Request):
return self.template.TemplateResponse(
'new.html',
{"request" : request,
"AgentMessage" : AgentMessage, "RiddleDataType": RiddleDataType,
"shared_data" : list_shared_data(), "shared_schema" : list_shared_schema(),
"SHARE_PATH" : SHARE_PATH
}
)

View File

@ -10,21 +10,31 @@
import os
from fastapi import FastAPI, Request
from typing import List
from datetime import datetime
from fastapi import FastAPI, Request, BackgroundTasks, HTTPException
from fastapi.responses import HTMLResponse
from fastapi.templating import Jinja2Templates
from ums.management.interface import Interface
from ums.management.db import DB
from jinja2.runtime import Undefined as JinjaUndefined
from ums.utils import AgentMessage, RiddleData, RiddleDataType, RiddleSolution, TEMPLATE_PATH
from ums.management.interface import Interface
from ums.management.db import DB, MessageDbRow
from ums.management.process import MessageProcessor
from ums.utils import AgentMessage, AgentResponse, TEMPLATE_PATH
class WebMain():
_TIME_FORMAT = "%H:%M:%S %d.%m.%Y"
def __init__(self):
self._init_app()
self._init_templates()
self.db = DB()
self.msg_process = MessageProcessor(self.db)
self._add_routes()
self._add_routers()
@ -44,41 +54,72 @@ class WebMain():
directory=TEMPLATE_PATH,
auto_reload=True
)
def timestamp2date(t:int|JinjaUndefined) -> str:
return "" if isinstance(t, JinjaUndefined) \
else datetime.fromtimestamp(t).strftime(self._TIME_FORMAT)
self.template.env.globals["timestamp2date"] = timestamp2date
def date2timestamp(d:str|JinjaUndefined) -> int|str:
return "" if isinstance(d, JinjaUndefined) \
else int(datetime.strptime(d, self._TIME_FORMAT).timestamp())
self.template.env.globals["date2timestamp"] = date2timestamp
def _add_routers(self):
interface_router = Interface(self.template, self.db)
self.app.include_router(interface_router.router)
def _add_routes(self):
@self.app.get("/test", summary="Test")
def huhu(request: Request) -> AgentMessage:
ex = AgentMessage(
id="ex1",
riddle={
"context":"Example 1",
"question":"Get the name of the person."
},
data=[
RiddleData(
type=RiddleDataType.TEXT,
file_plain="./cv.txt"
)
]
)
ex.status.extract.required = False
ex.solution = RiddleSolution(
solution="Otto",
explanation="Written in line 6 after 'Name:'"
@self.app.get("/index", response_class=HTMLResponse, summary="Link list")
def index(request: Request):
return self.template.TemplateResponse(
'index.html',
{"request" : request}
)
ins_count = self.db.add_message('from', 'to', ex)
self.db.set_processed(ins_count)
@self.app.post("/message", summary="Send a message to the management", tags=['agents'])
def message(request: Request, message:AgentMessage, background_tasks: BackgroundTasks) -> AgentResponse:
return ex
receiver = request.headers['host']
if ':' in receiver:
receiver = receiver[:receiver.rindex(':')]
sender = request.headers['x-forwarded-for']
if __name__ == "ums.management.main" and os.environ.get('SERVE', 'false') == 'true':
return self.msg_process.new_message(sender, receiver, message, background_tasks)
@self.app.get("/list", summary="Get list of messages (like table)", tags=["cli, agents"])
def list(id:str|None=None, sender:str|None=None, recipient:str|None=None,
processed:bool|None=None, solution:bool|None=None,
time_after:int|None=None, time_before:int|None=None,
limit:int=10, offset:int=0
) -> List[MessageDbRow]:
db_args = {
"limit" : limit,
"offset" : offset
}
for v,n in (
(id,'id'), (sender,'sender'), (recipient,'recipient'),
(processed,'processed'), (solution,'solution'),
(time_after, 'time_after'), (time_before, 'time_before')
):
if not v is None:
db_args[n] = v
return [row for row in self.db.iterate(**db_args)]
@self.app.get("/list/single", summary="Get a single message", tags=["cli, agents"])
def status(count:int) -> MessageDbRow:
msg = self.db.by_count(count)
if msg is None:
raise HTTPException(status_code=404, detail="Message not found")
return msg
if __name__ == "ums.management.main" and os.environ.get('SERVE', 'false').lower() == 'true':
main = WebMain()
app = main.app

268
ums/management/process.py Normal file
View File

@ -0,0 +1,268 @@
# Agenten Plattform
#
# (c) 2024 Magnus Bender
# Institute of Humanities-Centered Artificial Intelligence (CHAI)
# Universitaet Hamburg
# https://www.chai.uni-hamburg.de/~bender
#
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
import os, re
from typing import List
import requests
from fastapi import BackgroundTasks
from ums.management.db import DB
from ums.utils import AgentMessage, AgentResponse, logger, RiddleData, RiddleSolution
class MessageProcessor():
SOLUTION_MAX_TRIALS = int(os.environ.get('SOLUTION_MAX_TRIALS', 5))
MESSAGE_MAX_CONTACTS = int(os.environ.get('MESSAGE_MAX_CONTACTS', 100))
REQUIRE_FULL_EXTRACT = os.environ.get('REQUIRE_FULL_EXTRACT', 'false').lower() == 'true'
REQUIRE_FULL_SOLVE = os.environ.get('REQUIRE_FULL_SOLVE', 'false').lower() == 'true'
MANAGEMENT_URL = os.environ.get('MANAGEMENT_URL', 'http://127.0.0.1:80').strip().strip('/')
AGENTS_PROCESS = tuple(map(
lambda s:s.strip().strip('/'),
os.environ.get('AGENTS_PROCESS', '').split(',')
))
AGENTS_SOLVE = tuple(map(
lambda s:s.strip().strip('/'),
os.environ.get('AGENTS_SOLVE', '').split(',')
))
AGENTS_GATEKEEPER = tuple(map(
lambda s:s.strip().strip('/'),
os.environ.get('AGENTS_GATEKEEPER', '').split(',')
))
def __init__(self, db:DB):
self.db = db
self.management_name = self._get_name(self.MANAGEMENT_URL)
if len(self.AGENTS_PROCESS) == 0:
logger.warning(f"Not Process Agent (AGENTS_PROCESS) found, this may be a problem!")
if len(self.AGENTS_SOLVE) == 0:
logger.warning(f"Not Solve Agent (AGENTS_SOLVE) found, this may be a problem!")
if len(self.AGENTS_GATEKEEPER) == 0:
logger.warning(f"Not Gatekeeper Agent (AGENTS_GATEKEEPER) found, this may be a problem!")
def _get_name(self, url:str) -> str:
m = re.match(r'^https?://([^:]*)(?::(\d+))?$', url)
return "unknown" if m == None else m.group(1)
def new_message(self,
sender:str, receiver:str, message:AgentMessage,
background_tasks: BackgroundTasks
) -> AgentResponse:
try:
db_count = self.db.add_message(sender, receiver, message)
background_tasks.add_task(self._process_message, db_count)
return AgentResponse(
count=db_count,
msg="Added message to queue"
)
except Exception as e:
return AgentResponse(
count=-1,
error=True,
error_msg=str(e)
)
def _process_message(self, count:int, ignore_processed:bool=False):
db_message = self.db.by_count(count)
if db_message.processed and not ignore_processed:
# do not process processed messages again
return
# now message processed!
self.db.set_processed(count=count, processed=True)
# increment contacts counter
db_message.message.contacts += 1
if db_message.message.contacts > self.MESSAGE_MAX_CONTACTS:
logger.warning(f"Message reached max number of contacts! {db_message.message.id}, {count}")
return
# check which step/ state the message requires the management to do
# -> IF
if db_message.message.status.extract.required and not db_message.message.status.extract.finished:
# send to extract agents
self._send_messages(self.AGENTS_PROCESS, db_message.message)
return
# combine different extractions in data items
# will update items in `db_message.message.data`
fully_extracted = self._add_extractions(db_message.message.id, db_message.message.data)
if self.REQUIRE_FULL_EXTRACT and not fully_extracted:
logger.warning(f"Postpone message, wait for full extract of items! {db_message.message.id}, {count}")
return
# -> EL IF
if db_message.message.status.solve.required and not db_message.message.status.solve.finished:
# send to solve agents
self._send_messages(self.AGENTS_SOLVE, db_message.message)
return
# combine different solutions
# will add solutions received before to `db_message.message.solution`
fully_solved = self._add_solutions(db_message.message.id, db_message.message.solution, db_message.message.status.trial)
if self.REQUIRE_FULL_SOLVE and not fully_solved:
logger.warning(f"Postpone message, wait for all solutions of riddle! {db_message.message.id}, {count}")
return
# -> EL IF
if db_message.message.status.validate.required and not db_message.message.status.validate.finished:
# send to solve agents
self._send_messages(self.AGENTS_GATEKEEPER, db_message.message)
return
# -> ELSE
# all steps "done"
# validate not required? (then solved will never be set to true, thus set it here)
if not db_message.message.status.validate.required:
db_message.message.status.solved = True
if db_message.message.status.solved:
# yay, message is solved
self.db.set_solution(count=count, solution=True);
else:
# not solved, but all steps done
self.db.set_solution(count=count, solution=False);
# try again
self._do_again(db_message.message)
def _hash_solution(self, s:RiddleSolution) -> int:
return hash((s.solution, s.explanation, tuple((d.file_plain, d.type) for d in s.used_data)))
def _add_solutions(self, riddle_id:str, solution:List[RiddleSolution], trial:int) -> bool:
# do not do anything, if all solutions available
if len(solution) >= len(self.AGENTS_SOLVE):
return True
contained = set(self._hash_solution(s) for s in solution)
# search db for solutions from before
for row in self.db.iterate(
id=riddle_id,
limit=min(self.db.len(id=riddle_id), 250)
):
# make sure to only use solutions from same "trial"
if row.message.status.trial == trial:
for s in row.message.solution:
h = self._hash_solution(s)
if h not in contained:
# add the 'new' solution
solution.append(s)
contained.add(h)
# all solutions found ?
if len(solution) >= len(self.AGENTS_SOLVE):
break
return len(solution) >= len(self.AGENTS_SOLVE)
def _hash_data(self, d:RiddleData) -> int:
return hash((d.file_plain, d.type, d.prompt))
def _add_extractions(self, riddle_id:str, data:List[RiddleData]) -> bool:
# get all the data items without extraction
empty_data = {}
for i, d in enumerate(data):
if d.file_extracted is None:
empty_data[self._hash_data(d)] = i
# do not do anything if fully extracted
if len(empty_data) == 0:
return True
# search db for extractions already available
for row in self.db.iterate(
id=riddle_id,
limit=min(self.db.len(id=riddle_id), 250)
):
# check for required extraction
for d in row.message.data:
# already extracted ?
# extraction file exists ?
# one of the items, we do not have extractions for ?
# the same data item ?
if not d.file_extracted is None \
and not d.file_extracted.startswith("missing:") \
and self._hash_data(d) in empty_data:
# copy the reference to the extracted data
data[empty_data[self._hash_data(d)]].file_extracted = d.file_extracted
# remove from items we need extracted data for
del empty_data[self._hash_data(d)]
# break if all extractions found
if len(empty_data) == 0:
break
return len(empty_data) == 0 # fully extracted
def _do_again(self, message:AgentMessage):
if message.status.trial < self.SOLUTION_MAX_TRIALS:
# try again, recycle message
# require steps again
if message.status.extract.required:
message.status.extract.finished = False
if message.status.solve.required:
message.status.solve.finished = False
if message.status.validate.required:
message.status.validate.finished = False
# increment trial
message.status.trial += 1
# append current solution(s) als old one(s)
if len(message.solution) > 0:
message.riddle.solutions_before.extend(
message.solution
)
# reset current solution
message.solution = []
# add the riddle as new to management
self._send_message(self.MANAGEMENT_URL, message)
else:
logger.info(f"Unsolved riddle after max number of trials: {message.id}")
def _send_messages(self, recipients:List[str], message:AgentMessage) -> bool:
ok = True
for r in recipients:
ok = ok and self._send_message(r, message)
return ok
def _send_message(self, recipient:str, message:AgentMessage) -> bool:
db_count = self.db.add_message(
sender=self.management_name,
recipient=self._get_name(recipient),
message=message,
processed=False
)
r = requests.post(
"{}/message".format(recipient),
data=message.model_dump_json(),
headers={"accept" : "application/json", "content-type" : "application/json"}
)
if r.status_code == 200:
self.db.set_processed(db_count, processed=True)
return True
else:
logger.warning(f"Error sending message to: {recipient} {(r.text, r.headers)}")
return False

View File

@ -8,6 +8,21 @@
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
from ums.utils.const import *
import logging, os
if os.environ.get('SERVE', 'false').lower() == 'true':
logging.basicConfig(
handlers=[
logging.FileHandler(LOG_FILE),
logging.StreamHandler()
],
level=LOG_LEVEL,
format='%(asctime)s %(levelname)s %(name)s: %(message)s',
datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger('UMS Agenten')
from ums.utils.types import (
RiddleInformation,
AgentMessage,
@ -15,7 +30,17 @@ from ums.utils.types import (
RiddleSolution,
RiddleData,
RiddleDataType,
RiddleStatus
RiddleStatus,
AgentResponse,
MessageDbRow
)
from ums.utils.const import *
from ums.utils.request import ManagementRequest
from ums.utils.functions import list_shared_data, list_shared_schema
from ums.utils.schema import (
ExtractionSchema,
ExtractedData,
ExtractedContent, ExtractedPositions
)

View File

@ -13,9 +13,13 @@
See the content ...
"""
import os
import os, logging
BASE_PATH = '/ums-agenten'
SHARE_PATH = os.path.join(BASE_PATH, 'share')
PERSIST_PATH = os.path.join(BASE_PATH, 'persist')
TEMPLATE_PATH = os.path.join(BASE_PATH, 'plattform', 'web', 'templates')
PUBLIC_PATH = os.path.join(BASE_PATH, 'plattform', 'web', 'public')
TEMPLATE_PATH = os.path.join(BASE_PATH, 'plattform', 'web', 'templates')
LOG_FILE = os.path.join(PERSIST_PATH, 'ums.log')
LOG_LEVEL = logging.INFO

56
ums/utils/functions.py Normal file
View File

@ -0,0 +1,56 @@
# Agenten Plattform
#
# (c) 2024 Magnus Bender
# Institute of Humanities-Centered Artificial Intelligence (CHAI)
# Universitaet Hamburg
# https://www.chai.uni-hamburg.de/~bender
#
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
import os
from typing import List, Callable
from ums.utils.const import SHARE_PATH
def list_path(path:str) -> List[str]:
if os.path.isdir(path):
items = []
for item in os.listdir(path):
full = os.path.join(path, item)
if os.path.isdir(full):
items.extend(list_path(full))
elif os.path.isfile(full):
items.append(full)
return items
else:
return []
def list_shared(filter:Callable=lambda p,n,e: True) -> List[str]:
files = []
for f in list_path(SHARE_PATH):
r = f[len(SHARE_PATH)+1:]
if r[0] == '.' or '/.' in r:
# hidden files
continue
if '/' in r and '.' in r:
path, name, ending = r[:r.rfind('/')], r[r.rfind('/')+1:r.rfind('.')], r[r.rfind('.')+1:]
elif '/' in r:
path, name, ending = r[:r.rfind('/')], r[r.rfind('/')+1:], ""
elif '.' in r:
path, name, ending = "", r[:r.rfind('.')], r[r.rfind('.')+1:]
else:
path, name, ending = "", r, ""
if filter(path, name, ending):
files.append(r)
return files
def list_shared_data():
return list_shared(lambda p,n,e: e != "json")
def list_shared_schema():
return list_shared(lambda p,n,e: e == "json")

173
ums/utils/request.py Normal file
View File

@ -0,0 +1,173 @@
# Agenten Plattform
#
# (c) 2024 Magnus Bender
# Institute of Humanities-Centered Artificial Intelligence (CHAI)
# Universitaet Hamburg
# https://www.chai.uni-hamburg.de/~bender
#
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
"""
Access to the management, e.g., get the list of messages and single messages.
Manually send messages (if necessary, the platforms should do this).
### Example
```python
m_request = ManagementRequest()
m_request.get_message(count=12)
# MessageDbRow(count=12 sender='from' recipient='to' ...
m_request.list_messages(id="test", limit=2)
# [
# MessageDbRow(count=7256, sender='management', ...),
# MessageDbRow(count=7255, sender='management', ...),
# ]
m_request.total_messages(id="test")
# 31
```
See also `ums.example.__main__` and run in Docker via ``docker compose exec management python -m ums.example``
"""
import os
from typing import List, Dict, Any
import requests
from pydantic import validate_call
from ums.utils.types import AgentMessage, AgentResponse, MessageDbRow
class RequestException(Exception):
"""
Raised on http and similar errors.
"""
pass
class ManagementRequest():
MANAGEMENT_URL = os.environ.get('MANAGEMENT_URL', 'http://127.0.0.1:80').strip().strip('/')
@validate_call
def __init__(self, allow_lazy:bool=True):
"""
If `allow_lazy` is active, the type checking (by pydantic) is less strict.
E.g. it does not require that all files in the data section of messages must exist on the file system.
"""
self._allow_lazy = allow_lazy
self._pydantic_context = {
"require_file_exists": not self._allow_lazy
}
@validate_call
def get_message(self, count:int) -> MessageDbRow:
"""
Get a message (like a table row) from the management by using the `count`.
May raise `RequestException`.
"""
row = self._get_request(
'list/single',
{"count": count}
)
return MessageDbRow.model_validate(
row, context=self._pydantic_context
)
@validate_call
def list_messages(self,
id:str|None=None, sender:str|None=None, recipient:str|None=None,
processed:bool|None=None, solution:bool|None=None,
time_after:int|None=None, time_before:int|None=None,
limit:int=10, offset:int=0
) -> List[MessageDbRow]:
"""
Get the rows in the tables as list of messages.
The arguments are used for filtering.
May raise `RequestException`.
"""
kwargs = locals().copy()
params = {}
for k,v in kwargs.items():
if k not in ('self',) and not v is None:
params[k] = v
rows = self._get_request('list', params)
return [
MessageDbRow.model_validate(
row, context=self._pydantic_context
) for row in rows
]
@validate_call
def total_messages(self,
id:str|None=None, sender:str|None=None, recipient:str|None=None,
processed:bool|None=None, solution:bool|None=None,
time_after:int|None=None, time_before:int|None=None
) -> int:
"""
Get the total number of rows in the tables matching the filters.
May raise `RequestException`.
"""
kwargs = locals().copy()
params = {}
for k,v in kwargs.items():
if k not in ('self',) and not v is None:
params[k] = v
return int(self._get_request('app/table/total', params))
def _get_request(self, endpoint:str, params:Dict[str, Any]):
r = requests.get(
"{}/{}".format(self.MANAGEMENT_URL, endpoint),
params=params
)
if r.status_code == 200:
return r.json()
else:
raise RequestException(str(r.text)+"\n"+str(r.headers))
@validate_call
def send_message(self, message:AgentMessage) -> AgentResponse:
"""
Send the `message` to the management and return the management's agent response.
(On error an agent response with error message).
"""
try:
return AgentResponse.model_validate(
self._post_request(
"message",
message.model_dump_json()
)
)
except RequestException as e:
return AgentResponse(
count=-1,
error=True,
error_msg=str(e)
)
def _post_request(self, endpoint:str, data:Dict[str, Any]):
r = requests.post(
"{}/{}".format(self.MANAGEMENT_URL, endpoint),
data=data,
headers={"accept" : "application/json", "content-type" : "application/json"}
)
if r.status_code == 200:
return r.json()
else:
return RequestException(str(r.text)+"\n"+str(r.headers))

85
ums/utils/schema.py Normal file
View File

@ -0,0 +1,85 @@
# Agenten Plattform
#
# (c) 2024 Magnus Bender
# Institute of Humanities-Centered Artificial Intelligence (CHAI)
# Universitaet Hamburg
# https://www.chai.uni-hamburg.de/~bender
#
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
"""
This represents the basic types used for representing extracted information from the data.
The types are implemented using [pydantic](https://docs.pydantic.dev/).
It provides validation, allow JSON serialization and works well with [FastAPI](https://fastapi.tiangolo.com/) which is used internally for the http request between the agents and the management.
**This is work in progress!**
"""
from typing import List, Any, Dict
from pydantic import BaseModel
class ExtractionSchema(BaseModel):
"""
This is the basic class used as superclass for all extracted information from data items.
For all the `ExtractionSchema` is is required that the data can be serialized to json.
Thus, mostly only default data types like `int, str, bool, list, dict, tuple` also including `ExtractionSchema` and `RiddleInformation` can be used here!
"""
class ExtractedContent(ExtractionSchema):
"""
An extracted content item.
"""
type : str
"""
The type, as a string, the actual string will depend on the extraction agent.
"""
content : str | Any
"""
The extracted content
"""
class ExtractedPositions(ExtractionSchema):
"""
A position (like time, coordinates, ...) where something was extracted (each position should belong to a content item).
"""
type : str
"""
The type, as a string, the actual string will depend on the extraction agent.
"""
position : str | int | Any
"""
The position, will also depend on the extraction agent.
"""
description : str | Any = None
"""
An optional description for more details.
"""
class ExtractedData(ExtractionSchema):
"""
Contains the extracted items from a data file.
"""
contents : List[ExtractedContent] = []
"""
The extracted contents (i.e., transcriptions etc.), each item here should belong a position item at the same index.
"""
positions : List[ExtractedPositions] = []
"""
The positions of extracted contents, each item here should belong a content item at the same index.
"""
other : Dict[str, Any] = {}
"""
Possibly more data. Use a keywords (depending on agent) and store the data there.
"""

View File

@ -40,12 +40,13 @@
"question": "Get the name of the person.",
"solutions_before": []
},
"solution": null,
"solution": [],
"data": [
{
"type": "text",
"file_plain": "/ums-agenten/share/cv.txt",
"file_extracted": null
"file_extracted": null,
"prompt": null
}
],
"status": {
@ -63,7 +64,8 @@
},
"trial": 0,
"solved": false
}
},
"contacts": 0
}
```
```python
@ -75,32 +77,43 @@
```json
{
...
"solution": {
"solution": [{
"solution": "Otto",
"explanation": "Written in line 6 after 'Name:'",
"used_data": [],
"accepted": false,
"review": null
},
}],
...
}
```
"""
import os
import os, warnings
from enum import Enum
from typing import List
from typing import List, Any
from typing_extensions import Annotated
from pydantic import BaseModel
from pydantic.functional_validators import AfterValidator
from pydantic import (
BaseModel,
ValidationError, ValidationInfo,
ValidatorFunctionWrapHandler,
WrapValidator, AfterValidator, BeforeValidator
)
from ums.utils.const import SHARE_PATH
from ums.utils.schema import ExtractionSchema
class RiddleInformation(BaseModel):
# ignore:
# /usr/local/lib/python3.12/dist-packages/pydantic/_internal/_fields.py:172:
# UserWarning: Field name "validate" in "RiddleStatus" shadows an attribute in parent
# "RiddleInformation"
warnings.filterwarnings('ignore', category=UserWarning, lineno=172, module="pydantic")
"""
This is the basic class used as superclass for all message and infos
about a riddle.
@ -127,7 +140,22 @@ def _check_data_file(file_name:str) -> str:
return file_name
def _ignore_file_missing(
v: Any, handler: ValidatorFunctionWrapHandler, info: ValidationInfo
) -> str:
try:
return handler(v)
except ValidationError:
if not info.context is None and \
"require_file_exists" in info.context and \
info.context["require_file_exists"] == False and \
isinstance(v, str):
return "missing:{}".format(v)
else:
raise
class RiddleData(RiddleInformation):
"""
A data item to be used to solve the riddle
"""
@ -137,7 +165,7 @@ class RiddleData(RiddleInformation):
The type of the data item.
"""
file_plain: Annotated[str, AfterValidator(_check_data_file)]
file_plain: Annotated[str, AfterValidator(_check_data_file), WrapValidator(_ignore_file_missing)]
"""
The plain file (as path to file system) without any processing.
@ -145,7 +173,7 @@ class RiddleData(RiddleInformation):
The file must exist.
"""
file_extracted: Annotated[str, AfterValidator(_check_data_file)] | None = None
file_extracted: Annotated[str, AfterValidator(_check_data_file), WrapValidator(_ignore_file_missing)] | None = None
"""
The processed files (as path to file system), i.e., a schematic file containing all extracted informations.
@ -153,6 +181,12 @@ class RiddleData(RiddleInformation):
The file must exist.
"""
prompt: str | ExtractionSchema | None = None
"""
An optional prompt giving more details to the extraction agent, e.g., selecting a type of extraction/ task to do with the data.
"""
class RiddleSolution(RiddleInformation):
"""
A solution of a riddle.
@ -234,12 +268,12 @@ class RiddleStatus(RiddleInformation):
"""
The *main* solving step.
`AgentMessage.solution` shall be an `RiddleSolution` afterwards.
`AgentMessage.solution` shall contain an `RiddleSolution` afterwards.
"""
validate: RiddleSubStatus = RiddleSubStatus()
"""
The validation step, i.e., does the gatekeeper accept the solution in `AgentMessage.solution`.
The validation step, i.e., does the gatekeeper accept the solution(s) in `AgentMessage.solution`.
"""
trial: int = 0
@ -250,9 +284,13 @@ class RiddleStatus(RiddleInformation):
solved: bool = False
"""
True, after the gatekeeper accepts the solution at `AgentMessage.solution`
True, after the gatekeeper accepts the solution(s) at `AgentMessage.solution`
"""
def _transform_to_list(value : Any) -> List[Any]:
# type check of items is done next by pydantic
return value if isinstance(value, list) else [value]
class AgentMessage(RiddleInformation):
"""
The basic message, which is sent be the agent and the management.
@ -276,9 +314,10 @@ class AgentMessage(RiddleInformation):
The riddle to solve.
"""
solution: RiddleSolution | None = None
solution: Annotated[List[RiddleSolution], BeforeValidator(_transform_to_list)] = []
"""
The solution of the riddle (or empty if no solution available)
The solutions of the riddle (or empty list if no solutions available)
(When assigning a single object of `RiddleSolution` will be convert to list with this single object.)
"""
data: List[RiddleData] = []
@ -289,4 +328,77 @@ class AgentMessage(RiddleInformation):
status: RiddleStatus = RiddleStatus()
"""
The status of the riddle.
"""
contacts : int = 0
"""
A counter representing the number of contacts the management had with this message.
Each time the management processes the message, this counter is incremented by 1.
Using this counter the management is able to detect cycles and stop them.
"""
class AgentResponse(RiddleInformation):
"""
Returned by the management when receiving an `AgentMessage`.
"""
count : int
"""
The count of the message (overall numeric id).
"""
msg: str|None = None
"""
An additional message.
"""
error: bool = False
"""
If an error occurred.
"""
error_msg: str|None = None
"""
Error message (if `error` )
"""
class MessageDbRow(BaseModel):
"""
Object representing a database row.
"""
count : int
"""
The count (primary key) of the item.
"""
sender : str
"""
The sender of the message.
"""
recipient : str
"""
The recipient of the message
"""
time : int
"""
The time (unix timestamp) the message was received/ sent.
"""
message : AgentMessage
"""
The message received/ sent.
"""
processed : bool
"""
Did the management process the message, i.e., did the tasks necessary for this message (mostly only relevant for received messages).
"""
solution : bool|None = None
"""
Does this message contain a valid solution?
True if contains valid solution, False if solution not valid, Null/None if not applicable
"""

35
utils/agent/Dockerfile Normal file
View File

@ -0,0 +1,35 @@
# Agenten Plattform
#
# (c) 2024 Magnus Bender
# Institute of Humanities-Centered Artificial Intelligence (CHAI)
# Universitaet Hamburg
# https://www.chai.uni-hamburg.de/~bender
#
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
ARG FROM_IMAGE
FROM $FROM_IMAGE
ARG PIP_REQ_FILE
USER root
RUN mkdir -p /ums-agenten/plattform/ && mkdir -p /ums-agenten/persist/
COPY ./utils/agent/$PIP_REQ_FILE /ums-agenten/requirements.txt
RUN pip3 install --break-system-packages --no-cache-dir -r /ums-agenten/requirements.txt \
&& pip3 freeze -q -r /ums-agenten/requirements.txt > /ums-agenten/requirements-frozen.txt
# install the code of the repo
COPY ./utils/setup.py /ums-agenten/plattform/
RUN pip3 install --break-system-packages -e /ums-agenten/plattform/
COPY --chown=user:user ./ums/ /ums-agenten/plattform/ums/
COPY --chown=user:user ./web/ /ums-agenten/plattform/web/
WORKDIR /ums-agenten/plattform/ums/
RUN chown -R user:user /ums-agenten
USER user
ENV SERVE=true
CMD ["/usr/local/bin/uvicorn", "ums.agent.main:app", "--host", "0.0.0.0", "--port", "8000"]

View File

@ -0,0 +1,16 @@
# Agenten Plattform
#
# (c) 2024 Magnus Bender
# Institute of Humanities-Centered Artificial Intelligence (CHAI)
# Universitaet Hamburg
# https://www.chai.uni-hamburg.de/~bender
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
# non frozen dependecies, to use latest
requests==2.32.3
fastapi==0.115.4
uvicorn==0.32.0
python-multipart==0.0.16
## The following requirements were added by pip freeze:
# ...

View File

@ -8,8 +8,8 @@
# source code released under the terms of GNU Public License Version 3
# https://www.gnu.org/licenses/gpl-3.0.txt
ARG FROM_IMAGE=
FROM $FROM_IMAGE
# non frozen dependecies, to use latest
requests
fastapi
uvicorn[standard]
python-multipart

View File

@ -38,17 +38,17 @@ RUN ln -s /usr/bin/python3 /usr/local/bin/python \
RUN mkdir -p /ums-agenten/plattform/ && mkdir -p /ums-agenten/persist/
COPY ./docker-mgmt/$PIP_REQ_FILE /ums-agenten/requirements.txt
COPY ./utils/mgmt/$PIP_REQ_FILE /ums-agenten/requirements.txt
RUN pip3 install --break-system-packages --no-cache-dir -r /ums-agenten/requirements.txt \
&& pip3 freeze > /ums-agenten/requirements.txt
# nginx settings and startup
COPY ./docker-mgmt/supervisor.conf /etc/supervisor/supervisord.conf
COPY ./docker-mgmt/nginx.conf /etc/nginx/nginx.conf
COPY ./docker-mgmt/app.conf /etc/nginx/sites-enabled/default
COPY ./utils/mgmt/supervisor.conf /etc/supervisor/supervisord.conf
COPY ./utils/mgmt/nginx.conf /etc/nginx/nginx.conf
COPY ./utils/mgmt/app.conf /etc/nginx/sites-enabled/default
# install the code of the repo
COPY ./docker-mgmt/setup.py /ums-agenten/plattform/
COPY ./utils/setup.py /ums-agenten/plattform/
RUN pip3 install --break-system-packages -e /ums-agenten/plattform/
WORKDIR /ums-agenten/plattform/ums/

View File

@ -17,10 +17,23 @@ server {
root /ums-agenten/plattform/web/public/;
index index.html;
location = / {
server_name_in_redirect off;
port_in_redirect off;
absolute_redirect off;
return 303 /index;
}
location / {
try_files $uri $uri/ @dynamic;
}
location /share {
alias /ums-agenten/share;
autoindex on;
}
location @dynamic {
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

View File

@ -11,6 +11,8 @@
[supervisord]
nodaemon=true
user=root
logfile=/dev/stdout
logfile_maxbytes = 0
[program:setup]
command=/bin/sh -c "chown user:user -R /ums-agenten"
@ -29,6 +31,11 @@ autostart=true
autorestart=true
priority=10
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
[program:nginx]
command=/usr/sbin/nginx -g 'daemon off;'
autostart=true

View File

@ -13,5 +13,6 @@
IMAGE_REGISTRY="git.chai.uni-hamburg.de"
IMAGE_OWNER="ums-agenten"
IMAGE_NAME_AGENT="base-agent"
IMAGE_AGENT_BASE="base-image"
IMAGE_NAME_MGMT="management"
PLATFORMS="amd64 arm64 gpu"

File diff suppressed because one or more lines are too long

View File

@ -27,6 +27,7 @@
<h2>Submodules</h2>
<ul>
<li><a href="ums/agent.html">agent</a></li>
<li><a href="ums/example.html">example</a></li>
<li><a href="ums/management.html">management</a></li>
<li><a href="ums/utils.html">utils</a></li>
</ul>
@ -45,20 +46,79 @@
<h1 class="modulename">
ums </h1>
<div class="docstring"><p>The package <code><a href="">ums</a></code> contains the Agenten-Plattform, the implementations of the agents shall be created in the package <code>src</code>, see <a href="https://git.chai.uni-hamburg.de/UMS-Agenten/Agent-Template">Agent-Template</a>.</p>
<blockquote>
<p>Side note: The classes with comments may be useful when implementing the agents.
The classes without comments may be safe to ignore and are (only) used internally.</p>
</blockquote>
<ul>
<li><code><a href="ums/agent.html">ums.agent</a></code>
<ul>
<li>Contains the implementation of an agent for handling requests by the implementations in <code>src</code>.</li>
<li>Check for running single tasks without using management.</li>
</ul></li>
<li><code><a href="ums/example.html">ums.example</a></code>
<ul>
<li>Contains a very simple examples for all types of agents.</li>
<li>See <code><a href="ums/example/example.html">ums.example.example</a></code></li>
</ul></li>
<li><code><a href="ums/management.html">ums.management</a></code>
<ul>
<li>Contains the implementation of the management.</li>
<li>Take a look at the web gui of the management, possibly at <a href="http://localhost:8080/"><a href="http://localhost:8080/">http://localhost:8080/</a></a> or <a href="http://localhost:8000/"><a href="http://localhost:8000/">http://localhost:8000/</a></a></li>
</ul></li>
<li><code><a href="ums/utils.html">ums.utils</a></code>
<ul>
<li>Contains various utilities.</li>
<li><code><a href="ums/utils/const.html#SHARE_PATH">ums.utils.const.SHARE_PATH</a></code> The path for shared files between all agents</li>
<li><code><a href="ums/utils/const.html#PERSIST_PATH">ums.utils.const.PERSIST_PATH</a></code> The path to store persistent data of an agent</li>
<li><code><a href="ums/utils/request.html#ManagementRequest">ums.utils.request.ManagementRequest</a></code> Run request to the management (only necessary in special cases, most requests done automatically by platform)</li>
<li><code><a href="ums/utils/schema.html">ums.utils.schema</a></code> The schema (types) used in the files storing extracted data from plain data</li>
<li><code><a href="ums/utils/types.html">ums.utils.types</a></code> The types used in the communication between agent and management</li>
</ul></li>
</ul>
</div>
<input id="mod-ums-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<label class="view-source-button" for="mod-ums-view-source"><span>View Source</span></label>
<div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos">1</span></a><span class="c1"># Agenten Plattform</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos">2</span></a><span class="c1">#</span>
</span><span id="L-3"><a href="#L-3"><span class="linenos">3</span></a><span class="c1"># (c) 2024 Magnus Bender</span>
</span><span id="L-4"><a href="#L-4"><span class="linenos">4</span></a><span class="c1"># Institute of Humanities-Centered Artificial Intelligence (CHAI)</span>
</span><span id="L-5"><a href="#L-5"><span class="linenos">5</span></a><span class="c1"># Universitaet Hamburg</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos">6</span></a><span class="c1"># https://www.chai.uni-hamburg.de/~bender</span>
</span><span id="L-7"><a href="#L-7"><span class="linenos">7</span></a><span class="c1"># </span>
</span><span id="L-8"><a href="#L-8"><span class="linenos">8</span></a><span class="c1"># source code released under the terms of GNU Public License Version 3</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos">9</span></a><span class="c1"># https://www.gnu.org/licenses/gpl-3.0.txt</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos"> 1</span></a><span class="c1"># Agenten Plattform</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos"> 2</span></a><span class="c1">#</span>
</span><span id="L-3"><a href="#L-3"><span class="linenos"> 3</span></a><span class="c1"># (c) 2024 Magnus Bender</span>
</span><span id="L-4"><a href="#L-4"><span class="linenos"> 4</span></a><span class="c1"># Institute of Humanities-Centered Artificial Intelligence (CHAI)</span>
</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a><span class="c1"># Universitaet Hamburg</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a><span class="c1"># https://www.chai.uni-hamburg.de/~bender</span>
</span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a><span class="c1"># </span>
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a><span class="c1"># source code released under the terms of GNU Public License Version 3</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a><span class="c1"># https://www.gnu.org/licenses/gpl-3.0.txt</span>
</span><span id="L-10"><a href="#L-10"><span class="linenos">10</span></a>
</span><span id="L-11"><a href="#L-11"><span class="linenos">11</span></a><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-12"><a href="#L-12"><span class="linenos">12</span></a><span class="sd">The package `ums` contains the Agenten-Plattform, the implementations of the agents shall be created in the package `src`, see [Agent-Template](https://git.chai.uni-hamburg.de/UMS-Agenten/Agent-Template).</span>
</span><span id="L-13"><a href="#L-13"><span class="linenos">13</span></a>
</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a><span class="sd">&gt; Side note: The classes with comments may be useful when implementing the agents.</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a><span class="sd">&gt; The classes without comments may be safe to ignore and are (only) used internally.</span>
</span><span id="L-16"><a href="#L-16"><span class="linenos">16</span></a>
</span><span id="L-17"><a href="#L-17"><span class="linenos">17</span></a><span class="sd">- `ums.agent`</span>
</span><span id="L-18"><a href="#L-18"><span class="linenos">18</span></a><span class="sd"> - Contains the implementation of an agent for handling requests by the implementations in `src`.</span>
</span><span id="L-19"><a href="#L-19"><span class="linenos">19</span></a><span class="sd"> - Check for running single tasks without using management.</span>
</span><span id="L-20"><a href="#L-20"><span class="linenos">20</span></a><span class="sd">- `ums.example`</span>
</span><span id="L-21"><a href="#L-21"><span class="linenos">21</span></a><span class="sd"> - Contains a very simple examples for all types of agents.</span>
</span><span id="L-22"><a href="#L-22"><span class="linenos">22</span></a><span class="sd"> - See `ums.example.example`</span>
</span><span id="L-23"><a href="#L-23"><span class="linenos">23</span></a><span class="sd">- `ums.management`</span>
</span><span id="L-24"><a href="#L-24"><span class="linenos">24</span></a><span class="sd"> - Contains the implementation of the management.</span>
</span><span id="L-25"><a href="#L-25"><span class="linenos">25</span></a><span class="sd"> - Take a look at the web gui of the management, possibly at &lt;http://localhost:8080/&gt; or &lt;http://localhost:8000/&gt;</span>
</span><span id="L-26"><a href="#L-26"><span class="linenos">26</span></a><span class="sd">- `ums.utils`</span>
</span><span id="L-27"><a href="#L-27"><span class="linenos">27</span></a><span class="sd"> - Contains various utilities.</span>
</span><span id="L-28"><a href="#L-28"><span class="linenos">28</span></a><span class="sd"> - `ums.utils.const.SHARE_PATH` The path for shared files between all agents</span>
</span><span id="L-29"><a href="#L-29"><span class="linenos">29</span></a><span class="sd"> - `ums.utils.const.PERSIST_PATH` The path to store persistent data of an agent</span>
</span><span id="L-30"><a href="#L-30"><span class="linenos">30</span></a><span class="sd"> - `ums.utils.request.ManagementRequest` Run request to the management (only necessary in special cases, most requests done automatically by platform)</span>
</span><span id="L-31"><a href="#L-31"><span class="linenos">31</span></a><span class="sd"> - `ums.utils.schema` The schema (types) used in the files storing extracted data from plain data</span>
</span><span id="L-32"><a href="#L-32"><span class="linenos">32</span></a><span class="sd"> - `ums.utils.types` The types used in the communication between agent and management</span>
</span><span id="L-33"><a href="#L-33"><span class="linenos">33</span></a>
</span><span id="L-34"><a href="#L-34"><span class="linenos">34</span></a><span class="sd">&quot;&quot;&quot;</span>
</span></pre></div>

View File

@ -28,8 +28,20 @@
<input type="search" placeholder="Search..." role="searchbox" aria-label="search"
pattern=".+" required>
<h2>Contents</h2>
<ul>
<li><a href="#run-as-agent">Run as Agent</a></li>
<li><a href="#run-single-task">Run Single Task</a></li>
</ul>
<h2>Submodules</h2>
<ul>
<li><a href="agent/agent.html">agent</a></li>
<li><a href="agent/main.html">main</a></li>
<li><a href="agent/process.html">process</a></li>
</ul>
<a class="attribution" title="pdoc: Python API documentation generator" href="https://pdoc.dev" target="_blank">
@ -44,20 +56,104 @@
<h1 class="modulename">
<a href="./../ums.html">ums</a><wbr>.agent </h1>
<div class="docstring"><h2 id="run-as-agent">Run as Agent</h2>
<p>The env. variable <code>AGENTS_LIST</code> is used to identify the agents classes/ task handlers.
It must contain he the package name and a variable name in this package divided by <code>:</code>.
Then, the variable contains a list of agent classes (subclasses of <code><a href="agent/agent.html#BasicAgent">ums.agent.agent.BasicAgent</a></code>)</p>
<p>For example <code>AGENTS_LIST=ums.example.example:AGENT_CLASSES</code>, then in file <code>./ums/example/example.py</code> a variable <code>AGENT_CLASSES</code> exists.
One line in this file, e.g., is <code>AGENT_CLASSES = [MyExtractAudioAgent, MyExtractImageAgent]</code>.</p>
<p>When starting the Docker container of the agent, the classes specified in <code>AGENTS_LIST</code> are loaded and if the agent receives a task, the task is sent to the agent classes' <code>handle</code> methods.</p>
<h2 id="run-single-task">Run Single Task</h2>
<p>For development it might be cumbersome to always require a running management container and sending messages.
Hence, tasks can be run manually from the terminal (still in the container and using the agent classes), but without having a management.</p>
<p>This also uses the <code>AGENTS_LIST</code> env. variable, but the tasks are sent via command line:</p>
<p>There are three ways to send a task (if the agent's Docker container is running):</p>
<ul>
<li><code>docker compose exec agent_all python -m <a href="">ums.agent</a> -d</code>
<ul>
<li>Run a dummy task</li>
<li>Possibly <code>agent_all</code> needs to be changed to the service name (see <code>docker-compose.yml</code>) of the agent's Docker container</li>
</ul></li>
<li><code>cat ./msg.json | docker compose exec -T agent_all python -m <a href="">ums.agent</a> -i</code>
<ul>
<li>Send the task (json of <code>AgentMessage</code>) via STDIN from file <code>./msg.json</code> to the agent</li>
</ul></li>
<li><code>docker compose exec agent_all python -m <a href="">ums.agent</a> -f msg.json</code>
<ul>
<li>Get the task from the json file, the files are searched for by full name, in the shared, and the persistent directory.</li>
</ul></li>
</ul>
<p>If the Agent's Docker container is not running, a temporary container can be started.
For the dummy message, the command would be <code>docker compose run --rm --entrypoint "" agent_all python -m <a href="">ums.agent</a> -d</code>.
(Again, change <code>agent_all</code> for the service name in <code>docker-compose.yml</code>.)</p>
</div>
<input id="mod-agent-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<label class="view-source-button" for="mod-agent-view-source"><span>View Source</span></label>
<div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos">1</span></a><span class="c1"># Agenten Plattform</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos">2</span></a><span class="c1">#</span>
</span><span id="L-3"><a href="#L-3"><span class="linenos">3</span></a><span class="c1"># (c) 2024 Magnus Bender</span>
</span><span id="L-4"><a href="#L-4"><span class="linenos">4</span></a><span class="c1"># Institute of Humanities-Centered Artificial Intelligence (CHAI)</span>
</span><span id="L-5"><a href="#L-5"><span class="linenos">5</span></a><span class="c1"># Universitaet Hamburg</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos">6</span></a><span class="c1"># https://www.chai.uni-hamburg.de/~bender</span>
</span><span id="L-7"><a href="#L-7"><span class="linenos">7</span></a><span class="c1"># </span>
</span><span id="L-8"><a href="#L-8"><span class="linenos">8</span></a><span class="c1"># source code released under the terms of GNU Public License Version 3</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos">9</span></a><span class="c1"># https://www.gnu.org/licenses/gpl-3.0.txt</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos"> 1</span></a><span class="c1"># Agenten Plattform</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos"> 2</span></a><span class="c1">#</span>
</span><span id="L-3"><a href="#L-3"><span class="linenos"> 3</span></a><span class="c1"># (c) 2024 Magnus Bender</span>
</span><span id="L-4"><a href="#L-4"><span class="linenos"> 4</span></a><span class="c1"># Institute of Humanities-Centered Artificial Intelligence (CHAI)</span>
</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a><span class="c1"># Universitaet Hamburg</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a><span class="c1"># https://www.chai.uni-hamburg.de/~bender</span>
</span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a><span class="c1"># </span>
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a><span class="c1"># source code released under the terms of GNU Public License Version 3</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a><span class="c1"># https://www.gnu.org/licenses/gpl-3.0.txt</span>
</span><span id="L-10"><a href="#L-10"><span class="linenos">10</span></a>
</span><span id="L-11"><a href="#L-11"><span class="linenos">11</span></a><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-12"><a href="#L-12"><span class="linenos">12</span></a>
</span><span id="L-13"><a href="#L-13"><span class="linenos">13</span></a><span class="sd">## Run as Agent</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a><span class="sd">The env. variable `AGENTS_LIST` is used to identify the agents classes/ task handlers.</span>
</span><span id="L-16"><a href="#L-16"><span class="linenos">16</span></a><span class="sd">It must contain he the package name and a variable name in this package divided by `:`. </span>
</span><span id="L-17"><a href="#L-17"><span class="linenos">17</span></a><span class="sd">Then, the variable contains a list of agent classes (subclasses of `ums.agent.agent.BasicAgent`)</span>
</span><span id="L-18"><a href="#L-18"><span class="linenos">18</span></a>
</span><span id="L-19"><a href="#L-19"><span class="linenos">19</span></a><span class="sd">For example `AGENTS_LIST=ums.example.example:AGENT_CLASSES`, then in file `./ums/example/example.py` a variable `AGENT_CLASSES` exists. </span>
</span><span id="L-20"><a href="#L-20"><span class="linenos">20</span></a><span class="sd">One line in this file, e.g., is `AGENT_CLASSES = [MyExtractAudioAgent, MyExtractImageAgent]`.</span>
</span><span id="L-21"><a href="#L-21"><span class="linenos">21</span></a>
</span><span id="L-22"><a href="#L-22"><span class="linenos">22</span></a><span class="sd">When starting the Docker container of the agent, the classes specified in `AGENTS_LIST` are loaded and if the agent receives a task, the task is sent to the agent classes&#39; `handle` methods.</span>
</span><span id="L-23"><a href="#L-23"><span class="linenos">23</span></a>
</span><span id="L-24"><a href="#L-24"><span class="linenos">24</span></a><span class="sd">## Run Single Task</span>
</span><span id="L-25"><a href="#L-25"><span class="linenos">25</span></a>
</span><span id="L-26"><a href="#L-26"><span class="linenos">26</span></a><span class="sd">For development it might be cumbersome to always require a running management container and sending messages. </span>
</span><span id="L-27"><a href="#L-27"><span class="linenos">27</span></a><span class="sd">Hence, tasks can be run manually from the terminal (still in the container and using the agent classes), but without having a management.</span>
</span><span id="L-28"><a href="#L-28"><span class="linenos">28</span></a>
</span><span id="L-29"><a href="#L-29"><span class="linenos">29</span></a><span class="sd">This also uses the `AGENTS_LIST` env. variable, but the tasks are sent via command line:</span>
</span><span id="L-30"><a href="#L-30"><span class="linenos">30</span></a>
</span><span id="L-31"><a href="#L-31"><span class="linenos">31</span></a><span class="sd">There are three ways to send a task (if the agent&#39;s Docker container is running):</span>
</span><span id="L-32"><a href="#L-32"><span class="linenos">32</span></a><span class="sd">- `docker compose exec agent_all python -m ums.agent -d`</span>
</span><span id="L-33"><a href="#L-33"><span class="linenos">33</span></a><span class="sd"> - Run a dummy task</span>
</span><span id="L-34"><a href="#L-34"><span class="linenos">34</span></a><span class="sd"> - Possibly `agent_all` needs to be changed to the service name (see `docker-compose.yml`) of the agent&#39;s Docker container</span>
</span><span id="L-35"><a href="#L-35"><span class="linenos">35</span></a><span class="sd">- `cat ./msg.json | docker compose exec -T agent_all python -m ums.agent -i`</span>
</span><span id="L-36"><a href="#L-36"><span class="linenos">36</span></a><span class="sd"> - Send the task (json of `AgentMessage`) via STDIN from file `./msg.json` to the agent</span>
</span><span id="L-37"><a href="#L-37"><span class="linenos">37</span></a><span class="sd">- `docker compose exec agent_all python -m ums.agent -f msg.json`</span>
</span><span id="L-38"><a href="#L-38"><span class="linenos">38</span></a><span class="sd"> - Get the task from the json file, the files are searched for by full name, in the shared, and the persistent directory.</span>
</span><span id="L-39"><a href="#L-39"><span class="linenos">39</span></a>
</span><span id="L-40"><a href="#L-40"><span class="linenos">40</span></a><span class="sd">If the Agent&#39;s Docker container is not running, a temporary container can be started.</span>
</span><span id="L-41"><a href="#L-41"><span class="linenos">41</span></a><span class="sd">For the dummy message, the command would be `docker compose run --rm --entrypoint &quot;&quot; agent_all python -m ums.agent -d`.</span>
</span><span id="L-42"><a href="#L-42"><span class="linenos">42</span></a><span class="sd">(Again, change `agent_all` for the service name in `docker-compose.yml`.)</span>
</span><span id="L-43"><a href="#L-43"><span class="linenos">43</span></a>
</span><span id="L-44"><a href="#L-44"><span class="linenos">44</span></a><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-45"><a href="#L-45"><span class="linenos">45</span></a>
</span><span id="L-46"><a href="#L-46"><span class="linenos">46</span></a><span class="kn">from</span> <span class="nn">ums.agent.agent</span> <span class="kn">import</span> <span class="p">(</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos">47</span></a> <span class="n">AgentCapability</span><span class="p">,</span>
</span><span id="L-48"><a href="#L-48"><span class="linenos">48</span></a> <span class="n">BasicAgent</span><span class="p">,</span>
</span><span id="L-49"><a href="#L-49"><span class="linenos">49</span></a> <span class="n">ExtractAgent</span><span class="p">,</span>
</span><span id="L-50"><a href="#L-50"><span class="linenos">50</span></a> <span class="n">ExtractAudioAgent</span><span class="p">,</span> <span class="n">ExtractImageAgent</span><span class="p">,</span> <span class="n">ExtractTextAgent</span><span class="p">,</span>
</span><span id="L-51"><a href="#L-51"><span class="linenos">51</span></a> <span class="n">SolveAgent</span><span class="p">,</span>
</span><span id="L-52"><a href="#L-52"><span class="linenos">52</span></a> <span class="n">GatekeeperAgent</span>
</span><span id="L-53"><a href="#L-53"><span class="linenos">53</span></a><span class="p">)</span>
</span></pre></div>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -6,7 +6,7 @@
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="generator" content="pdoc 14.7.0"/>
<title>ums.__cli__ API documentation</title>
<title>ums.example API documentation</title>
<style>/*! * Bootstrap Reboot v5.0.0 (https://getbootstrap.com/) * Copyright 2011-2021 The Bootstrap Authors * Copyright 2011-2021 Twitter, Inc. * Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE) * Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md) */*,::after,::before{box-sizing:border-box}@media (prefers-reduced-motion:no-preference){:root{scroll-behavior:smooth}}body{margin:0;font-family:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans","Liberation Sans",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";font-size:1rem;font-weight:400;line-height:1.5;color:#212529;background-color:#fff;-webkit-text-size-adjust:100%;-webkit-tap-highlight-color:transparent}hr{margin:1rem 0;color:inherit;background-color:currentColor;border:0;opacity:.25}hr:not([size]){height:1px}h1,h2,h3,h4,h5,h6{margin-top:0;margin-bottom:.5rem;font-weight:500;line-height:1.2}h1{font-size:calc(1.375rem + 1.5vw)}@media (min-width:1200px){h1{font-size:2.5rem}}h2{font-size:calc(1.325rem + .9vw)}@media (min-width:1200px){h2{font-size:2rem}}h3{font-size:calc(1.3rem + .6vw)}@media (min-width:1200px){h3{font-size:1.75rem}}h4{font-size:calc(1.275rem + .3vw)}@media (min-width:1200px){h4{font-size:1.5rem}}h5{font-size:1.25rem}h6{font-size:1rem}p{margin-top:0;margin-bottom:1rem}abbr[data-bs-original-title],abbr[title]{-webkit-text-decoration:underline dotted;text-decoration:underline dotted;cursor:help;-webkit-text-decoration-skip-ink:none;text-decoration-skip-ink:none}address{margin-bottom:1rem;font-style:normal;line-height:inherit}ol,ul{padding-left:2rem}dl,ol,ul{margin-top:0;margin-bottom:1rem}ol ol,ol ul,ul ol,ul ul{margin-bottom:0}dt{font-weight:700}dd{margin-bottom:.5rem;margin-left:0}blockquote{margin:0 0 1rem}b,strong{font-weight:bolder}small{font-size:.875em}mark{padding:.2em;background-color:#fcf8e3}sub,sup{position:relative;font-size:.75em;line-height:0;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}a{color:#0d6efd;text-decoration:underline}a:hover{color:#0a58ca}a:not([href]):not([class]),a:not([href]):not([class]):hover{color:inherit;text-decoration:none}code,kbd,pre,samp{font-family:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;font-size:1em;direction:ltr;unicode-bidi:bidi-override}pre{display:block;margin-top:0;margin-bottom:1rem;overflow:auto;font-size:.875em}pre code{font-size:inherit;color:inherit;word-break:normal}code{font-size:.875em;color:#d63384;word-wrap:break-word}a>code{color:inherit}kbd{padding:.2rem .4rem;font-size:.875em;color:#fff;background-color:#212529;border-radius:.2rem}kbd kbd{padding:0;font-size:1em;font-weight:700}figure{margin:0 0 1rem}img,svg{vertical-align:middle}table{caption-side:bottom;border-collapse:collapse}caption{padding-top:.5rem;padding-bottom:.5rem;color:#6c757d;text-align:left}th{text-align:inherit;text-align:-webkit-match-parent}tbody,td,tfoot,th,thead,tr{border-color:inherit;border-style:solid;border-width:0}label{display:inline-block}button{border-radius:0}button:focus:not(:focus-visible){outline:0}button,input,optgroup,select,textarea{margin:0;font-family:inherit;font-size:inherit;line-height:inherit}button,select{text-transform:none}[role=button]{cursor:pointer}select{word-wrap:normal}select:disabled{opacity:1}[list]::-webkit-calendar-picker-indicator{display:none}[type=button],[type=reset],[type=submit],button{-webkit-appearance:button}[type=button]:not(:disabled),[type=reset]:not(:disabled),[type=submit]:not(:disabled),button:not(:disabled){cursor:pointer}::-moz-focus-inner{padding:0;border-style:none}textarea{resize:vertical}fieldset{min-width:0;padding:0;margin:0;border:0}legend{float:left;width:100%;padding:0;margin-bottom:.5rem;font-size:calc(1.275rem + .3vw);line-height:inherit}@media (min-width:1200px){legend{font-size:1.5rem}}legend+*{clear:left}::-webkit-datetime-edit-day-field,::-webkit-datetime-edit-fields-wrapper,::-webkit-datetime-edit-hour-field,::-webkit-datetime-edit-minute,::-webkit-datetime-edit-month-field,::-webkit-datetime-edit-text,::-webkit-datetime-edit-year-field{padding:0}::-webkit-inner-spin-button{height:auto}[type=search]{outline-offset:-2px;-webkit-appearance:textfield}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-color-swatch-wrapper{padding:0}::file-selector-button{font:inherit}::-webkit-file-upload-button{font:inherit;-webkit-appearance:button}output{display:inline-block}iframe{border:0}summary{display:list-item;cursor:pointer}progress{vertical-align:baseline}[hidden]{display:none!important}</style>
<style>/*! syntax-highlighting.css */pre{line-height:125%;}span.linenos{color:inherit; background-color:transparent; padding-left:5px; padding-right:20px;}.pdoc-code .hll{background-color:#ffffcc}.pdoc-code{background:#f8f8f8;}.pdoc-code .c{color:#3D7B7B; font-style:italic}.pdoc-code .err{border:1px solid #FF0000}.pdoc-code .k{color:#008000; font-weight:bold}.pdoc-code .o{color:#666666}.pdoc-code .ch{color:#3D7B7B; font-style:italic}.pdoc-code .cm{color:#3D7B7B; font-style:italic}.pdoc-code .cp{color:#9C6500}.pdoc-code .cpf{color:#3D7B7B; font-style:italic}.pdoc-code .c1{color:#3D7B7B; font-style:italic}.pdoc-code .cs{color:#3D7B7B; font-style:italic}.pdoc-code .gd{color:#A00000}.pdoc-code .ge{font-style:italic}.pdoc-code .gr{color:#E40000}.pdoc-code .gh{color:#000080; font-weight:bold}.pdoc-code .gi{color:#008400}.pdoc-code .go{color:#717171}.pdoc-code .gp{color:#000080; font-weight:bold}.pdoc-code .gs{font-weight:bold}.pdoc-code .gu{color:#800080; font-weight:bold}.pdoc-code .gt{color:#0044DD}.pdoc-code .kc{color:#008000; font-weight:bold}.pdoc-code .kd{color:#008000; font-weight:bold}.pdoc-code .kn{color:#008000; font-weight:bold}.pdoc-code .kp{color:#008000}.pdoc-code .kr{color:#008000; font-weight:bold}.pdoc-code .kt{color:#B00040}.pdoc-code .m{color:#666666}.pdoc-code .s{color:#BA2121}.pdoc-code .na{color:#687822}.pdoc-code .nb{color:#008000}.pdoc-code .nc{color:#0000FF; font-weight:bold}.pdoc-code .no{color:#880000}.pdoc-code .nd{color:#AA22FF}.pdoc-code .ni{color:#717171; font-weight:bold}.pdoc-code .ne{color:#CB3F38; font-weight:bold}.pdoc-code .nf{color:#0000FF}.pdoc-code .nl{color:#767600}.pdoc-code .nn{color:#0000FF; font-weight:bold}.pdoc-code .nt{color:#008000; font-weight:bold}.pdoc-code .nv{color:#19177C}.pdoc-code .ow{color:#AA22FF; font-weight:bold}.pdoc-code .w{color:#bbbbbb}.pdoc-code .mb{color:#666666}.pdoc-code .mf{color:#666666}.pdoc-code .mh{color:#666666}.pdoc-code .mi{color:#666666}.pdoc-code .mo{color:#666666}.pdoc-code .sa{color:#BA2121}.pdoc-code .sb{color:#BA2121}.pdoc-code .sc{color:#BA2121}.pdoc-code .dl{color:#BA2121}.pdoc-code .sd{color:#BA2121; font-style:italic}.pdoc-code .s2{color:#BA2121}.pdoc-code .se{color:#AA5D1F; font-weight:bold}.pdoc-code .sh{color:#BA2121}.pdoc-code .si{color:#A45A77; font-weight:bold}.pdoc-code .sx{color:#008000}.pdoc-code .sr{color:#A45A77}.pdoc-code .s1{color:#BA2121}.pdoc-code .ss{color:#19177C}.pdoc-code .bp{color:#008000}.pdoc-code .fm{color:#0000FF}.pdoc-code .vc{color:#19177C}.pdoc-code .vg{color:#19177C}.pdoc-code .vi{color:#19177C}.pdoc-code .vm{color:#19177C}.pdoc-code .il{color:#666666}</style>
@ -29,6 +29,10 @@
pattern=".+" required>
<h2>Submodules</h2>
<ul>
<li><a href="example/example.html">example</a></li>
</ul>
@ -42,12 +46,12 @@
<main class="pdoc">
<section class="module-info">
<h1 class="modulename">
<a href="./../ums.html">ums</a><wbr>.__cli__ </h1>
<a href="./../ums.html">ums</a><wbr>.example </h1>
<input id="mod-__cli__-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<input id="mod-example-view-source" class="view-source-toggle-state" type="checkbox" aria-hidden="true" tabindex="-1">
<label class="view-source-button" for="mod-__cli__-view-source"><span>View Source</span></label>
<label class="view-source-button" for="mod-example-view-source"><span>View Source</span></label>
<div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos">1</span></a><span class="c1"># Agenten Plattform</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos">2</span></a><span class="c1">#</span>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -34,6 +34,7 @@
<li><a href="management/db.html">db</a></li>
<li><a href="management/interface.html">interface</a></li>
<li><a href="management/main.html">main</a></li>
<li><a href="management/process.html">process</a></li>
</ul>

File diff suppressed because it is too large Load Diff

View File

@ -71,41 +71,112 @@
<label class="view-source-button" for="mod-interface-view-source"><span>View Source</span></label>
<div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos"> 1</span></a><span class="c1"># Agenten Plattform</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos"> 2</span></a><span class="c1">#</span>
</span><span id="L-3"><a href="#L-3"><span class="linenos"> 3</span></a><span class="c1"># (c) 2024 Magnus Bender</span>
</span><span id="L-4"><a href="#L-4"><span class="linenos"> 4</span></a><span class="c1"># Institute of Humanities-Centered Artificial Intelligence (CHAI)</span>
</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a><span class="c1"># Universitaet Hamburg</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a><span class="c1"># https://www.chai.uni-hamburg.de/~bender</span>
</span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a><span class="c1"># </span>
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a><span class="c1"># source code released under the terms of GNU Public License Version 3</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a><span class="c1"># https://www.gnu.org/licenses/gpl-3.0.txt</span>
</span><span id="L-10"><a href="#L-10"><span class="linenos">10</span></a>
</span><span id="L-11"><a href="#L-11"><span class="linenos">11</span></a><span class="kn">from</span> <span class="nn">fastapi</span> <span class="kn">import</span> <span class="n">APIRouter</span><span class="p">,</span> <span class="n">Request</span>
</span><span id="L-12"><a href="#L-12"><span class="linenos">12</span></a><span class="kn">from</span> <span class="nn">fastapi.templating</span> <span class="kn">import</span> <span class="n">Jinja2Templates</span>
</span><span id="L-13"><a href="#L-13"><span class="linenos">13</span></a>
</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a><span class="kn">from</span> <span class="nn">ums.management.db</span> <span class="kn">import</span> <span class="n">DB</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a>
</span><span id="L-16"><a href="#L-16"><span class="linenos">16</span></a><span class="k">class</span> <span class="nc">Interface</span><span class="p">():</span>
</span><span id="L-17"><a href="#L-17"><span class="linenos">17</span></a>
</span><span id="L-18"><a href="#L-18"><span class="linenos">18</span></a> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">template</span><span class="p">:</span><span class="n">Jinja2Templates</span><span class="p">,</span> <span class="n">db</span><span class="p">:</span><span class="n">DB</span><span class="p">):</span>
</span><span id="L-19"><a href="#L-19"><span class="linenos">19</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">template</span> <span class="o">=</span> <span class="n">template</span>
</span><span id="L-20"><a href="#L-20"><span class="linenos">20</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">db</span> <span class="o">=</span> <span class="n">db</span>
</span><span id="L-21"><a href="#L-21"><span class="linenos">21</span></a>
</span><span id="L-22"><a href="#L-22"><span class="linenos">22</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">router</span> <span class="o">=</span> <span class="n">APIRouter</span><span class="p">(</span>
</span><span id="L-23"><a href="#L-23"><span class="linenos">23</span></a> <span class="n">prefix</span><span class="o">=</span><span class="s2">&quot;/app&quot;</span><span class="p">,</span>
</span><span id="L-24"><a href="#L-24"><span class="linenos">24</span></a> <span class="n">tags</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;app, gui&quot;</span><span class="p">]</span>
</span><span id="L-25"><a href="#L-25"><span class="linenos">25</span></a> <span class="p">)</span>
</span><span id="L-26"><a href="#L-26"><span class="linenos">26</span></a>
</span><span id="L-27"><a href="#L-27"><span class="linenos">27</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_add_routes</span><span class="p">()</span>
</span><span id="L-28"><a href="#L-28"><span class="linenos">28</span></a>
</span><span id="L-29"><a href="#L-29"><span class="linenos">29</span></a> <span class="k">def</span> <span class="nf">_add_routes</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="L-30"><a href="#L-30"><span class="linenos">30</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/&quot;</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Test&quot;</span><span class="p">)</span>
</span><span id="L-31"><a href="#L-31"><span class="linenos">31</span></a> <span class="k">def</span> <span class="nf">corpus</span><span class="p">(</span><span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">):</span>
</span><span id="L-32"><a href="#L-32"><span class="linenos">32</span></a>
</span><span id="L-33"><a href="#L-33"><span class="linenos">33</span></a> <span class="nb">print</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">by_count</span><span class="p">(</span><span class="mi">3</span><span class="p">))</span>
</span><span id="L-34"><a href="#L-34"><span class="linenos">34</span></a>
</span><span id="L-35"><a href="#L-35"><span class="linenos">35</span></a> <span class="k">return</span> <span class="p">{}</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos"> 1</span></a><span class="c1"># Agenten Plattform</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos"> 2</span></a><span class="c1">#</span>
</span><span id="L-3"><a href="#L-3"><span class="linenos"> 3</span></a><span class="c1"># (c) 2024 Magnus Bender</span>
</span><span id="L-4"><a href="#L-4"><span class="linenos"> 4</span></a><span class="c1"># Institute of Humanities-Centered Artificial Intelligence (CHAI)</span>
</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a><span class="c1"># Universitaet Hamburg</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a><span class="c1"># https://www.chai.uni-hamburg.de/~bender</span>
</span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a><span class="c1"># </span>
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a><span class="c1"># source code released under the terms of GNU Public License Version 3</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a><span class="c1"># https://www.gnu.org/licenses/gpl-3.0.txt</span>
</span><span id="L-10"><a href="#L-10"><span class="linenos"> 10</span></a>
</span><span id="L-11"><a href="#L-11"><span class="linenos"> 11</span></a><span class="kn">import</span> <span class="nn">re</span>
</span><span id="L-12"><a href="#L-12"><span class="linenos"> 12</span></a>
</span><span id="L-13"><a href="#L-13"><span class="linenos"> 13</span></a><span class="kn">from</span> <span class="nn">urllib.parse</span> <span class="kn">import</span> <span class="n">urlencode</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos"> 14</span></a>
</span><span id="L-15"><a href="#L-15"><span class="linenos"> 15</span></a><span class="kn">from</span> <span class="nn">fastapi</span> <span class="kn">import</span> <span class="n">APIRouter</span><span class="p">,</span> <span class="n">Request</span>
</span><span id="L-16"><a href="#L-16"><span class="linenos"> 16</span></a><span class="kn">from</span> <span class="nn">fastapi.responses</span> <span class="kn">import</span> <span class="n">HTMLResponse</span><span class="p">,</span> <span class="n">RedirectResponse</span>
</span><span id="L-17"><a href="#L-17"><span class="linenos"> 17</span></a><span class="kn">from</span> <span class="nn">fastapi.templating</span> <span class="kn">import</span> <span class="n">Jinja2Templates</span>
</span><span id="L-18"><a href="#L-18"><span class="linenos"> 18</span></a>
</span><span id="L-19"><a href="#L-19"><span class="linenos"> 19</span></a><span class="kn">from</span> <span class="nn">ums.management.db</span> <span class="kn">import</span> <span class="n">DB</span>
</span><span id="L-20"><a href="#L-20"><span class="linenos"> 20</span></a>
</span><span id="L-21"><a href="#L-21"><span class="linenos"> 21</span></a><span class="kn">from</span> <span class="nn">ums.utils</span> <span class="kn">import</span> <span class="p">(</span><span class="n">AgentMessage</span><span class="p">,</span> <span class="n">RiddleDataType</span><span class="p">,</span>
</span><span id="L-22"><a href="#L-22"><span class="linenos"> 22</span></a> <span class="n">list_shared_data</span><span class="p">,</span> <span class="n">list_shared_schema</span><span class="p">,</span> <span class="n">SHARE_PATH</span><span class="p">)</span>
</span><span id="L-23"><a href="#L-23"><span class="linenos"> 23</span></a>
</span><span id="L-24"><a href="#L-24"><span class="linenos"> 24</span></a><span class="k">class</span> <span class="nc">Interface</span><span class="p">():</span>
</span><span id="L-25"><a href="#L-25"><span class="linenos"> 25</span></a>
</span><span id="L-26"><a href="#L-26"><span class="linenos"> 26</span></a> <span class="n">_PREFIX</span> <span class="o">=</span> <span class="s2">&quot;/app&quot;</span>
</span><span id="L-27"><a href="#L-27"><span class="linenos"> 27</span></a>
</span><span id="L-28"><a href="#L-28"><span class="linenos"> 28</span></a> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">template</span><span class="p">:</span><span class="n">Jinja2Templates</span><span class="p">,</span> <span class="n">db</span><span class="p">:</span><span class="n">DB</span><span class="p">):</span>
</span><span id="L-29"><a href="#L-29"><span class="linenos"> 29</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">template</span> <span class="o">=</span> <span class="n">template</span>
</span><span id="L-30"><a href="#L-30"><span class="linenos"> 30</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">db</span> <span class="o">=</span> <span class="n">db</span>
</span><span id="L-31"><a href="#L-31"><span class="linenos"> 31</span></a>
</span><span id="L-32"><a href="#L-32"><span class="linenos"> 32</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">router</span> <span class="o">=</span> <span class="n">APIRouter</span><span class="p">(</span>
</span><span id="L-33"><a href="#L-33"><span class="linenos"> 33</span></a> <span class="n">prefix</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_PREFIX</span><span class="p">,</span>
</span><span id="L-34"><a href="#L-34"><span class="linenos"> 34</span></a> <span class="n">tags</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;gui&quot;</span><span class="p">]</span>
</span><span id="L-35"><a href="#L-35"><span class="linenos"> 35</span></a> <span class="p">)</span>
</span><span id="L-36"><a href="#L-36"><span class="linenos"> 36</span></a>
</span><span id="L-37"><a href="#L-37"><span class="linenos"> 37</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_add_routes</span><span class="p">()</span>
</span><span id="L-38"><a href="#L-38"><span class="linenos"> 38</span></a>
</span><span id="L-39"><a href="#L-39"><span class="linenos"> 39</span></a> <span class="k">def</span> <span class="nf">_add_routes</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="L-40"><a href="#L-40"><span class="linenos"> 40</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/&quot;</span><span class="p">,</span> <span class="n">response_class</span><span class="o">=</span><span class="n">RedirectResponse</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Redirect&quot;</span><span class="p">)</span>
</span><span id="L-41"><a href="#L-41"><span class="linenos"> 41</span></a> <span class="k">def</span> <span class="nf">index</span><span class="p">(</span><span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">RedirectResponse</span><span class="p">:</span>
</span><span id="L-42"><a href="#L-42"><span class="linenos"> 42</span></a> <span class="k">return</span> <span class="n">RedirectResponse</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_PREFIX</span> <span class="o">+</span> <span class="s2">&quot;/table&quot;</span><span class="p">)</span>
</span><span id="L-43"><a href="#L-43"><span class="linenos"> 43</span></a>
</span><span id="L-44"><a href="#L-44"><span class="linenos"> 44</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/table&quot;</span><span class="p">,</span> <span class="n">response_class</span><span class="o">=</span><span class="n">HTMLResponse</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Table of messages&quot;</span><span class="p">)</span>
</span><span id="L-45"><a href="#L-45"><span class="linenos"> 45</span></a> <span class="k">def</span> <span class="nf">table</span><span class="p">(</span><span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">,</span>
</span><span id="L-46"><a href="#L-46"><span class="linenos"> 46</span></a> <span class="nb">id</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">sender</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">recipient</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos"> 47</span></a> <span class="n">processed</span><span class="p">:</span><span class="nb">bool</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">solution</span><span class="p">:</span><span class="nb">bool</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
</span><span id="L-48"><a href="#L-48"><span class="linenos"> 48</span></a> <span class="n">time_after</span><span class="p">:</span><span class="nb">int</span><span class="o">|</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">time_before</span><span class="p">:</span><span class="nb">int</span><span class="o">|</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
</span><span id="L-49"><a href="#L-49"><span class="linenos"> 49</span></a> <span class="n">limit</span><span class="p">:</span><span class="nb">int</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span> <span class="n">offset</span><span class="p">:</span><span class="nb">int</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">_count_only</span><span class="p">:</span><span class="nb">bool</span><span class="o">=</span><span class="kc">False</span>
</span><span id="L-50"><a href="#L-50"><span class="linenos"> 50</span></a> <span class="p">):</span>
</span><span id="L-51"><a href="#L-51"><span class="linenos"> 51</span></a>
</span><span id="L-52"><a href="#L-52"><span class="linenos"> 52</span></a> <span class="n">db_args</span> <span class="o">=</span> <span class="p">{</span>
</span><span id="L-53"><a href="#L-53"><span class="linenos"> 53</span></a> <span class="s2">&quot;limit&quot;</span> <span class="p">:</span> <span class="n">limit</span><span class="p">,</span>
</span><span id="L-54"><a href="#L-54"><span class="linenos"> 54</span></a> <span class="s2">&quot;offset&quot;</span> <span class="p">:</span> <span class="n">offset</span>
</span><span id="L-55"><a href="#L-55"><span class="linenos"> 55</span></a> <span class="p">}</span>
</span><span id="L-56"><a href="#L-56"><span class="linenos"> 56</span></a>
</span><span id="L-57"><a href="#L-57"><span class="linenos"> 57</span></a> <span class="n">convert_time</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">t</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">globals</span><span class="p">[</span><span class="s2">&quot;date2timestamp&quot;</span><span class="p">](</span><span class="n">t</span><span class="p">)</span> \
</span><span id="L-58"><a href="#L-58"><span class="linenos"> 58</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;^\d+$&#39;</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span> <span class="k">else</span> <span class="nb">int</span><span class="p">(</span><span class="n">t</span><span class="p">)</span>
</span><span id="L-59"><a href="#L-59"><span class="linenos"> 59</span></a> <span class="k">for</span> <span class="n">v</span><span class="p">,</span><span class="n">n</span><span class="p">,</span><span class="n">f</span> <span class="ow">in</span> <span class="p">(</span>
</span><span id="L-60"><a href="#L-60"><span class="linenos"> 60</span></a> <span class="p">(</span><span class="nb">id</span><span class="p">,</span><span class="s1">&#39;id&#39;</span><span class="p">,</span><span class="nb">str</span><span class="p">),</span> <span class="p">(</span><span class="n">sender</span><span class="p">,</span><span class="s1">&#39;sender&#39;</span><span class="p">,</span><span class="nb">str</span><span class="p">),</span> <span class="p">(</span><span class="n">recipient</span><span class="p">,</span><span class="s1">&#39;recipient&#39;</span><span class="p">,</span><span class="nb">str</span><span class="p">),</span>
</span><span id="L-61"><a href="#L-61"><span class="linenos"> 61</span></a> <span class="p">(</span><span class="n">processed</span><span class="p">,</span><span class="s1">&#39;processed&#39;</span><span class="p">,</span> <span class="nb">bool</span><span class="p">),</span> <span class="p">(</span><span class="n">solution</span><span class="p">,</span><span class="s1">&#39;solution&#39;</span><span class="p">,</span> <span class="nb">bool</span><span class="p">),</span>
</span><span id="L-62"><a href="#L-62"><span class="linenos"> 62</span></a> <span class="p">(</span><span class="n">time_after</span><span class="p">,</span> <span class="s1">&#39;time_after&#39;</span><span class="p">,</span> <span class="n">convert_time</span><span class="p">),</span> <span class="p">(</span><span class="n">time_before</span><span class="p">,</span> <span class="s1">&#39;time_before&#39;</span><span class="p">,</span> <span class="n">convert_time</span><span class="p">)</span>
</span><span id="L-63"><a href="#L-63"><span class="linenos"> 63</span></a> <span class="p">):</span>
</span><span id="L-64"><a href="#L-64"><span class="linenos"> 64</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">v</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="L-65"><a href="#L-65"><span class="linenos"> 65</span></a> <span class="n">db_args</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="n">v</span><span class="p">)</span>
</span><span id="L-66"><a href="#L-66"><span class="linenos"> 66</span></a>
</span><span id="L-67"><a href="#L-67"><span class="linenos"> 67</span></a> <span class="k">if</span> <span class="n">_count_only</span><span class="p">:</span>
</span><span id="L-68"><a href="#L-68"><span class="linenos"> 68</span></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">len</span><span class="p">(</span><span class="o">**</span><span class="n">db_args</span><span class="p">)</span>
</span><span id="L-69"><a href="#L-69"><span class="linenos"> 69</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="L-70"><a href="#L-70"><span class="linenos"> 70</span></a> <span class="k">def</span> <span class="nf">pagination_link</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
</span><span id="L-71"><a href="#L-71"><span class="linenos"> 71</span></a> <span class="n">link_args</span> <span class="o">=</span> <span class="n">db_args</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
</span><span id="L-72"><a href="#L-72"><span class="linenos"> 72</span></a> <span class="n">link_args</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">kwargs</span><span class="p">)</span>
</span><span id="L-73"><a href="#L-73"><span class="linenos"> 73</span></a> <span class="k">return</span> <span class="n">urlencode</span><span class="p">(</span><span class="n">link_args</span><span class="p">)</span>
</span><span id="L-74"><a href="#L-74"><span class="linenos"> 74</span></a>
</span><span id="L-75"><a href="#L-75"><span class="linenos"> 75</span></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">TemplateResponse</span><span class="p">(</span>
</span><span id="L-76"><a href="#L-76"><span class="linenos"> 76</span></a> <span class="s1">&#39;table.html&#39;</span><span class="p">,</span>
</span><span id="L-77"><a href="#L-77"><span class="linenos"> 77</span></a> <span class="p">{</span><span class="s2">&quot;request&quot;</span> <span class="p">:</span> <span class="n">request</span><span class="p">,</span>
</span><span id="L-78"><a href="#L-78"><span class="linenos"> 78</span></a> <span class="s2">&quot;db&quot;</span> <span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="p">,</span> <span class="s2">&quot;db_args&quot;</span> <span class="p">:</span> <span class="n">db_args</span><span class="p">,</span>
</span><span id="L-79"><a href="#L-79"><span class="linenos"> 79</span></a> <span class="s2">&quot;pagination_link&quot;</span> <span class="p">:</span> <span class="n">pagination_link</span>
</span><span id="L-80"><a href="#L-80"><span class="linenos"> 80</span></a> <span class="p">}</span>
</span><span id="L-81"><a href="#L-81"><span class="linenos"> 81</span></a> <span class="p">)</span>
</span><span id="L-82"><a href="#L-82"><span class="linenos"> 82</span></a>
</span><span id="L-83"><a href="#L-83"><span class="linenos"> 83</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/table/total&quot;</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Total number of messages in table&quot;</span><span class="p">)</span>
</span><span id="L-84"><a href="#L-84"><span class="linenos"> 84</span></a> <span class="k">def</span> <span class="nf">table_total</span><span class="p">(</span><span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">,</span>
</span><span id="L-85"><a href="#L-85"><span class="linenos"> 85</span></a> <span class="nb">id</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">sender</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">recipient</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
</span><span id="L-86"><a href="#L-86"><span class="linenos"> 86</span></a> <span class="n">processed</span><span class="p">:</span><span class="nb">bool</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">solution</span><span class="p">:</span><span class="nb">bool</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
</span><span id="L-87"><a href="#L-87"><span class="linenos"> 87</span></a> <span class="n">time_after</span><span class="p">:</span><span class="nb">int</span><span class="o">|</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">time_before</span><span class="p">:</span><span class="nb">int</span><span class="o">|</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
</span><span id="L-88"><a href="#L-88"><span class="linenos"> 88</span></a> <span class="n">limit</span><span class="p">:</span><span class="nb">int</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span> <span class="n">offset</span><span class="p">:</span><span class="nb">int</span><span class="o">=</span><span class="mi">0</span>
</span><span id="L-89"><a href="#L-89"><span class="linenos"> 89</span></a> <span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span><span id="L-90"><a href="#L-90"><span class="linenos"> 90</span></a>
</span><span id="L-91"><a href="#L-91"><span class="linenos"> 91</span></a> <span class="n">kwargs</span> <span class="o">=</span> <span class="nb">locals</span><span class="p">()</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
</span><span id="L-92"><a href="#L-92"><span class="linenos"> 92</span></a> <span class="k">del</span> <span class="n">kwargs</span><span class="p">[</span><span class="s1">&#39;table&#39;</span><span class="p">]</span>
</span><span id="L-93"><a href="#L-93"><span class="linenos"> 93</span></a> <span class="n">kwargs</span><span class="p">[</span><span class="s1">&#39;_count_only&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
</span><span id="L-94"><a href="#L-94"><span class="linenos"> 94</span></a>
</span><span id="L-95"><a href="#L-95"><span class="linenos"> 95</span></a> <span class="k">return</span> <span class="n">table</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</span><span id="L-96"><a href="#L-96"><span class="linenos"> 96</span></a>
</span><span id="L-97"><a href="#L-97"><span class="linenos"> 97</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/new&quot;</span><span class="p">,</span> <span class="n">response_class</span><span class="o">=</span><span class="n">HTMLResponse</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Add new riddle&quot;</span><span class="p">)</span>
</span><span id="L-98"><a href="#L-98"><span class="linenos"> 98</span></a> <span class="k">def</span> <span class="nf">new</span><span class="p">(</span><span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">):</span>
</span><span id="L-99"><a href="#L-99"><span class="linenos"> 99</span></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">TemplateResponse</span><span class="p">(</span>
</span><span id="L-100"><a href="#L-100"><span class="linenos">100</span></a> <span class="s1">&#39;new.html&#39;</span><span class="p">,</span>
</span><span id="L-101"><a href="#L-101"><span class="linenos">101</span></a> <span class="p">{</span><span class="s2">&quot;request&quot;</span> <span class="p">:</span> <span class="n">request</span><span class="p">,</span>
</span><span id="L-102"><a href="#L-102"><span class="linenos">102</span></a> <span class="s2">&quot;AgentMessage&quot;</span> <span class="p">:</span> <span class="n">AgentMessage</span><span class="p">,</span> <span class="s2">&quot;RiddleDataType&quot;</span><span class="p">:</span> <span class="n">RiddleDataType</span><span class="p">,</span>
</span><span id="L-103"><a href="#L-103"><span class="linenos">103</span></a> <span class="s2">&quot;shared_data&quot;</span> <span class="p">:</span> <span class="n">list_shared_data</span><span class="p">(),</span> <span class="s2">&quot;shared_schema&quot;</span> <span class="p">:</span> <span class="n">list_shared_schema</span><span class="p">(),</span>
</span><span id="L-104"><a href="#L-104"><span class="linenos">104</span></a> <span class="s2">&quot;SHARE_PATH&quot;</span> <span class="p">:</span> <span class="n">SHARE_PATH</span>
</span><span id="L-105"><a href="#L-105"><span class="linenos">105</span></a> <span class="p">}</span>
</span><span id="L-106"><a href="#L-106"><span class="linenos">106</span></a> <span class="p">)</span>
</span></pre></div>
@ -121,26 +192,89 @@
</div>
<a class="headerlink" href="#Interface"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="Interface-17"><a href="#Interface-17"><span class="linenos">17</span></a><span class="k">class</span> <span class="nc">Interface</span><span class="p">():</span>
</span><span id="Interface-18"><a href="#Interface-18"><span class="linenos">18</span></a>
</span><span id="Interface-19"><a href="#Interface-19"><span class="linenos">19</span></a> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">template</span><span class="p">:</span><span class="n">Jinja2Templates</span><span class="p">,</span> <span class="n">db</span><span class="p">:</span><span class="n">DB</span><span class="p">):</span>
</span><span id="Interface-20"><a href="#Interface-20"><span class="linenos">20</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">template</span> <span class="o">=</span> <span class="n">template</span>
</span><span id="Interface-21"><a href="#Interface-21"><span class="linenos">21</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">db</span> <span class="o">=</span> <span class="n">db</span>
</span><span id="Interface-22"><a href="#Interface-22"><span class="linenos">22</span></a>
</span><span id="Interface-23"><a href="#Interface-23"><span class="linenos">23</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">router</span> <span class="o">=</span> <span class="n">APIRouter</span><span class="p">(</span>
</span><span id="Interface-24"><a href="#Interface-24"><span class="linenos">24</span></a> <span class="n">prefix</span><span class="o">=</span><span class="s2">&quot;/app&quot;</span><span class="p">,</span>
</span><span id="Interface-25"><a href="#Interface-25"><span class="linenos">25</span></a> <span class="n">tags</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;app, gui&quot;</span><span class="p">]</span>
</span><span id="Interface-26"><a href="#Interface-26"><span class="linenos">26</span></a> <span class="p">)</span>
</span><span id="Interface-27"><a href="#Interface-27"><span class="linenos">27</span></a>
</span><span id="Interface-28"><a href="#Interface-28"><span class="linenos">28</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_add_routes</span><span class="p">()</span>
</span><span id="Interface-29"><a href="#Interface-29"><span class="linenos">29</span></a>
</span><span id="Interface-30"><a href="#Interface-30"><span class="linenos">30</span></a> <span class="k">def</span> <span class="nf">_add_routes</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="Interface-31"><a href="#Interface-31"><span class="linenos">31</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/&quot;</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Test&quot;</span><span class="p">)</span>
</span><span id="Interface-32"><a href="#Interface-32"><span class="linenos">32</span></a> <span class="k">def</span> <span class="nf">corpus</span><span class="p">(</span><span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">):</span>
</span><span id="Interface-33"><a href="#Interface-33"><span class="linenos">33</span></a>
</span><span id="Interface-34"><a href="#Interface-34"><span class="linenos">34</span></a> <span class="nb">print</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">by_count</span><span class="p">(</span><span class="mi">3</span><span class="p">))</span>
</span><span id="Interface-35"><a href="#Interface-35"><span class="linenos">35</span></a>
</span><span id="Interface-36"><a href="#Interface-36"><span class="linenos">36</span></a> <span class="k">return</span> <span class="p">{}</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="Interface-25"><a href="#Interface-25"><span class="linenos"> 25</span></a><span class="k">class</span> <span class="nc">Interface</span><span class="p">():</span>
</span><span id="Interface-26"><a href="#Interface-26"><span class="linenos"> 26</span></a>
</span><span id="Interface-27"><a href="#Interface-27"><span class="linenos"> 27</span></a> <span class="n">_PREFIX</span> <span class="o">=</span> <span class="s2">&quot;/app&quot;</span>
</span><span id="Interface-28"><a href="#Interface-28"><span class="linenos"> 28</span></a>
</span><span id="Interface-29"><a href="#Interface-29"><span class="linenos"> 29</span></a> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">template</span><span class="p">:</span><span class="n">Jinja2Templates</span><span class="p">,</span> <span class="n">db</span><span class="p">:</span><span class="n">DB</span><span class="p">):</span>
</span><span id="Interface-30"><a href="#Interface-30"><span class="linenos"> 30</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">template</span> <span class="o">=</span> <span class="n">template</span>
</span><span id="Interface-31"><a href="#Interface-31"><span class="linenos"> 31</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">db</span> <span class="o">=</span> <span class="n">db</span>
</span><span id="Interface-32"><a href="#Interface-32"><span class="linenos"> 32</span></a>
</span><span id="Interface-33"><a href="#Interface-33"><span class="linenos"> 33</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">router</span> <span class="o">=</span> <span class="n">APIRouter</span><span class="p">(</span>
</span><span id="Interface-34"><a href="#Interface-34"><span class="linenos"> 34</span></a> <span class="n">prefix</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_PREFIX</span><span class="p">,</span>
</span><span id="Interface-35"><a href="#Interface-35"><span class="linenos"> 35</span></a> <span class="n">tags</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;gui&quot;</span><span class="p">]</span>
</span><span id="Interface-36"><a href="#Interface-36"><span class="linenos"> 36</span></a> <span class="p">)</span>
</span><span id="Interface-37"><a href="#Interface-37"><span class="linenos"> 37</span></a>
</span><span id="Interface-38"><a href="#Interface-38"><span class="linenos"> 38</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_add_routes</span><span class="p">()</span>
</span><span id="Interface-39"><a href="#Interface-39"><span class="linenos"> 39</span></a>
</span><span id="Interface-40"><a href="#Interface-40"><span class="linenos"> 40</span></a> <span class="k">def</span> <span class="nf">_add_routes</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="Interface-41"><a href="#Interface-41"><span class="linenos"> 41</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/&quot;</span><span class="p">,</span> <span class="n">response_class</span><span class="o">=</span><span class="n">RedirectResponse</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Redirect&quot;</span><span class="p">)</span>
</span><span id="Interface-42"><a href="#Interface-42"><span class="linenos"> 42</span></a> <span class="k">def</span> <span class="nf">index</span><span class="p">(</span><span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">RedirectResponse</span><span class="p">:</span>
</span><span id="Interface-43"><a href="#Interface-43"><span class="linenos"> 43</span></a> <span class="k">return</span> <span class="n">RedirectResponse</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_PREFIX</span> <span class="o">+</span> <span class="s2">&quot;/table&quot;</span><span class="p">)</span>
</span><span id="Interface-44"><a href="#Interface-44"><span class="linenos"> 44</span></a>
</span><span id="Interface-45"><a href="#Interface-45"><span class="linenos"> 45</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/table&quot;</span><span class="p">,</span> <span class="n">response_class</span><span class="o">=</span><span class="n">HTMLResponse</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Table of messages&quot;</span><span class="p">)</span>
</span><span id="Interface-46"><a href="#Interface-46"><span class="linenos"> 46</span></a> <span class="k">def</span> <span class="nf">table</span><span class="p">(</span><span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">,</span>
</span><span id="Interface-47"><a href="#Interface-47"><span class="linenos"> 47</span></a> <span class="nb">id</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">sender</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">recipient</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
</span><span id="Interface-48"><a href="#Interface-48"><span class="linenos"> 48</span></a> <span class="n">processed</span><span class="p">:</span><span class="nb">bool</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">solution</span><span class="p">:</span><span class="nb">bool</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
</span><span id="Interface-49"><a href="#Interface-49"><span class="linenos"> 49</span></a> <span class="n">time_after</span><span class="p">:</span><span class="nb">int</span><span class="o">|</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">time_before</span><span class="p">:</span><span class="nb">int</span><span class="o">|</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
</span><span id="Interface-50"><a href="#Interface-50"><span class="linenos"> 50</span></a> <span class="n">limit</span><span class="p">:</span><span class="nb">int</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span> <span class="n">offset</span><span class="p">:</span><span class="nb">int</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="n">_count_only</span><span class="p">:</span><span class="nb">bool</span><span class="o">=</span><span class="kc">False</span>
</span><span id="Interface-51"><a href="#Interface-51"><span class="linenos"> 51</span></a> <span class="p">):</span>
</span><span id="Interface-52"><a href="#Interface-52"><span class="linenos"> 52</span></a>
</span><span id="Interface-53"><a href="#Interface-53"><span class="linenos"> 53</span></a> <span class="n">db_args</span> <span class="o">=</span> <span class="p">{</span>
</span><span id="Interface-54"><a href="#Interface-54"><span class="linenos"> 54</span></a> <span class="s2">&quot;limit&quot;</span> <span class="p">:</span> <span class="n">limit</span><span class="p">,</span>
</span><span id="Interface-55"><a href="#Interface-55"><span class="linenos"> 55</span></a> <span class="s2">&quot;offset&quot;</span> <span class="p">:</span> <span class="n">offset</span>
</span><span id="Interface-56"><a href="#Interface-56"><span class="linenos"> 56</span></a> <span class="p">}</span>
</span><span id="Interface-57"><a href="#Interface-57"><span class="linenos"> 57</span></a>
</span><span id="Interface-58"><a href="#Interface-58"><span class="linenos"> 58</span></a> <span class="n">convert_time</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">t</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">globals</span><span class="p">[</span><span class="s2">&quot;date2timestamp&quot;</span><span class="p">](</span><span class="n">t</span><span class="p">)</span> \
</span><span id="Interface-59"><a href="#Interface-59"><span class="linenos"> 59</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">re</span><span class="o">.</span><span class="n">match</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;^\d+$&#39;</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span> <span class="k">else</span> <span class="nb">int</span><span class="p">(</span><span class="n">t</span><span class="p">)</span>
</span><span id="Interface-60"><a href="#Interface-60"><span class="linenos"> 60</span></a> <span class="k">for</span> <span class="n">v</span><span class="p">,</span><span class="n">n</span><span class="p">,</span><span class="n">f</span> <span class="ow">in</span> <span class="p">(</span>
</span><span id="Interface-61"><a href="#Interface-61"><span class="linenos"> 61</span></a> <span class="p">(</span><span class="nb">id</span><span class="p">,</span><span class="s1">&#39;id&#39;</span><span class="p">,</span><span class="nb">str</span><span class="p">),</span> <span class="p">(</span><span class="n">sender</span><span class="p">,</span><span class="s1">&#39;sender&#39;</span><span class="p">,</span><span class="nb">str</span><span class="p">),</span> <span class="p">(</span><span class="n">recipient</span><span class="p">,</span><span class="s1">&#39;recipient&#39;</span><span class="p">,</span><span class="nb">str</span><span class="p">),</span>
</span><span id="Interface-62"><a href="#Interface-62"><span class="linenos"> 62</span></a> <span class="p">(</span><span class="n">processed</span><span class="p">,</span><span class="s1">&#39;processed&#39;</span><span class="p">,</span> <span class="nb">bool</span><span class="p">),</span> <span class="p">(</span><span class="n">solution</span><span class="p">,</span><span class="s1">&#39;solution&#39;</span><span class="p">,</span> <span class="nb">bool</span><span class="p">),</span>
</span><span id="Interface-63"><a href="#Interface-63"><span class="linenos"> 63</span></a> <span class="p">(</span><span class="n">time_after</span><span class="p">,</span> <span class="s1">&#39;time_after&#39;</span><span class="p">,</span> <span class="n">convert_time</span><span class="p">),</span> <span class="p">(</span><span class="n">time_before</span><span class="p">,</span> <span class="s1">&#39;time_before&#39;</span><span class="p">,</span> <span class="n">convert_time</span><span class="p">)</span>
</span><span id="Interface-64"><a href="#Interface-64"><span class="linenos"> 64</span></a> <span class="p">):</span>
</span><span id="Interface-65"><a href="#Interface-65"><span class="linenos"> 65</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">v</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="Interface-66"><a href="#Interface-66"><span class="linenos"> 66</span></a> <span class="n">db_args</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="n">v</span><span class="p">)</span>
</span><span id="Interface-67"><a href="#Interface-67"><span class="linenos"> 67</span></a>
</span><span id="Interface-68"><a href="#Interface-68"><span class="linenos"> 68</span></a> <span class="k">if</span> <span class="n">_count_only</span><span class="p">:</span>
</span><span id="Interface-69"><a href="#Interface-69"><span class="linenos"> 69</span></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">len</span><span class="p">(</span><span class="o">**</span><span class="n">db_args</span><span class="p">)</span>
</span><span id="Interface-70"><a href="#Interface-70"><span class="linenos"> 70</span></a> <span class="k">else</span><span class="p">:</span>
</span><span id="Interface-71"><a href="#Interface-71"><span class="linenos"> 71</span></a> <span class="k">def</span> <span class="nf">pagination_link</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
</span><span id="Interface-72"><a href="#Interface-72"><span class="linenos"> 72</span></a> <span class="n">link_args</span> <span class="o">=</span> <span class="n">db_args</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
</span><span id="Interface-73"><a href="#Interface-73"><span class="linenos"> 73</span></a> <span class="n">link_args</span><span class="o">.</span><span class="n">update</span><span class="p">(</span><span class="n">kwargs</span><span class="p">)</span>
</span><span id="Interface-74"><a href="#Interface-74"><span class="linenos"> 74</span></a> <span class="k">return</span> <span class="n">urlencode</span><span class="p">(</span><span class="n">link_args</span><span class="p">)</span>
</span><span id="Interface-75"><a href="#Interface-75"><span class="linenos"> 75</span></a>
</span><span id="Interface-76"><a href="#Interface-76"><span class="linenos"> 76</span></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">TemplateResponse</span><span class="p">(</span>
</span><span id="Interface-77"><a href="#Interface-77"><span class="linenos"> 77</span></a> <span class="s1">&#39;table.html&#39;</span><span class="p">,</span>
</span><span id="Interface-78"><a href="#Interface-78"><span class="linenos"> 78</span></a> <span class="p">{</span><span class="s2">&quot;request&quot;</span> <span class="p">:</span> <span class="n">request</span><span class="p">,</span>
</span><span id="Interface-79"><a href="#Interface-79"><span class="linenos"> 79</span></a> <span class="s2">&quot;db&quot;</span> <span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="p">,</span> <span class="s2">&quot;db_args&quot;</span> <span class="p">:</span> <span class="n">db_args</span><span class="p">,</span>
</span><span id="Interface-80"><a href="#Interface-80"><span class="linenos"> 80</span></a> <span class="s2">&quot;pagination_link&quot;</span> <span class="p">:</span> <span class="n">pagination_link</span>
</span><span id="Interface-81"><a href="#Interface-81"><span class="linenos"> 81</span></a> <span class="p">}</span>
</span><span id="Interface-82"><a href="#Interface-82"><span class="linenos"> 82</span></a> <span class="p">)</span>
</span><span id="Interface-83"><a href="#Interface-83"><span class="linenos"> 83</span></a>
</span><span id="Interface-84"><a href="#Interface-84"><span class="linenos"> 84</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/table/total&quot;</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Total number of messages in table&quot;</span><span class="p">)</span>
</span><span id="Interface-85"><a href="#Interface-85"><span class="linenos"> 85</span></a> <span class="k">def</span> <span class="nf">table_total</span><span class="p">(</span><span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">,</span>
</span><span id="Interface-86"><a href="#Interface-86"><span class="linenos"> 86</span></a> <span class="nb">id</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">sender</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">recipient</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
</span><span id="Interface-87"><a href="#Interface-87"><span class="linenos"> 87</span></a> <span class="n">processed</span><span class="p">:</span><span class="nb">bool</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">solution</span><span class="p">:</span><span class="nb">bool</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
</span><span id="Interface-88"><a href="#Interface-88"><span class="linenos"> 88</span></a> <span class="n">time_after</span><span class="p">:</span><span class="nb">int</span><span class="o">|</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">time_before</span><span class="p">:</span><span class="nb">int</span><span class="o">|</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
</span><span id="Interface-89"><a href="#Interface-89"><span class="linenos"> 89</span></a> <span class="n">limit</span><span class="p">:</span><span class="nb">int</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span> <span class="n">offset</span><span class="p">:</span><span class="nb">int</span><span class="o">=</span><span class="mi">0</span>
</span><span id="Interface-90"><a href="#Interface-90"><span class="linenos"> 90</span></a> <span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span><span id="Interface-91"><a href="#Interface-91"><span class="linenos"> 91</span></a>
</span><span id="Interface-92"><a href="#Interface-92"><span class="linenos"> 92</span></a> <span class="n">kwargs</span> <span class="o">=</span> <span class="nb">locals</span><span class="p">()</span><span class="o">.</span><span class="n">copy</span><span class="p">()</span>
</span><span id="Interface-93"><a href="#Interface-93"><span class="linenos"> 93</span></a> <span class="k">del</span> <span class="n">kwargs</span><span class="p">[</span><span class="s1">&#39;table&#39;</span><span class="p">]</span>
</span><span id="Interface-94"><a href="#Interface-94"><span class="linenos"> 94</span></a> <span class="n">kwargs</span><span class="p">[</span><span class="s1">&#39;_count_only&#39;</span><span class="p">]</span> <span class="o">=</span> <span class="kc">True</span>
</span><span id="Interface-95"><a href="#Interface-95"><span class="linenos"> 95</span></a>
</span><span id="Interface-96"><a href="#Interface-96"><span class="linenos"> 96</span></a> <span class="k">return</span> <span class="n">table</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">)</span>
</span><span id="Interface-97"><a href="#Interface-97"><span class="linenos"> 97</span></a>
</span><span id="Interface-98"><a href="#Interface-98"><span class="linenos"> 98</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">router</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/new&quot;</span><span class="p">,</span> <span class="n">response_class</span><span class="o">=</span><span class="n">HTMLResponse</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Add new riddle&quot;</span><span class="p">)</span>
</span><span id="Interface-99"><a href="#Interface-99"><span class="linenos"> 99</span></a> <span class="k">def</span> <span class="nf">new</span><span class="p">(</span><span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">):</span>
</span><span id="Interface-100"><a href="#Interface-100"><span class="linenos">100</span></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">TemplateResponse</span><span class="p">(</span>
</span><span id="Interface-101"><a href="#Interface-101"><span class="linenos">101</span></a> <span class="s1">&#39;new.html&#39;</span><span class="p">,</span>
</span><span id="Interface-102"><a href="#Interface-102"><span class="linenos">102</span></a> <span class="p">{</span><span class="s2">&quot;request&quot;</span> <span class="p">:</span> <span class="n">request</span><span class="p">,</span>
</span><span id="Interface-103"><a href="#Interface-103"><span class="linenos">103</span></a> <span class="s2">&quot;AgentMessage&quot;</span> <span class="p">:</span> <span class="n">AgentMessage</span><span class="p">,</span> <span class="s2">&quot;RiddleDataType&quot;</span><span class="p">:</span> <span class="n">RiddleDataType</span><span class="p">,</span>
</span><span id="Interface-104"><a href="#Interface-104"><span class="linenos">104</span></a> <span class="s2">&quot;shared_data&quot;</span> <span class="p">:</span> <span class="n">list_shared_data</span><span class="p">(),</span> <span class="s2">&quot;shared_schema&quot;</span> <span class="p">:</span> <span class="n">list_shared_schema</span><span class="p">(),</span>
</span><span id="Interface-105"><a href="#Interface-105"><span class="linenos">105</span></a> <span class="s2">&quot;SHARE_PATH&quot;</span> <span class="p">:</span> <span class="n">SHARE_PATH</span>
</span><span id="Interface-106"><a href="#Interface-106"><span class="linenos">106</span></a> <span class="p">}</span>
</span><span id="Interface-107"><a href="#Interface-107"><span class="linenos">107</span></a> <span class="p">)</span>
</span></pre></div>
@ -156,16 +290,16 @@
</div>
<a class="headerlink" href="#Interface.__init__"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="Interface.__init__-19"><a href="#Interface.__init__-19"><span class="linenos">19</span></a> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">template</span><span class="p">:</span><span class="n">Jinja2Templates</span><span class="p">,</span> <span class="n">db</span><span class="p">:</span><span class="n">DB</span><span class="p">):</span>
</span><span id="Interface.__init__-20"><a href="#Interface.__init__-20"><span class="linenos">20</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">template</span> <span class="o">=</span> <span class="n">template</span>
</span><span id="Interface.__init__-21"><a href="#Interface.__init__-21"><span class="linenos">21</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">db</span> <span class="o">=</span> <span class="n">db</span>
</span><span id="Interface.__init__-22"><a href="#Interface.__init__-22"><span class="linenos">22</span></a>
</span><span id="Interface.__init__-23"><a href="#Interface.__init__-23"><span class="linenos">23</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">router</span> <span class="o">=</span> <span class="n">APIRouter</span><span class="p">(</span>
</span><span id="Interface.__init__-24"><a href="#Interface.__init__-24"><span class="linenos">24</span></a> <span class="n">prefix</span><span class="o">=</span><span class="s2">&quot;/app&quot;</span><span class="p">,</span>
</span><span id="Interface.__init__-25"><a href="#Interface.__init__-25"><span class="linenos">25</span></a> <span class="n">tags</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;app, gui&quot;</span><span class="p">]</span>
</span><span id="Interface.__init__-26"><a href="#Interface.__init__-26"><span class="linenos">26</span></a> <span class="p">)</span>
</span><span id="Interface.__init__-27"><a href="#Interface.__init__-27"><span class="linenos">27</span></a>
</span><span id="Interface.__init__-28"><a href="#Interface.__init__-28"><span class="linenos">28</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_add_routes</span><span class="p">()</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="Interface.__init__-29"><a href="#Interface.__init__-29"><span class="linenos">29</span></a> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">template</span><span class="p">:</span><span class="n">Jinja2Templates</span><span class="p">,</span> <span class="n">db</span><span class="p">:</span><span class="n">DB</span><span class="p">):</span>
</span><span id="Interface.__init__-30"><a href="#Interface.__init__-30"><span class="linenos">30</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">template</span> <span class="o">=</span> <span class="n">template</span>
</span><span id="Interface.__init__-31"><a href="#Interface.__init__-31"><span class="linenos">31</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">db</span> <span class="o">=</span> <span class="n">db</span>
</span><span id="Interface.__init__-32"><a href="#Interface.__init__-32"><span class="linenos">32</span></a>
</span><span id="Interface.__init__-33"><a href="#Interface.__init__-33"><span class="linenos">33</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">router</span> <span class="o">=</span> <span class="n">APIRouter</span><span class="p">(</span>
</span><span id="Interface.__init__-34"><a href="#Interface.__init__-34"><span class="linenos">34</span></a> <span class="n">prefix</span><span class="o">=</span><span class="bp">self</span><span class="o">.</span><span class="n">_PREFIX</span><span class="p">,</span>
</span><span id="Interface.__init__-35"><a href="#Interface.__init__-35"><span class="linenos">35</span></a> <span class="n">tags</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;gui&quot;</span><span class="p">]</span>
</span><span id="Interface.__init__-36"><a href="#Interface.__init__-36"><span class="linenos">36</span></a> <span class="p">)</span>
</span><span id="Interface.__init__-37"><a href="#Interface.__init__-37"><span class="linenos">37</span></a>
</span><span id="Interface.__init__-38"><a href="#Interface.__init__-38"><span class="linenos">38</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_add_routes</span><span class="p">()</span>
</span></pre></div>

View File

@ -38,6 +38,9 @@
<li>
<a class="variable" href="#WebMain.db">db</a>
</li>
<li>
<a class="variable" href="#WebMain.msg_process">msg_process</a>
</li>
</ul>
</li>
@ -62,90 +65,131 @@
<label class="view-source-button" for="mod-main-view-source"><span>View Source</span></label>
<div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos"> 1</span></a><span class="c1"># Agenten Plattform</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos"> 2</span></a><span class="c1">#</span>
</span><span id="L-3"><a href="#L-3"><span class="linenos"> 3</span></a><span class="c1"># (c) 2024 Magnus Bender</span>
</span><span id="L-4"><a href="#L-4"><span class="linenos"> 4</span></a><span class="c1"># Institute of Humanities-Centered Artificial Intelligence (CHAI)</span>
</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a><span class="c1"># Universitaet Hamburg</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a><span class="c1"># https://www.chai.uni-hamburg.de/~bender</span>
</span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a><span class="c1"># </span>
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a><span class="c1"># source code released under the terms of GNU Public License Version 3</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a><span class="c1"># https://www.gnu.org/licenses/gpl-3.0.txt</span>
</span><span id="L-10"><a href="#L-10"><span class="linenos">10</span></a>
</span><span id="L-11"><a href="#L-11"><span class="linenos">11</span></a><span class="kn">import</span> <span class="nn">os</span>
</span><span id="L-12"><a href="#L-12"><span class="linenos">12</span></a>
</span><span id="L-13"><a href="#L-13"><span class="linenos">13</span></a><span class="kn">from</span> <span class="nn">fastapi</span> <span class="kn">import</span> <span class="n">FastAPI</span><span class="p">,</span> <span class="n">Request</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a><span class="kn">from</span> <span class="nn">fastapi.templating</span> <span class="kn">import</span> <span class="n">Jinja2Templates</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a>
</span><span id="L-16"><a href="#L-16"><span class="linenos">16</span></a><span class="kn">from</span> <span class="nn">ums.management.interface</span> <span class="kn">import</span> <span class="n">Interface</span>
</span><span id="L-17"><a href="#L-17"><span class="linenos">17</span></a><span class="kn">from</span> <span class="nn">ums.management.db</span> <span class="kn">import</span> <span class="n">DB</span>
</span><span id="L-18"><a href="#L-18"><span class="linenos">18</span></a>
</span><span id="L-19"><a href="#L-19"><span class="linenos">19</span></a><span class="kn">from</span> <span class="nn">ums.utils</span> <span class="kn">import</span> <span class="n">AgentMessage</span><span class="p">,</span> <span class="n">RiddleData</span><span class="p">,</span> <span class="n">RiddleDataType</span><span class="p">,</span> <span class="n">RiddleSolution</span><span class="p">,</span> <span class="n">TEMPLATE_PATH</span>
</span><span id="L-20"><a href="#L-20"><span class="linenos">20</span></a>
</span><span id="L-21"><a href="#L-21"><span class="linenos">21</span></a><span class="k">class</span> <span class="nc">WebMain</span><span class="p">():</span>
</span><span id="L-22"><a href="#L-22"><span class="linenos">22</span></a>
</span><span id="L-23"><a href="#L-23"><span class="linenos">23</span></a> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="L-24"><a href="#L-24"><span class="linenos">24</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_init_app</span><span class="p">()</span>
</span><span id="L-25"><a href="#L-25"><span class="linenos">25</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_init_templates</span><span class="p">()</span>
</span><span id="L-26"><a href="#L-26"><span class="linenos">26</span></a>
</span><span id="L-27"><a href="#L-27"><span class="linenos">27</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">db</span> <span class="o">=</span> <span class="n">DB</span><span class="p">()</span>
</span><span id="L-28"><a href="#L-28"><span class="linenos">28</span></a>
</span><span id="L-29"><a href="#L-29"><span class="linenos">29</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_add_routes</span><span class="p">()</span>
</span><span id="L-30"><a href="#L-30"><span class="linenos">30</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_add_routers</span><span class="p">()</span>
</span><span id="L-31"><a href="#L-31"><span class="linenos">31</span></a>
</span><span id="L-32"><a href="#L-32"><span class="linenos">32</span></a>
</span><span id="L-33"><a href="#L-33"><span class="linenos">33</span></a> <span class="k">def</span> <span class="nf">_init_app</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="L-34"><a href="#L-34"><span class="linenos">34</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">app</span> <span class="o">=</span> <span class="n">FastAPI</span><span class="p">(</span>
</span><span id="L-35"><a href="#L-35"><span class="linenos">35</span></a> <span class="n">title</span><span class="o">=</span><span class="s2">&quot;Agenten Plattform&quot;</span><span class="p">,</span>
</span><span id="L-36"><a href="#L-36"><span class="linenos">36</span></a> <span class="n">description</span><span class="o">=</span><span class="s2">&quot;Agenten Plattform Management&quot;</span><span class="p">,</span>
</span><span id="L-37"><a href="#L-37"><span class="linenos">37</span></a> <span class="n">openapi_url</span><span class="o">=</span><span class="s2">&quot;/api/schema.json&quot;</span><span class="p">,</span>
</span><span id="L-38"><a href="#L-38"><span class="linenos">38</span></a> <span class="n">docs_url</span><span class="o">=</span><span class="s1">&#39;/api&#39;</span><span class="p">,</span>
</span><span id="L-39"><a href="#L-39"><span class="linenos">39</span></a> <span class="n">redoc_url</span><span class="o">=</span><span class="kc">None</span>
</span><span id="L-40"><a href="#L-40"><span class="linenos">40</span></a> <span class="p">)</span>
</span><span id="L-41"><a href="#L-41"><span class="linenos">41</span></a>
</span><span id="L-42"><a href="#L-42"><span class="linenos">42</span></a> <span class="k">def</span> <span class="nf">_init_templates</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="L-43"><a href="#L-43"><span class="linenos">43</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">template</span> <span class="o">=</span> <span class="n">Jinja2Templates</span><span class="p">(</span>
</span><span id="L-44"><a href="#L-44"><span class="linenos">44</span></a> <span class="n">directory</span><span class="o">=</span><span class="n">TEMPLATE_PATH</span><span class="p">,</span>
</span><span id="L-45"><a href="#L-45"><span class="linenos">45</span></a> <span class="n">auto_reload</span><span class="o">=</span><span class="kc">True</span>
</span><span id="L-46"><a href="#L-46"><span class="linenos">46</span></a> <span class="p">)</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos">47</span></a>
</span><span id="L-48"><a href="#L-48"><span class="linenos">48</span></a> <span class="k">def</span> <span class="nf">_add_routers</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="L-49"><a href="#L-49"><span class="linenos">49</span></a> <span class="n">interface_router</span> <span class="o">=</span> <span class="n">Interface</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">template</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="p">)</span>
</span><span id="L-50"><a href="#L-50"><span class="linenos">50</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">include_router</span><span class="p">(</span><span class="n">interface_router</span><span class="o">.</span><span class="n">router</span><span class="p">)</span>
</span><span id="L-51"><a href="#L-51"><span class="linenos">51</span></a>
</span><span id="L-52"><a href="#L-52"><span class="linenos">52</span></a>
</span><span id="L-53"><a href="#L-53"><span class="linenos">53</span></a> <span class="k">def</span> <span class="nf">_add_routes</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="L-54"><a href="#L-54"><span class="linenos">54</span></a>
</span><span id="L-55"><a href="#L-55"><span class="linenos">55</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/test&quot;</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Test&quot;</span><span class="p">)</span>
</span><span id="L-56"><a href="#L-56"><span class="linenos">56</span></a> <span class="k">def</span> <span class="nf">huhu</span><span class="p">(</span><span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">AgentMessage</span><span class="p">:</span>
</span><span id="L-57"><a href="#L-57"><span class="linenos">57</span></a> <span class="n">ex</span> <span class="o">=</span> <span class="n">AgentMessage</span><span class="p">(</span>
</span><span id="L-58"><a href="#L-58"><span class="linenos">58</span></a> <span class="nb">id</span><span class="o">=</span><span class="s2">&quot;ex1&quot;</span><span class="p">,</span>
</span><span id="L-59"><a href="#L-59"><span class="linenos">59</span></a> <span class="n">riddle</span><span class="o">=</span><span class="p">{</span>
</span><span id="L-60"><a href="#L-60"><span class="linenos">60</span></a> <span class="s2">&quot;context&quot;</span><span class="p">:</span><span class="s2">&quot;Example 1&quot;</span><span class="p">,</span>
</span><span id="L-61"><a href="#L-61"><span class="linenos">61</span></a> <span class="s2">&quot;question&quot;</span><span class="p">:</span><span class="s2">&quot;Get the name of the person.&quot;</span>
</span><span id="L-62"><a href="#L-62"><span class="linenos">62</span></a> <span class="p">},</span>
</span><span id="L-63"><a href="#L-63"><span class="linenos">63</span></a> <span class="n">data</span><span class="o">=</span><span class="p">[</span>
</span><span id="L-64"><a href="#L-64"><span class="linenos">64</span></a> <span class="n">RiddleData</span><span class="p">(</span>
</span><span id="L-65"><a href="#L-65"><span class="linenos">65</span></a> <span class="nb">type</span><span class="o">=</span><span class="n">RiddleDataType</span><span class="o">.</span><span class="n">TEXT</span><span class="p">,</span>
</span><span id="L-66"><a href="#L-66"><span class="linenos">66</span></a> <span class="n">file_plain</span><span class="o">=</span><span class="s2">&quot;./cv.txt&quot;</span>
</span><span id="L-67"><a href="#L-67"><span class="linenos">67</span></a> <span class="p">)</span>
</span><span id="L-68"><a href="#L-68"><span class="linenos">68</span></a> <span class="p">]</span>
</span><span id="L-69"><a href="#L-69"><span class="linenos">69</span></a> <span class="p">)</span>
</span><span id="L-70"><a href="#L-70"><span class="linenos">70</span></a> <span class="n">ex</span><span class="o">.</span><span class="n">status</span><span class="o">.</span><span class="n">extract</span><span class="o">.</span><span class="n">required</span> <span class="o">=</span> <span class="kc">False</span>
</span><span id="L-71"><a href="#L-71"><span class="linenos">71</span></a>
</span><span id="L-72"><a href="#L-72"><span class="linenos">72</span></a> <span class="n">ex</span><span class="o">.</span><span class="n">solution</span> <span class="o">=</span> <span class="n">RiddleSolution</span><span class="p">(</span>
</span><span id="L-73"><a href="#L-73"><span class="linenos">73</span></a> <span class="n">solution</span><span class="o">=</span><span class="s2">&quot;Otto&quot;</span><span class="p">,</span>
</span><span id="L-74"><a href="#L-74"><span class="linenos">74</span></a> <span class="n">explanation</span><span class="o">=</span><span class="s2">&quot;Written in line 6 after &#39;Name:&#39;&quot;</span>
</span><span id="L-75"><a href="#L-75"><span class="linenos">75</span></a> <span class="p">)</span>
</span><span id="L-76"><a href="#L-76"><span class="linenos">76</span></a>
</span><span id="L-77"><a href="#L-77"><span class="linenos">77</span></a> <span class="n">ins_count</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">add_message</span><span class="p">(</span><span class="s1">&#39;from&#39;</span><span class="p">,</span> <span class="s1">&#39;to&#39;</span><span class="p">,</span> <span class="n">ex</span><span class="p">)</span>
</span><span id="L-78"><a href="#L-78"><span class="linenos">78</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">set_processed</span><span class="p">(</span><span class="n">ins_count</span><span class="p">)</span>
</span><span id="L-79"><a href="#L-79"><span class="linenos">79</span></a>
</span><span id="L-80"><a href="#L-80"><span class="linenos">80</span></a> <span class="k">return</span> <span class="n">ex</span>
</span><span id="L-81"><a href="#L-81"><span class="linenos">81</span></a>
</span><span id="L-82"><a href="#L-82"><span class="linenos">82</span></a><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;ums.management.main&quot;</span> <span class="ow">and</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;SERVE&#39;</span><span class="p">,</span> <span class="s1">&#39;false&#39;</span><span class="p">)</span> <span class="o">==</span> <span class="s1">&#39;true&#39;</span><span class="p">:</span>
</span><span id="L-83"><a href="#L-83"><span class="linenos">83</span></a> <span class="n">main</span> <span class="o">=</span> <span class="n">WebMain</span><span class="p">()</span>
</span><span id="L-84"><a href="#L-84"><span class="linenos">84</span></a> <span class="n">app</span> <span class="o">=</span> <span class="n">main</span><span class="o">.</span><span class="n">app</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="L-1"><a href="#L-1"><span class="linenos"> 1</span></a><span class="c1"># Agenten Plattform</span>
</span><span id="L-2"><a href="#L-2"><span class="linenos"> 2</span></a><span class="c1">#</span>
</span><span id="L-3"><a href="#L-3"><span class="linenos"> 3</span></a><span class="c1"># (c) 2024 Magnus Bender</span>
</span><span id="L-4"><a href="#L-4"><span class="linenos"> 4</span></a><span class="c1"># Institute of Humanities-Centered Artificial Intelligence (CHAI)</span>
</span><span id="L-5"><a href="#L-5"><span class="linenos"> 5</span></a><span class="c1"># Universitaet Hamburg</span>
</span><span id="L-6"><a href="#L-6"><span class="linenos"> 6</span></a><span class="c1"># https://www.chai.uni-hamburg.de/~bender</span>
</span><span id="L-7"><a href="#L-7"><span class="linenos"> 7</span></a><span class="c1"># </span>
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a><span class="c1"># source code released under the terms of GNU Public License Version 3</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a><span class="c1"># https://www.gnu.org/licenses/gpl-3.0.txt</span>
</span><span id="L-10"><a href="#L-10"><span class="linenos"> 10</span></a>
</span><span id="L-11"><a href="#L-11"><span class="linenos"> 11</span></a><span class="kn">import</span> <span class="nn">os</span>
</span><span id="L-12"><a href="#L-12"><span class="linenos"> 12</span></a>
</span><span id="L-13"><a href="#L-13"><span class="linenos"> 13</span></a><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos"> 14</span></a><span class="kn">from</span> <span class="nn">datetime</span> <span class="kn">import</span> <span class="n">datetime</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos"> 15</span></a>
</span><span id="L-16"><a href="#L-16"><span class="linenos"> 16</span></a><span class="kn">from</span> <span class="nn">fastapi</span> <span class="kn">import</span> <span class="n">FastAPI</span><span class="p">,</span> <span class="n">Request</span><span class="p">,</span> <span class="n">BackgroundTasks</span><span class="p">,</span> <span class="n">HTTPException</span>
</span><span id="L-17"><a href="#L-17"><span class="linenos"> 17</span></a><span class="kn">from</span> <span class="nn">fastapi.responses</span> <span class="kn">import</span> <span class="n">HTMLResponse</span>
</span><span id="L-18"><a href="#L-18"><span class="linenos"> 18</span></a><span class="kn">from</span> <span class="nn">fastapi.templating</span> <span class="kn">import</span> <span class="n">Jinja2Templates</span>
</span><span id="L-19"><a href="#L-19"><span class="linenos"> 19</span></a>
</span><span id="L-20"><a href="#L-20"><span class="linenos"> 20</span></a><span class="kn">from</span> <span class="nn">jinja2.runtime</span> <span class="kn">import</span> <span class="n">Undefined</span> <span class="k">as</span> <span class="n">JinjaUndefined</span>
</span><span id="L-21"><a href="#L-21"><span class="linenos"> 21</span></a>
</span><span id="L-22"><a href="#L-22"><span class="linenos"> 22</span></a><span class="kn">from</span> <span class="nn">ums.management.interface</span> <span class="kn">import</span> <span class="n">Interface</span>
</span><span id="L-23"><a href="#L-23"><span class="linenos"> 23</span></a><span class="kn">from</span> <span class="nn">ums.management.db</span> <span class="kn">import</span> <span class="n">DB</span><span class="p">,</span> <span class="n">MessageDbRow</span>
</span><span id="L-24"><a href="#L-24"><span class="linenos"> 24</span></a><span class="kn">from</span> <span class="nn">ums.management.process</span> <span class="kn">import</span> <span class="n">MessageProcessor</span>
</span><span id="L-25"><a href="#L-25"><span class="linenos"> 25</span></a>
</span><span id="L-26"><a href="#L-26"><span class="linenos"> 26</span></a><span class="kn">from</span> <span class="nn">ums.utils</span> <span class="kn">import</span> <span class="n">AgentMessage</span><span class="p">,</span> <span class="n">AgentResponse</span><span class="p">,</span> <span class="n">TEMPLATE_PATH</span>
</span><span id="L-27"><a href="#L-27"><span class="linenos"> 27</span></a>
</span><span id="L-28"><a href="#L-28"><span class="linenos"> 28</span></a><span class="k">class</span> <span class="nc">WebMain</span><span class="p">():</span>
</span><span id="L-29"><a href="#L-29"><span class="linenos"> 29</span></a>
</span><span id="L-30"><a href="#L-30"><span class="linenos"> 30</span></a> <span class="n">_TIME_FORMAT</span> <span class="o">=</span> <span class="s2">&quot;%H:%M:%S </span><span class="si">%d</span><span class="s2">.%m.%Y&quot;</span>
</span><span id="L-31"><a href="#L-31"><span class="linenos"> 31</span></a>
</span><span id="L-32"><a href="#L-32"><span class="linenos"> 32</span></a> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="L-33"><a href="#L-33"><span class="linenos"> 33</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_init_app</span><span class="p">()</span>
</span><span id="L-34"><a href="#L-34"><span class="linenos"> 34</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_init_templates</span><span class="p">()</span>
</span><span id="L-35"><a href="#L-35"><span class="linenos"> 35</span></a>
</span><span id="L-36"><a href="#L-36"><span class="linenos"> 36</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">db</span> <span class="o">=</span> <span class="n">DB</span><span class="p">()</span>
</span><span id="L-37"><a href="#L-37"><span class="linenos"> 37</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">msg_process</span> <span class="o">=</span> <span class="n">MessageProcessor</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="p">)</span>
</span><span id="L-38"><a href="#L-38"><span class="linenos"> 38</span></a>
</span><span id="L-39"><a href="#L-39"><span class="linenos"> 39</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_add_routes</span><span class="p">()</span>
</span><span id="L-40"><a href="#L-40"><span class="linenos"> 40</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_add_routers</span><span class="p">()</span>
</span><span id="L-41"><a href="#L-41"><span class="linenos"> 41</span></a>
</span><span id="L-42"><a href="#L-42"><span class="linenos"> 42</span></a>
</span><span id="L-43"><a href="#L-43"><span class="linenos"> 43</span></a> <span class="k">def</span> <span class="nf">_init_app</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="L-44"><a href="#L-44"><span class="linenos"> 44</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">app</span> <span class="o">=</span> <span class="n">FastAPI</span><span class="p">(</span>
</span><span id="L-45"><a href="#L-45"><span class="linenos"> 45</span></a> <span class="n">title</span><span class="o">=</span><span class="s2">&quot;Agenten Plattform&quot;</span><span class="p">,</span>
</span><span id="L-46"><a href="#L-46"><span class="linenos"> 46</span></a> <span class="n">description</span><span class="o">=</span><span class="s2">&quot;Agenten Plattform Management&quot;</span><span class="p">,</span>
</span><span id="L-47"><a href="#L-47"><span class="linenos"> 47</span></a> <span class="n">openapi_url</span><span class="o">=</span><span class="s2">&quot;/api/schema.json&quot;</span><span class="p">,</span>
</span><span id="L-48"><a href="#L-48"><span class="linenos"> 48</span></a> <span class="n">docs_url</span><span class="o">=</span><span class="s1">&#39;/api&#39;</span><span class="p">,</span>
</span><span id="L-49"><a href="#L-49"><span class="linenos"> 49</span></a> <span class="n">redoc_url</span><span class="o">=</span><span class="kc">None</span>
</span><span id="L-50"><a href="#L-50"><span class="linenos"> 50</span></a> <span class="p">)</span>
</span><span id="L-51"><a href="#L-51"><span class="linenos"> 51</span></a>
</span><span id="L-52"><a href="#L-52"><span class="linenos"> 52</span></a> <span class="k">def</span> <span class="nf">_init_templates</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="L-53"><a href="#L-53"><span class="linenos"> 53</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">template</span> <span class="o">=</span> <span class="n">Jinja2Templates</span><span class="p">(</span>
</span><span id="L-54"><a href="#L-54"><span class="linenos"> 54</span></a> <span class="n">directory</span><span class="o">=</span><span class="n">TEMPLATE_PATH</span><span class="p">,</span>
</span><span id="L-55"><a href="#L-55"><span class="linenos"> 55</span></a> <span class="n">auto_reload</span><span class="o">=</span><span class="kc">True</span>
</span><span id="L-56"><a href="#L-56"><span class="linenos"> 56</span></a> <span class="p">)</span>
</span><span id="L-57"><a href="#L-57"><span class="linenos"> 57</span></a>
</span><span id="L-58"><a href="#L-58"><span class="linenos"> 58</span></a> <span class="k">def</span> <span class="nf">timestamp2date</span><span class="p">(</span><span class="n">t</span><span class="p">:</span><span class="nb">int</span><span class="o">|</span><span class="n">JinjaUndefined</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span><span id="L-59"><a href="#L-59"><span class="linenos"> 59</span></a> <span class="k">return</span> <span class="s2">&quot;&quot;</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">t</span><span class="p">,</span> <span class="n">JinjaUndefined</span><span class="p">)</span> \
</span><span id="L-60"><a href="#L-60"><span class="linenos"> 60</span></a> <span class="k">else</span> <span class="n">datetime</span><span class="o">.</span><span class="n">fromtimestamp</span><span class="p">(</span><span class="n">t</span><span class="p">)</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_TIME_FORMAT</span><span class="p">)</span>
</span><span id="L-61"><a href="#L-61"><span class="linenos"> 61</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">globals</span><span class="p">[</span><span class="s2">&quot;timestamp2date&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">timestamp2date</span>
</span><span id="L-62"><a href="#L-62"><span class="linenos"> 62</span></a>
</span><span id="L-63"><a href="#L-63"><span class="linenos"> 63</span></a> <span class="k">def</span> <span class="nf">date2timestamp</span><span class="p">(</span><span class="n">d</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="n">JinjaUndefined</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="o">|</span><span class="nb">str</span><span class="p">:</span>
</span><span id="L-64"><a href="#L-64"><span class="linenos"> 64</span></a> <span class="k">return</span> <span class="s2">&quot;&quot;</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">JinjaUndefined</span><span class="p">)</span> \
</span><span id="L-65"><a href="#L-65"><span class="linenos"> 65</span></a> <span class="k">else</span> <span class="nb">int</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_TIME_FORMAT</span><span class="p">)</span><span class="o">.</span><span class="n">timestamp</span><span class="p">())</span>
</span><span id="L-66"><a href="#L-66"><span class="linenos"> 66</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">globals</span><span class="p">[</span><span class="s2">&quot;date2timestamp&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">date2timestamp</span>
</span><span id="L-67"><a href="#L-67"><span class="linenos"> 67</span></a>
</span><span id="L-68"><a href="#L-68"><span class="linenos"> 68</span></a>
</span><span id="L-69"><a href="#L-69"><span class="linenos"> 69</span></a> <span class="k">def</span> <span class="nf">_add_routers</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="L-70"><a href="#L-70"><span class="linenos"> 70</span></a> <span class="n">interface_router</span> <span class="o">=</span> <span class="n">Interface</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">template</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="p">)</span>
</span><span id="L-71"><a href="#L-71"><span class="linenos"> 71</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">include_router</span><span class="p">(</span><span class="n">interface_router</span><span class="o">.</span><span class="n">router</span><span class="p">)</span>
</span><span id="L-72"><a href="#L-72"><span class="linenos"> 72</span></a>
</span><span id="L-73"><a href="#L-73"><span class="linenos"> 73</span></a> <span class="k">def</span> <span class="nf">_add_routes</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="L-74"><a href="#L-74"><span class="linenos"> 74</span></a>
</span><span id="L-75"><a href="#L-75"><span class="linenos"> 75</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/index&quot;</span><span class="p">,</span> <span class="n">response_class</span><span class="o">=</span><span class="n">HTMLResponse</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Link list&quot;</span><span class="p">)</span>
</span><span id="L-76"><a href="#L-76"><span class="linenos"> 76</span></a> <span class="k">def</span> <span class="nf">index</span><span class="p">(</span><span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">):</span>
</span><span id="L-77"><a href="#L-77"><span class="linenos"> 77</span></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">TemplateResponse</span><span class="p">(</span>
</span><span id="L-78"><a href="#L-78"><span class="linenos"> 78</span></a> <span class="s1">&#39;index.html&#39;</span><span class="p">,</span>
</span><span id="L-79"><a href="#L-79"><span class="linenos"> 79</span></a> <span class="p">{</span><span class="s2">&quot;request&quot;</span> <span class="p">:</span> <span class="n">request</span><span class="p">}</span>
</span><span id="L-80"><a href="#L-80"><span class="linenos"> 80</span></a> <span class="p">)</span>
</span><span id="L-81"><a href="#L-81"><span class="linenos"> 81</span></a>
</span><span id="L-82"><a href="#L-82"><span class="linenos"> 82</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s2">&quot;/message&quot;</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Send a message to the management&quot;</span><span class="p">,</span> <span class="n">tags</span><span class="o">=</span><span class="p">[</span><span class="s1">&#39;agents&#39;</span><span class="p">])</span>
</span><span id="L-83"><a href="#L-83"><span class="linenos"> 83</span></a> <span class="k">def</span> <span class="nf">message</span><span class="p">(</span><span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">,</span> <span class="n">message</span><span class="p">:</span><span class="n">AgentMessage</span><span class="p">,</span> <span class="n">background_tasks</span><span class="p">:</span> <span class="n">BackgroundTasks</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">AgentResponse</span><span class="p">:</span>
</span><span id="L-84"><a href="#L-84"><span class="linenos"> 84</span></a>
</span><span id="L-85"><a href="#L-85"><span class="linenos"> 85</span></a> <span class="n">receiver</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">headers</span><span class="p">[</span><span class="s1">&#39;host&#39;</span><span class="p">]</span>
</span><span id="L-86"><a href="#L-86"><span class="linenos"> 86</span></a> <span class="k">if</span> <span class="s1">&#39;:&#39;</span> <span class="ow">in</span> <span class="n">receiver</span><span class="p">:</span>
</span><span id="L-87"><a href="#L-87"><span class="linenos"> 87</span></a> <span class="n">receiver</span> <span class="o">=</span> <span class="n">receiver</span><span class="p">[:</span><span class="n">receiver</span><span class="o">.</span><span class="n">rindex</span><span class="p">(</span><span class="s1">&#39;:&#39;</span><span class="p">)]</span>
</span><span id="L-88"><a href="#L-88"><span class="linenos"> 88</span></a>
</span><span id="L-89"><a href="#L-89"><span class="linenos"> 89</span></a> <span class="n">sender</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">headers</span><span class="p">[</span><span class="s1">&#39;x-forwarded-for&#39;</span><span class="p">]</span>
</span><span id="L-90"><a href="#L-90"><span class="linenos"> 90</span></a>
</span><span id="L-91"><a href="#L-91"><span class="linenos"> 91</span></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg_process</span><span class="o">.</span><span class="n">new_message</span><span class="p">(</span><span class="n">sender</span><span class="p">,</span> <span class="n">receiver</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">background_tasks</span><span class="p">)</span>
</span><span id="L-92"><a href="#L-92"><span class="linenos"> 92</span></a>
</span><span id="L-93"><a href="#L-93"><span class="linenos"> 93</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/list&quot;</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Get list of messages (like table)&quot;</span><span class="p">,</span> <span class="n">tags</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;cli, agents&quot;</span><span class="p">])</span>
</span><span id="L-94"><a href="#L-94"><span class="linenos"> 94</span></a> <span class="k">def</span> <span class="nf">list</span><span class="p">(</span><span class="nb">id</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">sender</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">recipient</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
</span><span id="L-95"><a href="#L-95"><span class="linenos"> 95</span></a> <span class="n">processed</span><span class="p">:</span><span class="nb">bool</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">solution</span><span class="p">:</span><span class="nb">bool</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
</span><span id="L-96"><a href="#L-96"><span class="linenos"> 96</span></a> <span class="n">time_after</span><span class="p">:</span><span class="nb">int</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">time_before</span><span class="p">:</span><span class="nb">int</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
</span><span id="L-97"><a href="#L-97"><span class="linenos"> 97</span></a> <span class="n">limit</span><span class="p">:</span><span class="nb">int</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span> <span class="n">offset</span><span class="p">:</span><span class="nb">int</span><span class="o">=</span><span class="mi">0</span>
</span><span id="L-98"><a href="#L-98"><span class="linenos"> 98</span></a> <span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">MessageDbRow</span><span class="p">]:</span>
</span><span id="L-99"><a href="#L-99"><span class="linenos"> 99</span></a>
</span><span id="L-100"><a href="#L-100"><span class="linenos">100</span></a> <span class="n">db_args</span> <span class="o">=</span> <span class="p">{</span>
</span><span id="L-101"><a href="#L-101"><span class="linenos">101</span></a> <span class="s2">&quot;limit&quot;</span> <span class="p">:</span> <span class="n">limit</span><span class="p">,</span>
</span><span id="L-102"><a href="#L-102"><span class="linenos">102</span></a> <span class="s2">&quot;offset&quot;</span> <span class="p">:</span> <span class="n">offset</span>
</span><span id="L-103"><a href="#L-103"><span class="linenos">103</span></a> <span class="p">}</span>
</span><span id="L-104"><a href="#L-104"><span class="linenos">104</span></a>
</span><span id="L-105"><a href="#L-105"><span class="linenos">105</span></a> <span class="k">for</span> <span class="n">v</span><span class="p">,</span><span class="n">n</span> <span class="ow">in</span> <span class="p">(</span>
</span><span id="L-106"><a href="#L-106"><span class="linenos">106</span></a> <span class="p">(</span><span class="nb">id</span><span class="p">,</span><span class="s1">&#39;id&#39;</span><span class="p">),</span> <span class="p">(</span><span class="n">sender</span><span class="p">,</span><span class="s1">&#39;sender&#39;</span><span class="p">),</span> <span class="p">(</span><span class="n">recipient</span><span class="p">,</span><span class="s1">&#39;recipient&#39;</span><span class="p">),</span>
</span><span id="L-107"><a href="#L-107"><span class="linenos">107</span></a> <span class="p">(</span><span class="n">processed</span><span class="p">,</span><span class="s1">&#39;processed&#39;</span><span class="p">),</span> <span class="p">(</span><span class="n">solution</span><span class="p">,</span><span class="s1">&#39;solution&#39;</span><span class="p">),</span>
</span><span id="L-108"><a href="#L-108"><span class="linenos">108</span></a> <span class="p">(</span><span class="n">time_after</span><span class="p">,</span> <span class="s1">&#39;time_after&#39;</span><span class="p">),</span> <span class="p">(</span><span class="n">time_before</span><span class="p">,</span> <span class="s1">&#39;time_before&#39;</span><span class="p">)</span>
</span><span id="L-109"><a href="#L-109"><span class="linenos">109</span></a> <span class="p">):</span>
</span><span id="L-110"><a href="#L-110"><span class="linenos">110</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">v</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="L-111"><a href="#L-111"><span class="linenos">111</span></a> <span class="n">db_args</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="o">=</span> <span class="n">v</span>
</span><span id="L-112"><a href="#L-112"><span class="linenos">112</span></a>
</span><span id="L-113"><a href="#L-113"><span class="linenos">113</span></a> <span class="k">return</span> <span class="p">[</span><span class="n">row</span> <span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">iterate</span><span class="p">(</span><span class="o">**</span><span class="n">db_args</span><span class="p">)]</span>
</span><span id="L-114"><a href="#L-114"><span class="linenos">114</span></a>
</span><span id="L-115"><a href="#L-115"><span class="linenos">115</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/list/single&quot;</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Get a single message&quot;</span><span class="p">,</span> <span class="n">tags</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;cli, agents&quot;</span><span class="p">])</span>
</span><span id="L-116"><a href="#L-116"><span class="linenos">116</span></a> <span class="k">def</span> <span class="nf">status</span><span class="p">(</span><span class="n">count</span><span class="p">:</span><span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">MessageDbRow</span><span class="p">:</span>
</span><span id="L-117"><a href="#L-117"><span class="linenos">117</span></a> <span class="n">msg</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">by_count</span><span class="p">(</span><span class="n">count</span><span class="p">)</span>
</span><span id="L-118"><a href="#L-118"><span class="linenos">118</span></a> <span class="k">if</span> <span class="n">msg</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="L-119"><a href="#L-119"><span class="linenos">119</span></a> <span class="k">raise</span> <span class="n">HTTPException</span><span class="p">(</span><span class="n">status_code</span><span class="o">=</span><span class="mi">404</span><span class="p">,</span> <span class="n">detail</span><span class="o">=</span><span class="s2">&quot;Message not found&quot;</span><span class="p">)</span>
</span><span id="L-120"><a href="#L-120"><span class="linenos">120</span></a>
</span><span id="L-121"><a href="#L-121"><span class="linenos">121</span></a> <span class="k">return</span> <span class="n">msg</span>
</span><span id="L-122"><a href="#L-122"><span class="linenos">122</span></a>
</span><span id="L-123"><a href="#L-123"><span class="linenos">123</span></a><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&quot;ums.management.main&quot;</span> <span class="ow">and</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;SERVE&#39;</span><span class="p">,</span> <span class="s1">&#39;false&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="s1">&#39;true&#39;</span><span class="p">:</span>
</span><span id="L-124"><a href="#L-124"><span class="linenos">124</span></a> <span class="n">main</span> <span class="o">=</span> <span class="n">WebMain</span><span class="p">()</span>
</span><span id="L-125"><a href="#L-125"><span class="linenos">125</span></a> <span class="n">app</span> <span class="o">=</span> <span class="n">main</span><span class="o">.</span><span class="n">app</span>
</span></pre></div>
@ -161,66 +205,100 @@
</div>
<a class="headerlink" href="#WebMain"></a>
<div class="pdoc-code codehilite"><pre><span></span><span id="WebMain-22"><a href="#WebMain-22"><span class="linenos">22</span></a><span class="k">class</span> <span class="nc">WebMain</span><span class="p">():</span>
</span><span id="WebMain-23"><a href="#WebMain-23"><span class="linenos">23</span></a>
</span><span id="WebMain-24"><a href="#WebMain-24"><span class="linenos">24</span></a> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="WebMain-25"><a href="#WebMain-25"><span class="linenos">25</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_init_app</span><span class="p">()</span>
</span><span id="WebMain-26"><a href="#WebMain-26"><span class="linenos">26</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_init_templates</span><span class="p">()</span>
</span><span id="WebMain-27"><a href="#WebMain-27"><span class="linenos">27</span></a>
</span><span id="WebMain-28"><a href="#WebMain-28"><span class="linenos">28</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">db</span> <span class="o">=</span> <span class="n">DB</span><span class="p">()</span>
</span><span id="WebMain-29"><a href="#WebMain-29"><span class="linenos">29</span></a>
</span><span id="WebMain-30"><a href="#WebMain-30"><span class="linenos">30</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_add_routes</span><span class="p">()</span>
</span><span id="WebMain-31"><a href="#WebMain-31"><span class="linenos">31</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_add_routers</span><span class="p">()</span>
</span><span id="WebMain-32"><a href="#WebMain-32"><span class="linenos">32</span></a>
</span><span id="WebMain-33"><a href="#WebMain-33"><span class="linenos">33</span></a>
</span><span id="WebMain-34"><a href="#WebMain-34"><span class="linenos">34</span></a> <span class="k">def</span> <span class="nf">_init_app</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="WebMain-35"><a href="#WebMain-35"><span class="linenos">35</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">app</span> <span class="o">=</span> <span class="n">FastAPI</span><span class="p">(</span>
</span><span id="WebMain-36"><a href="#WebMain-36"><span class="linenos">36</span></a> <span class="n">title</span><span class="o">=</span><span class="s2">&quot;Agenten Plattform&quot;</span><span class="p">,</span>
</span><span id="WebMain-37"><a href="#WebMain-37"><span class="linenos">37</span></a> <span class="n">description</span><span class="o">=</span><span class="s2">&quot;Agenten Plattform Management&quot;</span><span class="p">,</span>
</span><span id="WebMain-38"><a href="#WebMain-38"><span class="linenos">38</span></a> <span class="n">openapi_url</span><span class="o">=</span><span class="s2">&quot;/api/schema.json&quot;</span><span class="p">,</span>
</span><span id="WebMain-39"><a href="#WebMain-39"><span class="linenos">39</span></a> <span class="n">docs_url</span><span class="o">=</span><span class="s1">&#39;/api&#39;</span><span class="p">,</span>
</span><span id="WebMain-40"><a href="#WebMain-40"><span class="linenos">40</span></a> <span class="n">redoc_url</span><span class="o">=</span><span class="kc">None</span>
</span><span id="WebMain-41"><a href="#WebMain-41"><span class="linenos">41</span></a> <span class="p">)</span>
</span><span id="WebMain-42"><a href="#WebMain-42"><span class="linenos">42</span></a>
</span><span id="WebMain-43"><a href="#WebMain-43"><span class="linenos">43</span></a> <span class="k">def</span> <span class="nf">_init_templates</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="WebMain-44"><a href="#WebMain-44"><span class="linenos">44</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">template</span> <span class="o">=</span> <span class="n">Jinja2Templates</span><span class="p">(</span>
</span><span id="WebMain-45"><a href="#WebMain-45"><span class="linenos">45</span></a> <span class="n">directory</span><span class="o">=</span><span class="n">TEMPLATE_PATH</span><span class="p">,</span>
</span><span id="WebMain-46"><a href="#WebMain-46"><span class="linenos">46</span></a> <span class="n">auto_reload</span><span class="o">=</span><span class="kc">True</span>
</span><span id="WebMain-47"><a href="#WebMain-47"><span class="linenos">47</span></a> <span class="p">)</span>
</span><span id="WebMain-48"><a href="#WebMain-48"><span class="linenos">48</span></a>
</span><span id="WebMain-49"><a href="#WebMain-49"><span class="linenos">49</span></a> <span class="k">def</span> <span class="nf">_add_routers</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="WebMain-50"><a href="#WebMain-50"><span class="linenos">50</span></a> <span class="n">interface_router</span> <span class="o">=</span> <span class="n">Interface</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">template</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="p">)</span>
</span><span id="WebMain-51"><a href="#WebMain-51"><span class="linenos">51</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">include_router</span><span class="p">(</span><span class="n">interface_router</span><span class="o">.</span><span class="n">router</span><span class="p">)</span>
</span><span id="WebMain-52"><a href="#WebMain-52"><span class="linenos">52</span></a>
</span><span id="WebMain-53"><a href="#WebMain-53"><span class="linenos">53</span></a>
</span><span id="WebMain-54"><a href="#WebMain-54"><span class="linenos">54</span></a> <span class="k">def</span> <span class="nf">_add_routes</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="WebMain-55"><a href="#WebMain-55"><span class="linenos">55</span></a>
</span><span id="WebMain-56"><a href="#WebMain-56"><span class="linenos">56</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/test&quot;</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Test&quot;</span><span class="p">)</span>
</span><span id="WebMain-57"><a href="#WebMain-57"><span class="linenos">57</span></a> <span class="k">def</span> <span class="nf">huhu</span><span class="p">(</span><span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">AgentMessage</span><span class="p">:</span>
</span><span id="WebMain-58"><a href="#WebMain-58"><span class="linenos">58</span></a> <span class="n">ex</span> <span class="o">=</span> <span class="n">AgentMessage</span><span class="p">(</span>
</span><span id="WebMain-59"><a href="#WebMain-59"><span class="linenos">59</span></a> <span class="nb">id</span><span class="o">=</span><span class="s2">&quot;ex1&quot;</span><span class="p">,</span>
</span><span id="WebMain-60"><a href="#WebMain-60"><span class="linenos">60</span></a> <span class="n">riddle</span><span class="o">=</span><span class="p">{</span>
</span><span id="WebMain-61"><a href="#WebMain-61"><span class="linenos">61</span></a> <span class="s2">&quot;context&quot;</span><span class="p">:</span><span class="s2">&quot;Example 1&quot;</span><span class="p">,</span>
</span><span id="WebMain-62"><a href="#WebMain-62"><span class="linenos">62</span></a> <span class="s2">&quot;question&quot;</span><span class="p">:</span><span class="s2">&quot;Get the name of the person.&quot;</span>
</span><span id="WebMain-63"><a href="#WebMain-63"><span class="linenos">63</span></a> <span class="p">},</span>
</span><span id="WebMain-64"><a href="#WebMain-64"><span class="linenos">64</span></a> <span class="n">data</span><span class="o">=</span><span class="p">[</span>
</span><span id="WebMain-65"><a href="#WebMain-65"><span class="linenos">65</span></a> <span class="n">RiddleData</span><span class="p">(</span>
</span><span id="WebMain-66"><a href="#WebMain-66"><span class="linenos">66</span></a> <span class="nb">type</span><span class="o">=</span><span class="n">RiddleDataType</span><span class="o">.</span><span class="n">TEXT</span><span class="p">,</span>
</span><span id="WebMain-67"><a href="#WebMain-67"><span class="linenos">67</span></a> <span class="n">file_plain</span><span class="o">=</span><span class="s2">&quot;./cv.txt&quot;</span>
</span><span id="WebMain-68"><a href="#WebMain-68"><span class="linenos">68</span></a> <span class="p">)</span>
</span><span id="WebMain-69"><a href="#WebMain-69"><span class="linenos">69</span></a> <span class="p">]</span>
</span><span id="WebMain-70"><a href="#WebMain-70"><span class="linenos">70</span></a> <span class="p">)</span>
</span><span id="WebMain-71"><a href="#WebMain-71"><span class="linenos">71</span></a> <span class="n">ex</span><span class="o">.</span><span class="n">status</span><span class="o">.</span><span class="n">extract</span><span class="o">.</span><span class="n">required</span> <span class="o">=</span> <span class="kc">False</span>
</span><span id="WebMain-72"><a href="#WebMain-72"><span class="linenos">72</span></a>
</span><span id="WebMain-73"><a href="#WebMain-73"><span class="linenos">73</span></a> <span class="n">ex</span><span class="o">.</span><span class="n">solution</span> <span class="o">=</span> <span class="n">RiddleSolution</span><span class="p">(</span>
</span><span id="WebMain-74"><a href="#WebMain-74"><span class="linenos">74</span></a> <span class="n">solution</span><span class="o">=</span><span class="s2">&quot;Otto&quot;</span><span class="p">,</span>
</span><span id="WebMain-75"><a href="#WebMain-75"><span class="linenos">75</span></a> <span class="n">explanation</span><span class="o">=</span><span class="s2">&quot;Written in line 6 after &#39;Name:&#39;&quot;</span>
</span><span id="WebMain-76"><a href="#WebMain-76"><span class="linenos">76</span></a> <span class="p">)</span>
</span><span id="WebMain-77"><a href="#WebMain-77"><span class="linenos">77</span></a>
</span><span id="WebMain-78"><a href="#WebMain-78"><span class="linenos">78</span></a> <span class="n">ins_count</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">add_message</span><span class="p">(</span><span class="s1">&#39;from&#39;</span><span class="p">,</span> <span class="s1">&#39;to&#39;</span><span class="p">,</span> <span class="n">ex</span><span class="p">)</span>
</span><span id="WebMain-79"><a href="#WebMain-79"><span class="linenos">79</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">set_processed</span><span class="p">(</span><span class="n">ins_count</span><span class="p">)</span>
</span><span id="WebMain-80"><a href="#WebMain-80"><span class="linenos">80</span></a>
</span><span id="WebMain-81"><a href="#WebMain-81"><span class="linenos">81</span></a> <span class="k">return</span> <span class="n">ex</span>
<div class="pdoc-code codehilite"><pre><span></span><span id="WebMain-29"><a href="#WebMain-29"><span class="linenos"> 29</span></a><span class="k">class</span> <span class="nc">WebMain</span><span class="p">():</span>
</span><span id="WebMain-30"><a href="#WebMain-30"><span class="linenos"> 30</span></a>
</span><span id="WebMain-31"><a href="#WebMain-31"><span class="linenos"> 31</span></a> <span class="n">_TIME_FORMAT</span> <span class="o">=</span> <span class="s2">&quot;%H:%M:%S </span><span class="si">%d</span><span class="s2">.%m.%Y&quot;</span>
</span><span id="WebMain-32"><a href="#WebMain-32"><span class="linenos"> 32</span></a>
</span><span id="WebMain-33"><a href="#WebMain-33"><span class="linenos"> 33</span></a> <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="WebMain-34"><a href="#WebMain-34"><span class="linenos"> 34</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_init_app</span><span class="p">()</span>
</span><span id="WebMain-35"><a href="#WebMain-35"><span class="linenos"> 35</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_init_templates</span><span class="p">()</span>
</span><span id="WebMain-36"><a href="#WebMain-36"><span class="linenos"> 36</span></a>
</span><span id="WebMain-37"><a href="#WebMain-37"><span class="linenos"> 37</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">db</span> <span class="o">=</span> <span class="n">DB</span><span class="p">()</span>
</span><span id="WebMain-38"><a href="#WebMain-38"><span class="linenos"> 38</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">msg_process</span> <span class="o">=</span> <span class="n">MessageProcessor</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="p">)</span>
</span><span id="WebMain-39"><a href="#WebMain-39"><span class="linenos"> 39</span></a>
</span><span id="WebMain-40"><a href="#WebMain-40"><span class="linenos"> 40</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_add_routes</span><span class="p">()</span>
</span><span id="WebMain-41"><a href="#WebMain-41"><span class="linenos"> 41</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">_add_routers</span><span class="p">()</span>
</span><span id="WebMain-42"><a href="#WebMain-42"><span class="linenos"> 42</span></a>
</span><span id="WebMain-43"><a href="#WebMain-43"><span class="linenos"> 43</span></a>
</span><span id="WebMain-44"><a href="#WebMain-44"><span class="linenos"> 44</span></a> <span class="k">def</span> <span class="nf">_init_app</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="WebMain-45"><a href="#WebMain-45"><span class="linenos"> 45</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">app</span> <span class="o">=</span> <span class="n">FastAPI</span><span class="p">(</span>
</span><span id="WebMain-46"><a href="#WebMain-46"><span class="linenos"> 46</span></a> <span class="n">title</span><span class="o">=</span><span class="s2">&quot;Agenten Plattform&quot;</span><span class="p">,</span>
</span><span id="WebMain-47"><a href="#WebMain-47"><span class="linenos"> 47</span></a> <span class="n">description</span><span class="o">=</span><span class="s2">&quot;Agenten Plattform Management&quot;</span><span class="p">,</span>
</span><span id="WebMain-48"><a href="#WebMain-48"><span class="linenos"> 48</span></a> <span class="n">openapi_url</span><span class="o">=</span><span class="s2">&quot;/api/schema.json&quot;</span><span class="p">,</span>
</span><span id="WebMain-49"><a href="#WebMain-49"><span class="linenos"> 49</span></a> <span class="n">docs_url</span><span class="o">=</span><span class="s1">&#39;/api&#39;</span><span class="p">,</span>
</span><span id="WebMain-50"><a href="#WebMain-50"><span class="linenos"> 50</span></a> <span class="n">redoc_url</span><span class="o">=</span><span class="kc">None</span>
</span><span id="WebMain-51"><a href="#WebMain-51"><span class="linenos"> 51</span></a> <span class="p">)</span>
</span><span id="WebMain-52"><a href="#WebMain-52"><span class="linenos"> 52</span></a>
</span><span id="WebMain-53"><a href="#WebMain-53"><span class="linenos"> 53</span></a> <span class="k">def</span> <span class="nf">_init_templates</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="WebMain-54"><a href="#WebMain-54"><span class="linenos"> 54</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">template</span> <span class="o">=</span> <span class="n">Jinja2Templates</span><span class="p">(</span>
</span><span id="WebMain-55"><a href="#WebMain-55"><span class="linenos"> 55</span></a> <span class="n">directory</span><span class="o">=</span><span class="n">TEMPLATE_PATH</span><span class="p">,</span>
</span><span id="WebMain-56"><a href="#WebMain-56"><span class="linenos"> 56</span></a> <span class="n">auto_reload</span><span class="o">=</span><span class="kc">True</span>
</span><span id="WebMain-57"><a href="#WebMain-57"><span class="linenos"> 57</span></a> <span class="p">)</span>
</span><span id="WebMain-58"><a href="#WebMain-58"><span class="linenos"> 58</span></a>
</span><span id="WebMain-59"><a href="#WebMain-59"><span class="linenos"> 59</span></a> <span class="k">def</span> <span class="nf">timestamp2date</span><span class="p">(</span><span class="n">t</span><span class="p">:</span><span class="nb">int</span><span class="o">|</span><span class="n">JinjaUndefined</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span><span id="WebMain-60"><a href="#WebMain-60"><span class="linenos"> 60</span></a> <span class="k">return</span> <span class="s2">&quot;&quot;</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">t</span><span class="p">,</span> <span class="n">JinjaUndefined</span><span class="p">)</span> \
</span><span id="WebMain-61"><a href="#WebMain-61"><span class="linenos"> 61</span></a> <span class="k">else</span> <span class="n">datetime</span><span class="o">.</span><span class="n">fromtimestamp</span><span class="p">(</span><span class="n">t</span><span class="p">)</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_TIME_FORMAT</span><span class="p">)</span>
</span><span id="WebMain-62"><a href="#WebMain-62"><span class="linenos"> 62</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">globals</span><span class="p">[</span><span class="s2">&quot;timestamp2date&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">timestamp2date</span>
</span><span id="WebMain-63"><a href="#WebMain-63"><span class="linenos"> 63</span></a>
</span><span id="WebMain-64"><a href="#WebMain-64"><span class="linenos"> 64</span></a> <span class="k">def</span> <span class="nf">date2timestamp</span><span class="p">(</span><span class="n">d</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="n">JinjaUndefined</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="o">|</span><span class="nb">str</span><span class="p">:</span>
</span><span id="WebMain-65"><a href="#WebMain-65"><span class="linenos"> 65</span></a> <span class="k">return</span> <span class="s2">&quot;&quot;</span> <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="n">JinjaUndefined</span><span class="p">)</span> \
</span><span id="WebMain-66"><a href="#WebMain-66"><span class="linenos"> 66</span></a> <span class="k">else</span> <span class="nb">int</span><span class="p">(</span><span class="n">datetime</span><span class="o">.</span><span class="n">strptime</span><span class="p">(</span><span class="n">d</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_TIME_FORMAT</span><span class="p">)</span><span class="o">.</span><span class="n">timestamp</span><span class="p">())</span>
</span><span id="WebMain-67"><a href="#WebMain-67"><span class="linenos"> 67</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">env</span><span class="o">.</span><span class="n">globals</span><span class="p">[</span><span class="s2">&quot;date2timestamp&quot;</span><span class="p">]</span> <span class="o">=</span> <span class="n">date2timestamp</span>
</span><span id="WebMain-68"><a href="#WebMain-68"><span class="linenos"> 68</span></a>
</span><span id="WebMain-69"><a href="#WebMain-69"><span class="linenos"> 69</span></a>
</span><span id="WebMain-70"><a href="#WebMain-70"><span class="linenos"> 70</span></a> <span class="k">def</span> <span class="nf">_add_routers</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="WebMain-71"><a href="#WebMain-71"><span class="linenos"> 71</span></a> <span class="n">interface_router</span> <span class="o">=</span> <span class="n">Interface</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">template</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="p">)</span>
</span><span id="WebMain-72"><a href="#WebMain-72"><span class="linenos"> 72</span></a> <span class="bp">self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">include_router</span><span class="p">(</span><span class="n">interface_router</span><span class="o">.</span><span class="n">router</span><span class="p">)</span>
</span><span id="WebMain-73"><a href="#WebMain-73"><span class="linenos"> 73</span></a>
</span><span id="WebMain-74"><a href="#WebMain-74"><span class="linenos"> 74</span></a> <span class="k">def</span> <span class="nf">_add_routes</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span><span id="WebMain-75"><a href="#WebMain-75"><span class="linenos"> 75</span></a>
</span><span id="WebMain-76"><a href="#WebMain-76"><span class="linenos"> 76</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/index&quot;</span><span class="p">,</span> <span class="n">response_class</span><span class="o">=</span><span class="n">HTMLResponse</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Link list&quot;</span><span class="p">)</span>
</span><span id="WebMain-77"><a href="#WebMain-77"><span class="linenos"> 77</span></a> <span class="k">def</span> <span class="nf">index</span><span class="p">(</span><span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">):</span>
</span><span id="WebMain-78"><a href="#WebMain-78"><span class="linenos"> 78</span></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">template</span><span class="o">.</span><span class="n">TemplateResponse</span><span class="p">(</span>
</span><span id="WebMain-79"><a href="#WebMain-79"><span class="linenos"> 79</span></a> <span class="s1">&#39;index.html&#39;</span><span class="p">,</span>
</span><span id="WebMain-80"><a href="#WebMain-80"><span class="linenos"> 80</span></a> <span class="p">{</span><span class="s2">&quot;request&quot;</span> <span class="p">:</span> <span class="n">request</span><span class="p">}</span>
</span><span id="WebMain-81"><a href="#WebMain-81"><span class="linenos"> 81</span></a> <span class="p">)</span>
</span><span id="WebMain-82"><a href="#WebMain-82"><span class="linenos"> 82</span></a>
</span><span id="WebMain-83"><a href="#WebMain-83"><span class="linenos"> 83</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">post</span><span class="p">(</span><span class="s2">&quot;/message&quot;</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Send a message to the management&quot;</span><span class="p">,</span> <span class="n">tags</span><span class="o">=</span><span class="p">[</span><span class="s1">&#39;agents&#39;</span><span class="p">])</span>
</span><span id="WebMain-84"><a href="#WebMain-84"><span class="linenos"> 84</span></a> <span class="k">def</span> <span class="nf">message</span><span class="p">(</span><span class="n">request</span><span class="p">:</span> <span class="n">Request</span><span class="p">,</span> <span class="n">message</span><span class="p">:</span><span class="n">AgentMessage</span><span class="p">,</span> <span class="n">background_tasks</span><span class="p">:</span> <span class="n">BackgroundTasks</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">AgentResponse</span><span class="p">:</span>
</span><span id="WebMain-85"><a href="#WebMain-85"><span class="linenos"> 85</span></a>
</span><span id="WebMain-86"><a href="#WebMain-86"><span class="linenos"> 86</span></a> <span class="n">receiver</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">headers</span><span class="p">[</span><span class="s1">&#39;host&#39;</span><span class="p">]</span>
</span><span id="WebMain-87"><a href="#WebMain-87"><span class="linenos"> 87</span></a> <span class="k">if</span> <span class="s1">&#39;:&#39;</span> <span class="ow">in</span> <span class="n">receiver</span><span class="p">:</span>
</span><span id="WebMain-88"><a href="#WebMain-88"><span class="linenos"> 88</span></a> <span class="n">receiver</span> <span class="o">=</span> <span class="n">receiver</span><span class="p">[:</span><span class="n">receiver</span><span class="o">.</span><span class="n">rindex</span><span class="p">(</span><span class="s1">&#39;:&#39;</span><span class="p">)]</span>
</span><span id="WebMain-89"><a href="#WebMain-89"><span class="linenos"> 89</span></a>
</span><span id="WebMain-90"><a href="#WebMain-90"><span class="linenos"> 90</span></a> <span class="n">sender</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">headers</span><span class="p">[</span><span class="s1">&#39;x-forwarded-for&#39;</span><span class="p">]</span>
</span><span id="WebMain-91"><a href="#WebMain-91"><span class="linenos"> 91</span></a>
</span><span id="WebMain-92"><a href="#WebMain-92"><span class="linenos"> 92</span></a> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">msg_process</span><span class="o">.</span><span class="n">new_message</span><span class="p">(</span><span class="n">sender</span><span class="p">,</span> <span class="n">receiver</span><span class="p">,</span> <span class="n">message</span><span class="p">,</span> <span class="n">background_tasks</span><span class="p">)</span>
</span><span id="WebMain-93"><a href="#WebMain-93"><span class="linenos"> 93</span></a>
</span><span id="WebMain-94"><a href="#WebMain-94"><span class="linenos"> 94</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/list&quot;</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Get list of messages (like table)&quot;</span><span class="p">,</span> <span class="n">tags</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;cli, agents&quot;</span><span class="p">])</span>
</span><span id="WebMain-95"><a href="#WebMain-95"><span class="linenos"> 95</span></a> <span class="k">def</span> <span class="nf">list</span><span class="p">(</span><span class="nb">id</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">sender</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">recipient</span><span class="p">:</span><span class="nb">str</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
</span><span id="WebMain-96"><a href="#WebMain-96"><span class="linenos"> 96</span></a> <span class="n">processed</span><span class="p">:</span><span class="nb">bool</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">solution</span><span class="p">:</span><span class="nb">bool</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
</span><span id="WebMain-97"><a href="#WebMain-97"><span class="linenos"> 97</span></a> <span class="n">time_after</span><span class="p">:</span><span class="nb">int</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span> <span class="n">time_before</span><span class="p">:</span><span class="nb">int</span><span class="o">|</span><span class="kc">None</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span>
</span><span id="WebMain-98"><a href="#WebMain-98"><span class="linenos"> 98</span></a> <span class="n">limit</span><span class="p">:</span><span class="nb">int</span><span class="o">=</span><span class="mi">10</span><span class="p">,</span> <span class="n">offset</span><span class="p">:</span><span class="nb">int</span><span class="o">=</span><span class="mi">0</span>
</span><span id="WebMain-99"><a href="#WebMain-99"><span class="linenos"> 99</span></a> <span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">MessageDbRow</span><span class="p">]:</span>
</span><span id="WebMain-100"><a href="#WebMain-100"><span class="linenos">100</span></a>
</span><span id="WebMain-101"><a href="#WebMain-101"><span class="linenos">101</span></a> <span class="n">db_args</span> <span class="o">=</span> <span class="p">{</span>
</span><span id="WebMain-102"><a href="#WebMain-102"><span class="linenos">102</span></a> <span class="s2">&quot;limit&quot;</span> <span class="p">:</span> <span class="n">limit</span><span class="p">,</span>
</span><span id="WebMain-103"><a href="#WebMain-103"><span class="linenos">103</span></a> <span class="s2">&quot;offset&quot;</span> <span class="p">:</span> <span class="n">offset</span>
</span><span id="WebMain-104"><a href="#WebMain-104"><span class="linenos">104</span></a> <span class="p">}</span>
</span><span id="WebMain-105"><a href="#WebMain-105"><span class="linenos">105</span></a>
</span><span id="WebMain-106"><a href="#WebMain-106"><span class="linenos">106</span></a> <span class="k">for</span> <span class="n">v</span><span class="p">,</span><span class="n">n</span> <span class="ow">in</span> <span class="p">(</span>
</span><span id="WebMain-107"><a href="#WebMain-107"><span class="linenos">107</span></a> <span class="p">(</span><span class="nb">id</span><span class="p">,</span><span class="s1">&#39;id&#39;</span><span class="p">),</span> <span class="p">(</span><span class="n">sender</span><span class="p">,</span><span class="s1">&#39;sender&#39;</span><span class="p">),</span> <span class="p">(</span><span class="n">recipient</span><span class="p">,</span><span class="s1">&#39;recipient&#39;</span><span class="p">),</span>
</span><span id="WebMain-108"><a href="#WebMain-108"><span class="linenos">108</span></a> <span class="p">(</span><span class="n">processed</span><span class="p">,</span><span class="s1">&#39;processed&#39;</span><span class="p">),</span> <span class="p">(</span><span class="n">solution</span><span class="p">,</span><span class="s1">&#39;solution&#39;</span><span class="p">),</span>
</span><span id="WebMain-109"><a href="#WebMain-109"><span class="linenos">109</span></a> <span class="p">(</span><span class="n">time_after</span><span class="p">,</span> <span class="s1">&#39;time_after&#39;</span><span class="p">),</span> <span class="p">(</span><span class="n">time_before</span><span class="p">,</span> <span class="s1">&#39;time_before&#39;</span><span class="p">)</span>
</span><span id="WebMain-110"><a href="#WebMain-110"><span class="linenos">110</span></a> <span class="p">):</span>
</span><span id="WebMain-111"><a href="#WebMain-111"><span class="linenos">111</span></a> <span class="k">if</span> <span class="ow">not</span> <span class="n">v</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="WebMain-112"><a href="#WebMain-112"><span class="linenos">112</span></a> <span class="n">db_args</span><span class="p">[</span><span class="n">n</span><span class="p">]</span> <span class="o">=</span> <span class="n">v</span>
</span><span id="WebMain-113"><a href="#WebMain-113"><span class="linenos">113</span></a>
</span><span id="WebMain-114"><a href="#WebMain-114"><span class="linenos">114</span></a> <span class="k">return</span> <span class="p">[</span><span class="n">row</span> <span class="k">for</span> <span class="n">row</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">iterate</span><span class="p">(</span><span class="o">**</span><span class="n">db_args</span><span class="p">)]</span>
</span><span id="WebMain-115"><a href="#WebMain-115"><span class="linenos">115</span></a>
</span><span id="WebMain-116"><a href="#WebMain-116"><span class="linenos">116</span></a> <span class="nd">@self</span><span class="o">.</span><span class="n">app</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s2">&quot;/list/single&quot;</span><span class="p">,</span> <span class="n">summary</span><span class="o">=</span><span class="s2">&quot;Get a single message&quot;</span><span class="p">,</span> <span class="n">tags</span><span class="o">=</span><span class="p">[</span><span class="s2">&quot;cli, agents&quot;</span><span class="p">])</span>
</span><span id="WebMain-117"><a href="#WebMain-117"><span class="linenos">117</span></a> <span class="k">def</span> <span class="nf">status</span><span class="p">(</span><span class="n">count</span><span class="p">:</span><span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">MessageDbRow</span><span class="p">:</span>
</span><span id="WebMain-118"><a href="#WebMain-118"><span class="linenos">118</span></a> <span class="n">msg</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">db</span><span class="o">.</span><span class="n">by_count</span><span class="p">(</span><span class="n">count</span><span class="p">)</span>
</span><span id="WebMain-119"><a href="#WebMain-119"><span class="linenos">119</span></a> <span class="k">if</span> <span class="n">msg</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span><span id="WebMain-120"><a href="#WebMain-120"><span class="linenos">120</span></a> <span class="k">raise</span> <span class="n">HTTPException</span><span class="p">(</span><span class="n">status_code</span><span class="o">=</span><span class="mi">404</span><span class="p">,</span> <span class="n">detail</span><span class="o">=</span><span class="s2">&quot;Message not found&quot;</span><span class="p">)</span>
</span><span id="WebMain-121"><a href="#WebMain-121"><span class="linenos">121</span></a>
</span><span id="WebMain-122"><a href="#WebMain-122"><span class="linenos">122</span></a> <span class="k">return</span> <span class="n">msg</span>
</span></pre></div>
@ -236,6 +314,17 @@
</div>
<div id="WebMain.msg_process" class="classattr">
<div class="attr variable">
<span class="name">msg_process</span>
</div>
<a class="headerlink" href="#WebMain.msg_process"></a>
</div>
</section>
</main>

File diff suppressed because one or more lines are too long

View File

@ -32,9 +32,19 @@
<h2>Submodules</h2>
<ul>
<li><a href="utils/const.html">const</a></li>
<li><a href="utils/functions.html">functions</a></li>
<li><a href="utils/request.html">request</a></li>
<li><a href="utils/schema.html">schema</a></li>
<li><a href="utils/types.html">types</a></li>
</ul>
<h2>API Documentation</h2>
<ul class="memberlist">
<li>
<a class="variable" href="#logger">logger</a>
</li>
</ul>
<a class="attribution" title="pdoc: Python API documentation generator" href="https://pdoc.dev" target="_blank">
@ -64,21 +74,58 @@
</span><span id="L-8"><a href="#L-8"><span class="linenos"> 8</span></a><span class="c1"># source code released under the terms of GNU Public License Version 3</span>
</span><span id="L-9"><a href="#L-9"><span class="linenos"> 9</span></a><span class="c1"># https://www.gnu.org/licenses/gpl-3.0.txt</span>
</span><span id="L-10"><a href="#L-10"><span class="linenos">10</span></a>
</span><span id="L-11"><a href="#L-11"><span class="linenos">11</span></a><span class="kn">from</span> <span class="nn">ums.utils.types</span> <span class="kn">import</span> <span class="p">(</span>
</span><span id="L-12"><a href="#L-12"><span class="linenos">12</span></a> <span class="n">RiddleInformation</span><span class="p">,</span>
</span><span id="L-13"><a href="#L-13"><span class="linenos">13</span></a> <span class="n">AgentMessage</span><span class="p">,</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a> <span class="n">Riddle</span><span class="p">,</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a> <span class="n">RiddleSolution</span><span class="p">,</span>
</span><span id="L-16"><a href="#L-16"><span class="linenos">16</span></a> <span class="n">RiddleData</span><span class="p">,</span>
</span><span id="L-17"><a href="#L-17"><span class="linenos">17</span></a> <span class="n">RiddleDataType</span><span class="p">,</span>
</span><span id="L-18"><a href="#L-18"><span class="linenos">18</span></a> <span class="n">RiddleStatus</span>
</span><span id="L-19"><a href="#L-19"><span class="linenos">19</span></a><span class="p">)</span>
</span><span id="L-20"><a href="#L-20"><span class="linenos">20</span></a>
</span><span id="L-21"><a href="#L-21"><span class="linenos">21</span></a><span class="kn">from</span> <span class="nn">ums.utils.const</span> <span class="kn">import</span> <span class="o">*</span>
</span><span id="L-11"><a href="#L-11"><span class="linenos">11</span></a><span class="kn">from</span> <span class="nn">ums.utils.const</span> <span class="kn">import</span> <span class="o">*</span>
</span><span id="L-12"><a href="#L-12"><span class="linenos">12</span></a>
</span><span id="L-13"><a href="#L-13"><span class="linenos">13</span></a><span class="kn">import</span> <span class="nn">logging</span><span class="o">,</span> <span class="nn">os</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a><span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;SERVE&#39;</span><span class="p">,</span> <span class="s1">&#39;false&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span> <span class="o">==</span> <span class="s1">&#39;true&#39;</span><span class="p">:</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a> <span class="n">logging</span><span class="o">.</span><span class="n">basicConfig</span><span class="p">(</span>
</span><span id="L-16"><a href="#L-16"><span class="linenos">16</span></a> <span class="n">handlers</span><span class="o">=</span><span class="p">[</span>
</span><span id="L-17"><a href="#L-17"><span class="linenos">17</span></a> <span class="n">logging</span><span class="o">.</span><span class="n">FileHandler</span><span class="p">(</span><span class="n">LOG_FILE</span><span class="p">),</span>
</span><span id="L-18"><a href="#L-18"><span class="linenos">18</span></a> <span class="n">logging</span><span class="o">.</span><span class="n">StreamHandler</span><span class="p">()</span>
</span><span id="L-19"><a href="#L-19"><span class="linenos">19</span></a> <span class="p">],</span>
</span><span id="L-20"><a href="#L-20"><span class="linenos">20</span></a> <span class="n">level</span><span class="o">=</span><span class="n">LOG_LEVEL</span><span class="p">,</span>
</span><span id="L-21"><a href="#L-21"><span class="linenos">21</span></a> <span class="nb">format</span><span class="o">=</span><span class="s1">&#39;</span><span class="si">%(asctime)s</span><span class="s1"> </span><span class="si">%(levelname)s</span><span class="s1"> </span><span class="si">%(name)s</span><span class="s1">: </span><span class="si">%(message)s</span><span class="s1">&#39;</span><span class="p">,</span>
</span><span id="L-22"><a href="#L-22"><span class="linenos">22</span></a> <span class="n">datefmt</span><span class="o">=</span><span class="s1">&#39;%Y-%m-</span><span class="si">%d</span><span class="s1"> %H:%M:%S&#39;</span>
</span><span id="L-23"><a href="#L-23"><span class="linenos">23</span></a> <span class="p">)</span>
</span><span id="L-24"><a href="#L-24"><span class="linenos">24</span></a><span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="s1">&#39;UMS Agenten&#39;</span><span class="p">)</span>
</span><span id="L-25"><a href="#L-25"><span class="linenos">25</span></a>
</span><span id="L-26"><a href="#L-26"><span class="linenos">26</span></a><span class="kn">from</span> <span class="nn">ums.utils.types</span> <span class="kn">import</span> <span class="p">(</span>
</span><span id="L-27"><a href="#L-27"><span class="linenos">27</span></a> <span class="n">RiddleInformation</span><span class="p">,</span>
</span><span id="L-28"><a href="#L-28"><span class="linenos">28</span></a> <span class="n">AgentMessage</span><span class="p">,</span>
</span><span id="L-29"><a href="#L-29"><span class="linenos">29</span></a> <span class="n">Riddle</span><span class="p">,</span>
</span><span id="L-30"><a href="#L-30"><span class="linenos">30</span></a> <span class="n">RiddleSolution</span><span class="p">,</span>
</span><span id="L-31"><a href="#L-31"><span class="linenos">31</span></a> <span class="n">RiddleData</span><span class="p">,</span>
</span><span id="L-32"><a href="#L-32"><span class="linenos">32</span></a> <span class="n">RiddleDataType</span><span class="p">,</span>
</span><span id="L-33"><a href="#L-33"><span class="linenos">33</span></a> <span class="n">RiddleStatus</span><span class="p">,</span>
</span><span id="L-34"><a href="#L-34"><span class="linenos">34</span></a> <span class="n">AgentResponse</span><span class="p">,</span>
</span><span id="L-35"><a href="#L-35"><span class="linenos">35</span></a> <span class="n">MessageDbRow</span>
</span><span id="L-36"><a href="#L-36"><span class="linenos">36</span></a><span class="p">)</span>
</span><span id="L-37"><a href="#L-37"><span class="linenos">37</span></a>
</span><span id="L-38"><a href="#L-38"><span class="linenos">38</span></a><span class="kn">from</span> <span class="nn">ums.utils.request</span> <span class="kn">import</span> <span class="n">ManagementRequest</span>
</span><span id="L-39"><a href="#L-39"><span class="linenos">39</span></a>
</span><span id="L-40"><a href="#L-40"><span class="linenos">40</span></a><span class="kn">from</span> <span class="nn">ums.utils.functions</span> <span class="kn">import</span> <span class="n">list_shared_data</span><span class="p">,</span> <span class="n">list_shared_schema</span>
</span><span id="L-41"><a href="#L-41"><span class="linenos">41</span></a>
</span><span id="L-42"><a href="#L-42"><span class="linenos">42</span></a><span class="kn">from</span> <span class="nn">ums.utils.schema</span> <span class="kn">import</span> <span class="p">(</span>
</span><span id="L-43"><a href="#L-43"><span class="linenos">43</span></a> <span class="n">ExtractionSchema</span><span class="p">,</span>
</span><span id="L-44"><a href="#L-44"><span class="linenos">44</span></a> <span class="n">ExtractedData</span><span class="p">,</span>
</span><span id="L-45"><a href="#L-45"><span class="linenos">45</span></a> <span class="n">ExtractedContent</span><span class="p">,</span> <span class="n">ExtractedPositions</span>
</span><span id="L-46"><a href="#L-46"><span class="linenos">46</span></a><span class="p">)</span>
</span></pre></div>
</section>
<section id="logger">
<div class="attr variable">
<span class="name">logger</span> =
<span class="default_value">&lt;Logger UMS Agenten (WARNING)&gt;</span>
</div>
<a class="headerlink" href="#logger"></a>
</section>
</main>
<script>
function escapeHTML(html) {

View File

@ -41,9 +41,18 @@
<li>
<a class="variable" href="#PERSIST_PATH">PERSIST_PATH</a>
</li>
<li>
<a class="variable" href="#PUBLIC_PATH">PUBLIC_PATH</a>
</li>
<li>
<a class="variable" href="#TEMPLATE_PATH">TEMPLATE_PATH</a>
</li>
<li>
<a class="variable" href="#LOG_FILE">LOG_FILE</a>
</li>
<li>
<a class="variable" href="#LOG_LEVEL">LOG_LEVEL</a>
</li>
</ul>
@ -83,12 +92,16 @@ See the content ...</p>
</span><span id="L-13"><a href="#L-13"><span class="linenos">13</span></a><span class="sd"> See the content ...</span>
</span><span id="L-14"><a href="#L-14"><span class="linenos">14</span></a><span class="sd">&quot;&quot;&quot;</span>
</span><span id="L-15"><a href="#L-15"><span class="linenos">15</span></a>
</span><span id="L-16"><a href="#L-16"><span class="linenos">16</span></a><span class="kn">import</span> <span class="nn">os</span>
</span><span id="L-16"><a href="#L-16"><span class="linenos">16</span></a><span class="kn">import</span> <span class="nn">os</span><span class="o">,</span> <span class="nn">logging</span>
</span><span id="L-17"><a href="#L-17"><span class="linenos">17</span></a>
</span><span id="L-18"><a href="#L-18"><span class="linenos">18</span></a><span class="n">BASE_PATH</span> <span class="o">=</span> <span class="s1">&#39;/ums-agenten&#39;</span>
</span><span id="L-19"><a href="#L-19"><span class="linenos">19</span></a><span class="n">SHARE_PATH</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">BASE_PATH</span><span class="p">,</span> <span class="s1">&#39;share&#39;</span><span class="p">)</span>
</span><span id="L-20"><a href="#L-20"><span class="linenos">20</span></a><span class="n">PERSIST_PATH</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">BASE_PATH</span><span class="p">,</span> <span class="s1">&#39;persist&#39;</span><span class="p">)</span>
</span><span id="L-21"><a href="#L-21"><span class="linenos">21</span></a><span class="n">TEMPLATE_PATH</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">BASE_PATH</span><span class="p">,</span> <span class="s1">&#39;plattform&#39;</span><span class="p">,</span> <span class="s1">&#39;web&#39;</span><span class="p">,</span> <span class="s1">&#39;templates&#39;</span><span class="p">)</span>
</span><span id="L-21"><a href="#L-21"><span class="linenos">21</span></a><span class="n">PUBLIC_PATH</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">BASE_PATH</span><span class="p">,</span> <span class="s1">&#39;plattform&#39;</span><span class="p">,</span> <span class="s1">&#39;web&#39;</span><span class="p">,</span> <span class="s1">&#39;public&#39;</span><span class="p">)</span>
</span><span id="L-22"><a href="#L-22"><span class="linenos">22</span></a><span class="n">TEMPLATE_PATH</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">BASE_PATH</span><span class="p">,</span> <span class="s1">&#39;plattform&#39;</span><span class="p">,</span> <span class="s1">&#39;web&#39;</span><span class="p">,</span> <span class="s1">&#39;templates&#39;</span><span class="p">)</span>
</span><span id="L-23"><a href="#L-23"><span class="linenos">23</span></a>
</span><span id="L-24"><a href="#L-24"><span class="linenos">24</span></a><span class="n">LOG_FILE</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">PERSIST_PATH</span><span class="p">,</span> <span class="s1">&#39;ums.log&#39;</span><span class="p">)</span>
</span><span id="L-25"><a href="#L-25"><span class="linenos">25</span></a><span class="n">LOG_LEVEL</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">INFO</span>
</span></pre></div>
@ -128,6 +141,18 @@ See the content ...</p>
</section>
<section id="PUBLIC_PATH">
<div class="attr variable">
<span class="name">PUBLIC_PATH</span> =
<span class="default_value">&#39;/ums-agenten/plattform/web/public&#39;</span>
</div>
<a class="headerlink" href="#PUBLIC_PATH"></a>
</section>
<section id="TEMPLATE_PATH">
<div class="attr variable">
@ -140,6 +165,30 @@ See the content ...</p>
</section>
<section id="LOG_FILE">
<div class="attr variable">
<span class="name">LOG_FILE</span> =
<span class="default_value">&#39;/ums-agenten/persist/ums.log&#39;</span>
</div>
<a class="headerlink" href="#LOG_FILE"></a>
</section>
<section id="LOG_LEVEL">
<div class="attr variable">
<span class="name">LOG_LEVEL</span> =
<span class="default_value">20</span>
</div>
<a class="headerlink" href="#LOG_LEVEL"></a>
</section>
</main>
<script>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -1,14 +0,0 @@
<html>
<head>
<title>UMS-Agenten &ndash; Management</title>
</head>
<body>
<h1>UMS-Agenten &ndash; Management</h1>
<ul>
<li><a href="/app/" target="_blank">Web App (small GUI)</a></li>
<li><a href="/app/new" target="_blank">Add Riddle via GUI</a></li>
<li><a href="/api/" target="_blank">API Documentations</a></li>
<li><a href="/docs/" target="_blank">Code Documentation</a></li>
</ul>
</body>
</html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

6
web/public/static/bootstrap.min.css vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

2
web/public/static/jquery.min.js vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,16 @@
/** Agenten Plattform
(c) 2024 Magnus Bender
Institute of Humanities-Centered Artificial Intelligence (CHAI)
Universitaet Hamburg
https://www.chai.uni-hamburg.de/~bender
source code released under the terms of GNU Public License Version 3
https://www.gnu.org/licenses/gpl-3.0.txt
**/
.value_filter {
width: 150px;
}
#message_content{
height: 300px;
}

126
web/public/static/new.js Normal file
View File

@ -0,0 +1,126 @@
/** Agenten Plattform
(c) 2024 Magnus Bender
Institute of Humanities-Centered Artificial Intelligence (CHAI)
Universitaet Hamburg
https://www.chai.uni-hamburg.de/~bender
source code released under the terms of GNU Public License Version 3
https://www.gnu.org/licenses/gpl-3.0.txt
**/
var fileLast = 0;
function renderFile(cnt, type="", file_extracted="", file_plain=""){
var template = $("#filesTemplate").html();
template = template.replaceAll('{cnt}', cnt)
.replaceAll('{file_extracted}', file_extracted)
.replaceAll('{file_extracted}', file_extracted)
.replaceAll('{file_plain}', file_plain);
['text', 'image', 'audio'].forEach((t)=>{
template = template.replaceAll('{'+t+'_selected}', t === type ? 'selected' : '' );
});
$("#filesRender").append(template);
$("button#removeFile"+cnt).click( () => {
$("#filesRow" + cnt).remove();
update_json_message()
});
fileLast = cnt;
}
$("#addFile").click(() => renderFile(++fileLast));
function update_json_message(){
let message = JSON.parse(basic_message);
var store_values = {}
$(".message-attribute").each((_,v)=>{
let el = $(v);
let name = el.attr('name');
let val = el.attr("type") == "checkbox" ? el.prop('checked') : el.val();
// optional fields (empty => null)
if( name.endsWith("file_extracted") && val.length == 0 ){
val = null;
}
store_values[name] = val;
let curr_msg = message;
let last_ob = {};
let last_name = "";
name.split('.').forEach((e)=>{
last_ob = curr_msg;
last_name = e;
if( !curr_msg.hasOwnProperty(e) ){
curr_msg[e] = {}
}
curr_msg = curr_msg[e];
});
last_ob[last_name] = val;
});
localStorage.setItem("new_riddle", JSON.stringify(store_values))
// fix array for data
if(message.hasOwnProperty('data')){
var data_items = message['data'];
message['data'] = [];
Object.keys(data_items).forEach((v)=>{
if( v !== null){
message['data'].push(data_items[v]);
}
});
}
$("#message_content").val(JSON.stringify(message, null, 2));
}
function load_last_values(){
if(localStorage.getItem("new_riddle") !== null){
var items = JSON.parse(localStorage.getItem("new_riddle"))
console.log(items)
Object.keys(items).forEach((k)=>{
// if data, create the file select for this id
if(k.startsWith('data.') && $("[name='"+k+"']").length == 0){
renderFile(parseInt(k.substring(5, k.indexOf('.',5))))
}
let el = $("[name='"+k+"']");
if(el.attr("type") == "checkbox"){
el.prop('checked', items[k]);
}
else{
el.val(items[k]);
}
});
update_json_message()
}
}
load_last_values();
$( document ).on( "change", ".message-attribute", update_json_message)
$( document ).on( "click", ".message-attribute[type=checkbox]", update_json_message)
function send_json_message(json_str){
$.ajax(
"/message",
{
contentType : 'application/json',
type : 'POST',
data: json_str,
},
).then((d) => {
$("#message_sent .modal-title").text("Message Sent");
$("#message_sent .modal-body").html('<pre>'+JSON.stringify(d, null, 2)+'</pre>');
new bootstrap.Modal('#message_sent').show();
}).fail((d)=>{
$("#message_sent .modal-title").text("Error Sending Message");
$("#message_sent .modal-body").html('<pre>'+JSON.stringify(d, null, 2)+'</pre>');
new bootstrap.Modal('#message_sent').show();
});
}
$("#send_message").click(
() => send_json_message($("#message_content").val())
);

View File

@ -0,0 +1,65 @@
/** Agenten Plattform
(c) 2024 Magnus Bender
Institute of Humanities-Centered Artificial Intelligence (CHAI)
Universitaet Hamburg
https://www.chai.uni-hamburg.de/~bender
source code released under the terms of GNU Public License Version 3
https://www.gnu.org/licenses/gpl-3.0.txt
**/
function pagination_link(name, value){
let link_args = db_args;
if (name && value){
link_args[name] = value;
}
else if(name){
delete link_args[name];
}
return '?' + $.param( link_args );
}
$(".value_filter").change((e)=>{
window.location = pagination_link($(e.target).attr('name').substr('filter_'.length), $(e.target).val())
});
function enable_auto_refresh(){
setInterval( () => {
if($('#autoRefresh').prop('checked')){
$.get(
'/app/table/total' + pagination_link(),
(v) => {
if( v != db_total ){
window.location = pagination_link()
}
}
);
}
}, 1000);
sessionStorage.setItem('auto_refresh', $('#autoRefresh').prop('checked'));
}
$("#autoRefresh").click(enable_auto_refresh);
if(sessionStorage.hasOwnProperty('auto_refresh') && sessionStorage.getItem('auto_refresh') === 'true'){
$("#autoRefresh").prop('checked', true);
enable_auto_refresh()
}
function send_json_message(json_str){
$.ajax(
"/message",
{
contentType : 'application/json',
type : 'POST',
data: json_str,
},
).then((d) => {
$("#message_sent .modal-title").text("Message Sent");
$("#message_sent .modal-body").html('<pre>'+JSON.stringify(d, null, 2)+'</pre>');
new bootstrap.Modal('#message_sent').show();
}).fail((d)=>{
$("#message_sent .modal-title").text("Error Sending Message");
$("#message_sent .modal-body").html('<pre>'+JSON.stringify(d, null, 2)+'</pre>');
new bootstrap.Modal('#message_sent').show();
});
}
$(".send_message_again").click(
(e) => send_json_message( $("pre#row_message_raw_"+$(e.target).attr('idx')).text() )
);

49
web/templates/base.html Normal file
View File

@ -0,0 +1,49 @@
{#-
Agenten Plattform
(c) 2024 Magnus Bender
Institute of Humanities-Centered Artificial Intelligence (CHAI)
Universitaet Hamburg
https://www.chai.uni-hamburg.de/~bender
source code released under the terms of GNU Public License Version 3
https://www.gnu.org/licenses/gpl-3.0.txt
-#}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<link rel="stylesheet" href="/static/bootstrap.min.css" />
<link rel="stylesheet" href="/static/main.css" />
<script src="/static/jquery.min.js"></script>
<script src="/static/bootstrap.bundle.min.js"></script>
<title>{{title}} &ndash; MGMT</title>
<!--
Agenten Plattform
(c) 2024 Magnus Bender
Institute of Humanities-Centered Artificial Intelligence (CHAI)
Universitaet Hamburg
https://www.chai.uni-hamburg.de/~bender
source code released under the terms of GNU Public License Version 3
https://www.gnu.org/licenses/gpl-3.0.txt
-->
{% block morehead %}
{% endblock %}
</head>
<body>
<div class="container">
<h1>{{title}} &ndash; MGMT</h1>
{% block maincontent %}
{% endblock %}
</div>
{% block morefoot %}
{% endblock %}
</body>
</html>

20
web/templates/index.html Normal file
View File

@ -0,0 +1,20 @@
{#-
Agenten Plattform
(c) 2024 Magnus Bender
Institute of Humanities-Centered Artificial Intelligence (CHAI)
Universitaet Hamburg
https://www.chai.uni-hamburg.de/~bender
source code released under the terms of GNU Public License Version 3
https://www.gnu.org/licenses/gpl-3.0.txt
-#}
{% extends "base.html" %}
{% set title = "Overview" %}
{% block maincontent %}
<ul>
<li><a href="/app/table" target="_blank">&nearr; Web App: Table</a></li>
<li><a href="/app/new" target="_blank">&nearr; Web App: New Riddle</a></li>
<li><a href="/share/" target="_blank">&nearr; Data: Access the riddle files</a></li>
<li><a href="/api" target="_blank">&nearr; Documentation: API </a></li>
<li><a href="/docs/" target="_blank">&nearr; Documentation: Code </a></li>
</ul>
{% endblock %}

21
web/templates/modal.html Normal file
View File

@ -0,0 +1,21 @@
{#-
Agenten Plattform
(c) 2024 Magnus Bender
Institute of Humanities-Centered Artificial Intelligence (CHAI)
Universitaet Hamburg
https://www.chai.uni-hamburg.de/~bender
source code released under the terms of GNU Public License Version 3
https://www.gnu.org/licenses/gpl-3.0.txt
-#}
<div class="modal" tabindex="-1" id="message_sent">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title"></h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
</div>
</div>
</div>
</div>

129
web/templates/new.html Normal file
View File

@ -0,0 +1,129 @@
{#-
Agenten Plattform
(c) 2024 Magnus Bender
Institute of Humanities-Centered Artificial Intelligence (CHAI)
Universitaet Hamburg
https://www.chai.uni-hamburg.de/~bender
source code released under the terms of GNU Public License Version 3
https://www.gnu.org/licenses/gpl-3.0.txt
-#}
{% extends "base.html" %}
{% set title = "New" %}
{% block maincontent %}
<div class="row">
<div class="col">
</div>
<div class="col">
<a href="/app/table" class="btn btn-secondary">&larr; Back to Messages</a>
</div>
</div>
<h2>Create New Riddle</h2>
<div class="mb-3">
<label for="message_id" class="form-label">Riddle ID</label>
<input type="text" name="id" class="message-attribute form-control" id="message_id">
</div>
<div class="mb-3">
<label for="message_id" class="form-label">Riddle Question</label>
<input type="text" name="riddle.question" class="message-attribute form-control" id="message_id">
</div>
<div class="mb-3">
<label for="message_context" class="form-label">Riddle Context</label>
<textarea class="form-control message-attribute" name="riddle.context" id="message_context" rows="2"></textarea>
</div>
<h3>Steps</h3>
<div class="mb-3">
<div class="form-check form-check-inline">
<input class="form-check-input message-attribute" name="status.extract.required" type="checkbox" id="message_extract" value="true" checked>
<label class="form-check-label" for="message_extract">Extract</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input message-attribute" name="status.solve.required" type="checkbox" id="message_solve" value="true" checked>
<label class="form-check-label" for="message_solve">Solve</label>
</div>
<div class="form-check form-check-inline">
<input class="form-check-input message-attribute" name="status.validate.required" type="checkbox" id="message_validate" value="true" checked>
<label class="form-check-label" for="message_validate">Validate</label>
</div>
</div>
<h3>Files</h3>
<p>
Manually add files to the shared directory and then select them here to assign them to a riddle.
Shared directory is <code>{{SHARE_PATH}}</code> which should be linked to the host using docker to, e.g., <code>./data/share</code>.
</p>
<datalist id="dataFiles">
{% for f in shared_data %}
<option value="{{f}}">
{% endfor %}
</datalist>
<datalist id="schemaFiles">
{% for f in shared_schema %}
<option value="{{f}}">
{% endfor %}
</datalist>
<template id="filesTemplate">
<div class="mb-3 row" id="filesRow{cnt}">
<div class="col col-sm-1">
{cnt}
</div>
<div class="col">
<label for="fileType{cnt}" class="form-label">File Type</label>
<select id="fileType{cnt}" name="data.{cnt}.type" class="form-select message-attribute">
<option>Select Type</option>
{% for t in RiddleDataType %}
<option value="{{t.value}}" { {{- t.value -}} _selected}>{{t.name}}</option>
{% endfor %}
</select>
</div>
<div class="col">
<label for="inputFile{cnt}" class="form-label">Input File</label>
<input class="form-control message-attribute" name="data.{cnt}.file_plain"
list="dataFiles" id="inputFile{cnt}" value="{file_plain}" placeholder="Type to search files">
</div>
<div class="col">
<label for="schemaFile{cnt}" class="form-label">Schema File</label>
<input class="form-control message-attribute" name="data.{cnt}.file_extracted"
list="schemaFiles" id="schemaFile{cnt}" value="{file_extracted}" placeholder="Type to search files">
</div>
<div class="col col-sm-1">
<button type="button" id="removeFile{cnt}" class="btn btn-danger">Remove</button>
</div>
</div>
</template>
<div id="filesRender">
</div>
<div class="mb-3 row">
<div class="col col-sm-1">
<button type="button" id="addFile" class="btn btn-secondary">Add</button>
</div>
</div>
<h2>JSON Representation</h2>
<div class="mb-3">
<div class="form-floating">
<textarea class="form-control" id="message_content">
{{- AgentMessage(id="",riddle={"context":"","question":""}).model_dump_json(indent=2) -}}
</textarea>
<label for="message_content">Message to send</label>
</div>
</div>
<button type="submit" class="btn btn-primary" id="send_message">Send Message</button>
{% include "modal.html" %}
{% endblock %}
{% block morehead %}
<script>
const basic_message = '{{ AgentMessage(id="",riddle={"context":"","question":""}).model_dump_json()|safe }}';
</script>
{% endblock %}
{% block morefoot %}
<script src="/static/new.js"></script>
{% endblock %}

144
web/templates/table.html Normal file
View File

@ -0,0 +1,144 @@
{#-
Agenten Plattform
(c) 2024 Magnus Bender
Institute of Humanities-Centered Artificial Intelligence (CHAI)
Universitaet Hamburg
https://www.chai.uni-hamburg.de/~bender
source code released under the terms of GNU Public License Version 3
https://www.gnu.org/licenses/gpl-3.0.txt
-#}
{% extends "base.html" %}
{% set title = "Messages" %}
{% macro pagination() %}
<nav>
<ul class="pagination justify-content-center">
<li class="page-item {% if db_args.offset-db_args.limit < 0 %}disabled{% endif %}">
<a class="page-link" href="?{{ pagination_link(offset=db_args.offset-db_args.limit) }}">Previous</a>
</li>
<li class="page-item active" aria-current="page">
<span class="page-link">Offset: {{db_args.offset}}</span>
</li>
<li class="page-item">
<a class="page-link" href="?{{ pagination_link(offset=db_args.offset+db_args.limit) }}">Next</a>
</li>
</ul>
</nav>
{% endmacro %}
{% block maincontent %}
<div class="row">
<div class="col">
<div class="form-check form-switch">
<input class="form-check-input" type="checkbox" role="switch" id="autoRefresh">
<label class="form-check-label" for="autoRefresh">Refresh for new messages</label>
</div>
</div>
<div class="col">
{{pagination()}}
</div>
<div class="col">
<a href="/app/new" class="btn btn-secondary">&rarr; Add a Riddle</a>
</div>
</div>
<table class="table table-striped">
<thead>
{% for item in db.iterate(**db_args) %}
{% set field_names = ['id'] + item.__fields__.keys()|list %}
{% if loop.index == 1 %}
<tr id="row_0">
{% for field in field_names %}
<th>
{% if field == 'time' %}
<input type="text" class="value_filter" name="filter_time_before" value="{{timestamp2date(db_args.time_before)}}" class="form-control" placeholder="Before"><br />
<input type="text" class="value_filter" name="filter_time_after" value="{{timestamp2date(db_args.time_after)}}" class="form-control" placeholder="After"><br />
{% elif field not in ('message', 'count') %}
<input type="text" class="value_filter" name="filter_{{field}}" value="{{db_args[field]}}" class="form-control" placeholder="Filter"><br />
{% endif %}
{{ field.title() }}
</th>
{% endfor %}
</tr>
</thead><tbody>
{% endif %}
<tr id="row_{{loop.index}}">
{% set row_index = loop.index %}
{% for field in field_names %}
{% if field == "message" %}
<td>
<button type="button" class="btn btn-outline-secondary btn-outline" data-bs-toggle="modal" data-bs-target="#row_message_{{row_index}}">
Show Message
</button>
<div class="modal fade" id="row_message_{{row_index}}" tabindex="-1" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title fs-5">Content of Message</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<pre id="row_message_raw_{{row_index}}">{{ item[field].model_dump_json(indent=2)|string }}</pre>
<button class="btn btn-warning send_message_again" idx="{{row_index}}">Send Again</button>
</div>
</div>
</div>
</div>
</td>
{% elif field == "id" %}
<td>{{ item.message.id }}</td>
{% elif field == "time" %}
<td ts="item[field]">{{ timestamp2date(item[field]) }}</td>
{% else %}
<td>{{ item[field] }}</td>
{% endif %}
{% endfor %}
</tr>
{% else %}
<div class="alert alert-warning" role="alert">
No items found, reset offset, limit, filter, ...!<br />
<a class="btn btn-warning" href="/app/table">Reset</a>
</div>
{% endfor %}
</tbody>
</table>
<div class="row">
<div class="col">
{{pagination()}}
</div>
<div class="col">
<div class="input-group">
<label class="input-group-text" for="total-items">Total items</label>
<input class="form-control" id="total-items" disabled value="{{ db.len(**db_args) }}" />
</div>
</div>
<div class="col">
<div class="input-group">
<label class="input-group-text" for="items-per-page">Items per page</label>
<select class="form-select" id="items-per-page" onchange="window.location = this.value;">
<option value="?{{ pagination_link(limit=5) }}" {% if db_args.limit == 5 %}selected{% endif %}>5</option>
<option value="?{{ pagination_link(limit=10) }}" {% if db_args.limit == 10 %}selected{% endif %}>10</option>
<option value="?{{ pagination_link(limit=25) }}" {% if db_args.limit == 25 %}selected{% endif %}>25</option>
<option value="?{{ pagination_link(limit=100) }}" {% if db_args.limit == 100 %}selected{% endif %}>100</option>
{% if db_args.limit not in (5, 10, 25, 100) %}
<option value="?{{ pagination_link(limit=db_args.limit) }}" selected>{{db_args.limit}}</option>
{% endif %}
</select>
</div>
</div>
</div>
{% include "modal.html" %}
{% endblock %}
{% block morehead %}
<script>
const db_args = JSON.parse('{{ db_args|tojson }}');
const db_total = {{ db.len(**db_args) }};
</script>
{% endblock %}
{% block morefoot %}
<script src="/static/table.js"></script>
{% endblock %}