sciveo 0.1.90__tar.gz → 0.1.91__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {sciveo-0.1.90 → sciveo-0.1.91}/PKG-INFO +1 -1
- sciveo-0.1.91/sciveo/agents/base.py +241 -0
- sciveo-0.1.91/sciveo/agents/clients/anthropic.py +81 -0
- sciveo-0.1.91/sciveo/agents/clients/gemini.py +67 -0
- sciveo-0.1.91/sciveo/agents/clients/groq.py +36 -0
- sciveo-0.1.91/sciveo/agents/console.py +66 -0
- sciveo-0.1.91/sciveo/agents/tools/os.py +115 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/cli.py +5 -3
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/monitoring/monitor.py +34 -10
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/monitoring/start.py +3 -1
- sciveo-0.1.91/sciveo/tools/aws/__init__.py +0 -0
- sciveo-0.1.91/sciveo/tools/draw/__init__.py +0 -0
- sciveo-0.1.91/sciveo/version.py +2 -0
- sciveo-0.1.91/sciveo/web/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo.egg-info/PKG-INFO +1 -1
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo.egg-info/SOURCES.txt +9 -0
- sciveo-0.1.90/sciveo/version.py +0 -2
- {sciveo-0.1.90 → sciveo-0.1.91}/README.md +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/__init__.py +0 -0
- {sciveo-0.1.90/sciveo/api → sciveo-0.1.91/sciveo/agents}/__init__.py +0 -0
- {sciveo-0.1.90/sciveo/common → sciveo-0.1.91/sciveo/agents/clients}/__init__.py +0 -0
- {sciveo-0.1.90/sciveo/content → sciveo-0.1.91/sciveo/agents/tools}/__init__.py +0 -0
- {sciveo-0.1.90/sciveo/db → sciveo-0.1.91/sciveo/api}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/api/base.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/api/predictors.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/api/server.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/api/upload.py +0 -0
- {sciveo-0.1.90/sciveo/media → sciveo-0.1.91/sciveo/common}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/common/configuration.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/common/model.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/common/optimizers.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/common/sampling.py +0 -0
- {sciveo-0.1.90/sciveo/media/capture → sciveo-0.1.91/sciveo/content}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/content/dataset.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/content/experiment.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/content/project.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/content/runner.py +0 -0
- {sciveo-0.1.90/sciveo/media/capture/games → sciveo-0.1.91/sciveo/db}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/db/read_table.py +0 -0
- {sciveo-0.1.90/sciveo/media/capture/games/asteroids → sciveo-0.1.91/sciveo/media}/__init__.py +0 -0
- {sciveo-0.1.90/sciveo/media/ml → sciveo-0.1.91/sciveo/media/capture}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/capture/cam.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/capture/draw.py +0 -0
- {sciveo-0.1.90/sciveo/media/ml/encoders → sciveo-0.1.91/sciveo/media/capture/games}/__init__.py +0 -0
- {sciveo-0.1.90/sciveo/media/ml/nlp → sciveo-0.1.91/sciveo/media/capture/games/asteroids}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/capture/games/asteroids/asteroid.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/capture/games/asteroids/base_move.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/capture/games/asteroids/circle.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/capture/games/asteroids/game.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/capture/games/asteroids/geometrics.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/capture/games/asteroids/gravity_ball.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/capture/games/asteroids/laser.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/capture/games/asteroids/rocket.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/capture/games/asteroids/space_asteroids.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/capture/games/asteroids/volume_bar.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/capture/gst_server.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/capture/motion_detection.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/capture/nvr.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/capture/readers.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/capture/rpi.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/capture/rtsp.py +0 -0
- {sciveo-0.1.90/sciveo/media/ml/time_series → sciveo-0.1.91/sciveo/media/ml}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/ml/base.py +0 -0
- {sciveo-0.1.90/sciveo/media/pipelines → sciveo-0.1.91/sciveo/media/ml/encoders}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/ml/encoders/base.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/ml/encoders/normalizer.py +0 -0
- {sciveo-0.1.90/sciveo/media/pipelines/layouts → sciveo-0.1.91/sciveo/media/ml/nlp}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/ml/nlp/search.py +0 -0
- {sciveo-0.1.90/sciveo/media/pipelines/postprocessors → sciveo-0.1.91/sciveo/media/ml/time_series}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/ml/time_series/dataset.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/ml/time_series/predictor.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/ml/time_series/trainer.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/ml/time_series/window_generator.py +0 -0
- {sciveo-0.1.90/sciveo/media/pipelines/processors → sciveo-0.1.91/sciveo/media/pipelines}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/base.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/job_daemon.py +0 -0
- {sciveo-0.1.90/sciveo/media/pipelines/processors/audio → sciveo-0.1.91/sciveo/media/pipelines/layouts}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/layouts/base.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/pipeline.py +0 -0
- {sciveo-0.1.90/sciveo/media/pipelines/processors/file → sciveo-0.1.91/sciveo/media/pipelines/postprocessors}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/postprocessors/base.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/postprocessors/default.py +0 -0
- {sciveo-0.1.90/sciveo/media/pipelines/processors/image → sciveo-0.1.91/sciveo/media/pipelines/processors}/__init__.py +0 -0
- {sciveo-0.1.90/sciveo/media/pipelines/processors/nlp → sciveo-0.1.91/sciveo/media/pipelines/processors/audio}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/audio/audio.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/audio/audio_extractor_process.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/aws.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/base.py +0 -0
- {sciveo-0.1.90/sciveo/media/pipelines/processors/sci → sciveo-0.1.91/sciveo/media/pipelines/processors/file}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/file/archive.py +0 -0
- {sciveo-0.1.90/sciveo/media/pipelines/processors/sci/time_series → sciveo-0.1.91/sciveo/media/pipelines/processors/image}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/image/album.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/image/album_in_image.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/image/depth_esimation.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/image/embeddings.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/image/filters.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/image/generators.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/image/histogram.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/image/mask.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/image/object_detection.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/image/resize.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/image/segmentation.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/image/watermark.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/media_info.py +0 -0
- {sciveo-0.1.90/sciveo/media/pipelines/processors/video → sciveo-0.1.91/sciveo/media/pipelines/processors/nlp}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/nlp/address.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/qr.py +0 -0
- {sciveo-0.1.90/sciveo/media/pipelines/web → sciveo-0.1.91/sciveo/media/pipelines/processors/sci}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/sci/base.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/sci/dataset.py +0 -0
- {sciveo-0.1.90/sciveo/media/tools → sciveo-0.1.91/sciveo/media/pipelines/processors/sci/time_series}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/sci/time_series/predictor.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/sci/time_series/trainer.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/tpu_base.py +0 -0
- {sciveo-0.1.90/sciveo/ml → sciveo-0.1.91/sciveo/media/pipelines/processors/video}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/video/generators.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/video/motion_detection.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/video/resize.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/video/video_album.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/video/video_frames.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/processors/video/video_resample.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/queues.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/server.py +0 -0
- {sciveo-0.1.90/sciveo/ml/dataset → sciveo-0.1.91/sciveo/media/pipelines/web}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/pipelines/web/server.py +0 -0
- {sciveo-0.1.90/sciveo/ml/evaluation → sciveo-0.1.91/sciveo/media/tools}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/media/tools/video_interactive.py +0 -0
- {sciveo-0.1.90/sciveo/ml/images → sciveo-0.1.91/sciveo/ml}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/ml/base.py +0 -0
- {sciveo-0.1.90/sciveo/ml/nlp → sciveo-0.1.91/sciveo/ml/dataset}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/ml/dataset/object_detection.py +0 -0
- {sciveo-0.1.90/sciveo/ml/nlp/tokenizers → sciveo-0.1.91/sciveo/ml/evaluation}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/ml/evaluation/markdown.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/ml/evaluation/object_detection.py +0 -0
- {sciveo-0.1.90/sciveo/ml/video → sciveo-0.1.91/sciveo/ml/images}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/ml/images/base.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/ml/images/description.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/ml/images/embeddings.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/ml/images/object_detection.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/ml/images/tools.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/ml/images/transformers.py +0 -0
- {sciveo-0.1.90/sciveo/monitoring → sciveo-0.1.91/sciveo/ml/nlp}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/ml/nlp/embeddings.py +0 -0
- {sciveo-0.1.90/sciveo/monitoring/power → sciveo-0.1.91/sciveo/ml/nlp/tokenizers}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/ml/nlp/tokenizers/bpe.py +0 -0
- {sciveo-0.1.90/sciveo/monitoring/watchdog → sciveo-0.1.91/sciveo/ml/video}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/ml/video/description.py +0 -0
- {sciveo-0.1.90/sciveo/network → sciveo-0.1.91/sciveo/monitoring}/__init__.py +0 -0
- {sciveo-0.1.90/sciveo/tools → sciveo-0.1.91/sciveo/monitoring/power}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/monitoring/power/ems300.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/monitoring/power/sim.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/monitoring/power/tools.py +0 -0
- {sciveo-0.1.90/sciveo/tools/aws → sciveo-0.1.91/sciveo/monitoring/watchdog}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/monitoring/watchdog/base.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/monitoring/watchdog/process.py +0 -0
- {sciveo-0.1.90/sciveo/tools/draw → sciveo-0.1.91/sciveo/network}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/network/camera.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/network/sniffer.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/network/tools.py +0 -0
- {sciveo-0.1.90/sciveo/web → sciveo-0.1.91/sciveo/tools}/__init__.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/array.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/aws/priority_queue.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/aws/s3.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/common.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/complexity.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/compress.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/configuration.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/crypto.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/daemon.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/draw/contours.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/formating.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/hardware.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/http.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/logger.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/os.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/queue.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/random.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/remote.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/simple_counter.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/synchronized.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/timers.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/tools/totp.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo/web/common.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo.egg-info/dependency_links.txt +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo.egg-info/entry_points.txt +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo.egg-info/requires.txt +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/sciveo.egg-info/top_level.txt +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/setup.cfg +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/setup.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/test/test_complexity.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/test/test_compress.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/test/test_configuration.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/test/test_crypto.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/test/test_eval_markdown.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/test/test_ml_datasets.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/test/test_monitoring.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/test/test_runner.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/test/test_sampling.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/test/test_tokenizers.py +0 -0
- {sciveo-0.1.90 → sciveo-0.1.91}/test/test_totp.py +0 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Pavlin Georgiev, Softel Labs
|
|
3
|
+
#
|
|
4
|
+
# This is a proprietary file and may not be copied,
|
|
5
|
+
# distributed, or modified without express permission
|
|
6
|
+
# from the owner. For licensing inquiries, please
|
|
7
|
+
# contact pavlin@softel.bg.
|
|
8
|
+
#
|
|
9
|
+
# 2026
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
from sciveo.tools.logger import *
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# =========================
|
|
17
|
+
# Agent IR (Anthropic-style)
|
|
18
|
+
# =========================
|
|
19
|
+
|
|
20
|
+
class ToolCall:
|
|
21
|
+
def __init__(self, name: str, input: dict):
|
|
22
|
+
self.name = name
|
|
23
|
+
self.input = input
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class AgentBlock:
|
|
27
|
+
def __init__(self, block_type: str, content):
|
|
28
|
+
self.type = block_type # "text" | "tool_use"
|
|
29
|
+
self.content = content
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def parse_agent_blocks(raw_result) -> list:
|
|
33
|
+
"""
|
|
34
|
+
Strict JSON-only parser.
|
|
35
|
+
Expected format: Anthropic-style block array.
|
|
36
|
+
"""
|
|
37
|
+
try:
|
|
38
|
+
if isinstance(raw_result, str):
|
|
39
|
+
raw = json.loads(raw_result)
|
|
40
|
+
elif isinstance(raw_result, list):
|
|
41
|
+
raw = raw_result
|
|
42
|
+
else:
|
|
43
|
+
raise ValueError(f"Invalid type from LLM: {type(raw_result)}")
|
|
44
|
+
except Exception as e:
|
|
45
|
+
raise ValueError(f"Invalid JSON from LLM: {e}")
|
|
46
|
+
|
|
47
|
+
if not isinstance(raw, list):
|
|
48
|
+
raise ValueError("Top-level JSON must be a list")
|
|
49
|
+
|
|
50
|
+
blocks = []
|
|
51
|
+
|
|
52
|
+
for item in raw:
|
|
53
|
+
if not isinstance(item, dict):
|
|
54
|
+
raise ValueError("Each block must be an object")
|
|
55
|
+
|
|
56
|
+
block_type = item.get("type")
|
|
57
|
+
|
|
58
|
+
if block_type == "text":
|
|
59
|
+
blocks.append(
|
|
60
|
+
AgentBlock("text", item.get("text", ""))
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
elif block_type == "tool_use":
|
|
64
|
+
blocks.append(
|
|
65
|
+
AgentBlock(
|
|
66
|
+
"tool_use",
|
|
67
|
+
ToolCall(
|
|
68
|
+
name=item.get("name"),
|
|
69
|
+
input=item.get("input", {})
|
|
70
|
+
)
|
|
71
|
+
)
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
else:
|
|
75
|
+
raise ValueError(f"Unknown block type: {block_type}")
|
|
76
|
+
|
|
77
|
+
return blocks
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
# =========================
|
|
81
|
+
# Tools
|
|
82
|
+
# =========================
|
|
83
|
+
|
|
84
|
+
class ToolBase:
|
|
85
|
+
name = ""
|
|
86
|
+
description = ""
|
|
87
|
+
|
|
88
|
+
def run(self, args: str, agent):
|
|
89
|
+
raise NotImplementedError
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class ToolHelp(ToolBase):
|
|
93
|
+
schema = {
|
|
94
|
+
"name": "help",
|
|
95
|
+
"description": "List available tools",
|
|
96
|
+
"input_schema": {
|
|
97
|
+
"type": "object",
|
|
98
|
+
"properties": {},
|
|
99
|
+
"required": [],
|
|
100
|
+
},
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
def run(self, args, agent):
|
|
104
|
+
return "\n".join(
|
|
105
|
+
f"{name}: {tool.schema.description}"
|
|
106
|
+
for name, tool in agent.tools.items()
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
# =========================
|
|
111
|
+
# LLM Client Base
|
|
112
|
+
# =========================
|
|
113
|
+
|
|
114
|
+
class LLMClientBase:
|
|
115
|
+
def chat(self, messages: list[dict], tools=None) -> str:
|
|
116
|
+
"""
|
|
117
|
+
Must return a STRING containing ONLY valid JSON
|
|
118
|
+
matching the AgentBlock schema.
|
|
119
|
+
"""
|
|
120
|
+
raise NotImplementedError
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
# =========================
|
|
124
|
+
# Agent Base
|
|
125
|
+
# =========================
|
|
126
|
+
|
|
127
|
+
class AgentBase:
|
|
128
|
+
def __init__(self, llm: LLMClientBase):
|
|
129
|
+
self.llm = llm
|
|
130
|
+
self.tools = {}
|
|
131
|
+
self.messages = []
|
|
132
|
+
self.system_prompt = "You are a coding assistant. Use tools to help the user. Be concise and careful!"
|
|
133
|
+
# self.system_prompt = self._build_system_prompt()
|
|
134
|
+
|
|
135
|
+
def register_tool(self, tool: ToolBase):
|
|
136
|
+
debug("register_tool", tool.schema)
|
|
137
|
+
self.tools[tool.schema["name"]] = tool
|
|
138
|
+
|
|
139
|
+
def call_tool(self, name: str, args):
|
|
140
|
+
debug("TOOL", name, "args", args)
|
|
141
|
+
tool = self.tools.get(name)
|
|
142
|
+
if tool is None:
|
|
143
|
+
return f"[Tool error] Unknown tool: {name}"
|
|
144
|
+
return tool.run(args, self)
|
|
145
|
+
|
|
146
|
+
def _build_system_prompt(self) -> str:
|
|
147
|
+
tools_list = "\n".join(
|
|
148
|
+
f"- {t.name}: {t.description}"
|
|
149
|
+
for t in self.tools.values()
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
return f"""
|
|
153
|
+
You are a cautious code agent.
|
|
154
|
+
|
|
155
|
+
You have access to the following tools:
|
|
156
|
+
{tools_list}
|
|
157
|
+
|
|
158
|
+
When responding, output ONLY valid JSON.
|
|
159
|
+
The response MUST be a JSON array of blocks.
|
|
160
|
+
|
|
161
|
+
Each block must be one of:
|
|
162
|
+
|
|
163
|
+
1) Tool call:
|
|
164
|
+
{{
|
|
165
|
+
"type": "tool_use",
|
|
166
|
+
"name": "<tool_name>",
|
|
167
|
+
"input": {{ "args": "<string>" }}
|
|
168
|
+
}}
|
|
169
|
+
|
|
170
|
+
2) Text:
|
|
171
|
+
{{
|
|
172
|
+
"type": "text",
|
|
173
|
+
"text": "<string>"
|
|
174
|
+
}}
|
|
175
|
+
|
|
176
|
+
Rules:
|
|
177
|
+
- Use double quotes only
|
|
178
|
+
- No markdown
|
|
179
|
+
- No explanations outside JSON
|
|
180
|
+
- JSON must parse with json.loads()
|
|
181
|
+
""".strip()
|
|
182
|
+
|
|
183
|
+
def clear(self):
|
|
184
|
+
self.messages = []
|
|
185
|
+
|
|
186
|
+
def loop(self, user_input: str, is_clear=True):
|
|
187
|
+
if is_clear:
|
|
188
|
+
self.clear()
|
|
189
|
+
|
|
190
|
+
if len(self.messages) == 0:
|
|
191
|
+
# debug("system_prompt", system_prompt)
|
|
192
|
+
self.messages.append({
|
|
193
|
+
"role": "user",
|
|
194
|
+
"content": self.system_prompt
|
|
195
|
+
})
|
|
196
|
+
|
|
197
|
+
self.messages.append({
|
|
198
|
+
"role": "user",
|
|
199
|
+
"content": user_input
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
while True:
|
|
203
|
+
|
|
204
|
+
response = self.llm.chat(self.messages, self.tools)
|
|
205
|
+
|
|
206
|
+
self.messages.append({
|
|
207
|
+
"role": "assistant",
|
|
208
|
+
"content": str(response)
|
|
209
|
+
})
|
|
210
|
+
|
|
211
|
+
try:
|
|
212
|
+
blocks = parse_agent_blocks(response)
|
|
213
|
+
except Exception as e:
|
|
214
|
+
exception(e)
|
|
215
|
+
return f"[Agent error] {e}"
|
|
216
|
+
|
|
217
|
+
tool_used = False
|
|
218
|
+
final_text = ""
|
|
219
|
+
|
|
220
|
+
for block in blocks:
|
|
221
|
+
if block.type == "text":
|
|
222
|
+
final_text = block.content
|
|
223
|
+
|
|
224
|
+
elif block.type == "tool_use":
|
|
225
|
+
tool_used = True
|
|
226
|
+
result = self.call_tool(
|
|
227
|
+
block.content.name,
|
|
228
|
+
block.content.input.get("command", "")
|
|
229
|
+
)
|
|
230
|
+
|
|
231
|
+
debug("TOOL RESULT", result)
|
|
232
|
+
|
|
233
|
+
# Tool results are fed back as plain text
|
|
234
|
+
self.messages.append({
|
|
235
|
+
"role": "user",
|
|
236
|
+
"content": str(result)
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
# Stop when model stops calling tools
|
|
240
|
+
if not tool_used:
|
|
241
|
+
return final_text
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Pavlin Georgiev, Softel Labs
|
|
3
|
+
#
|
|
4
|
+
# This is a proprietary file and may not be copied,
|
|
5
|
+
# distributed, or modified without express permission
|
|
6
|
+
# from the owner. For licensing inquiries, please
|
|
7
|
+
# contact pavlin@softel.bg.
|
|
8
|
+
#
|
|
9
|
+
# 2026
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
import json
|
|
13
|
+
from anthropic import Anthropic
|
|
14
|
+
from sciveo.tools.logger import *
|
|
15
|
+
from sciveo.agents.base import LLMClientBase
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class AnthropicClient(LLMClientBase):
|
|
19
|
+
"""
|
|
20
|
+
Anthropic client using Messages API with native tool support.
|
|
21
|
+
Accepts structured tools list, handles tool_use and text blocks.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self, api_key: str, model: str = "claude-sonnet-4-20250514", max_tokens: int = 4096, temperature: float = 0.2):
|
|
25
|
+
"""
|
|
26
|
+
Initialize Anthropic Messages API client.
|
|
27
|
+
"""
|
|
28
|
+
self.client = Anthropic(api_key=api_key)
|
|
29
|
+
self.model = model
|
|
30
|
+
self.max_tokens = max_tokens
|
|
31
|
+
self.temperature = temperature
|
|
32
|
+
|
|
33
|
+
def chat(self, messages: list[dict], tools=None) -> list[dict]:
|
|
34
|
+
"""
|
|
35
|
+
Send messages to Claude with optional tools.
|
|
36
|
+
messages: [{"role": "user|assistant", "content": "..."}]
|
|
37
|
+
tools: [{"name": str, "description": str, "input_schema": dict}, ...]
|
|
38
|
+
Returns: list of blocks [{"type": "text|tool_use", ...}, ...]
|
|
39
|
+
"""
|
|
40
|
+
try:
|
|
41
|
+
message_tools = []
|
|
42
|
+
for tn, T in tools.items():
|
|
43
|
+
message_tools.append(T.schema)
|
|
44
|
+
|
|
45
|
+
resp = self.client.messages.create(
|
|
46
|
+
model=self.model,
|
|
47
|
+
messages=messages,
|
|
48
|
+
tools=message_tools,
|
|
49
|
+
max_tokens=self.max_tokens,
|
|
50
|
+
temperature=self.temperature
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
# resp.content is a list of TextBlock or ToolUseBlock
|
|
54
|
+
blocks = []
|
|
55
|
+
for block in resp.content:
|
|
56
|
+
if block.type == "text":
|
|
57
|
+
try:
|
|
58
|
+
json_blocks = json.loads(block.text)
|
|
59
|
+
for json_block in json_blocks:
|
|
60
|
+
blocks.append({
|
|
61
|
+
"type": json_block["type"],
|
|
62
|
+
"name": json_block["name"],
|
|
63
|
+
"input": json_block["input"]
|
|
64
|
+
})
|
|
65
|
+
except Exception:
|
|
66
|
+
blocks.append({"type": "text", "text": block.text})
|
|
67
|
+
elif block.type == "tool_use":
|
|
68
|
+
blocks.append({
|
|
69
|
+
"type": "tool_use",
|
|
70
|
+
"name": block.name,
|
|
71
|
+
"input": block.input
|
|
72
|
+
})
|
|
73
|
+
else:
|
|
74
|
+
# Fallback: treat unknown blocks as text
|
|
75
|
+
blocks.append({"type": "text", "text": str(block)})
|
|
76
|
+
|
|
77
|
+
debug("AnthropicClient blocks", blocks)
|
|
78
|
+
return blocks
|
|
79
|
+
|
|
80
|
+
except Exception as e:
|
|
81
|
+
return [{"type": "text", "text": f"[Anthropic error] {e}"}]
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Pavlin Georgiev, Softel Labs
|
|
3
|
+
#
|
|
4
|
+
# This is a proprietary file and may not be copied,
|
|
5
|
+
# distributed, or modified without express permission
|
|
6
|
+
# from the owner. For licensing inquiries, please
|
|
7
|
+
# contact pavlin@softel.bg.
|
|
8
|
+
#
|
|
9
|
+
# 2026
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
from google import genai
|
|
13
|
+
from google.genai import types
|
|
14
|
+
from sciveo.tools.logger import *
|
|
15
|
+
from sciveo.agents.base import LLMClientBase
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class GeminiClient(LLMClientBase):
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
api_key: str,
|
|
22
|
+
model: str = "gemini-2.5-flash",
|
|
23
|
+
temperature: float = 0.2,
|
|
24
|
+
max_output_tokens: int = 4096,
|
|
25
|
+
):
|
|
26
|
+
"""
|
|
27
|
+
Uses the new google-genai SDK.
|
|
28
|
+
"""
|
|
29
|
+
# Create the unified GenAI client
|
|
30
|
+
self.client = genai.Client(api_key=api_key)
|
|
31
|
+
self.model = model
|
|
32
|
+
self.temperature = temperature
|
|
33
|
+
self.max_output_tokens = max_output_tokens
|
|
34
|
+
|
|
35
|
+
def chat(self, messages: list[dict], tools: list[dict] = None) -> str:
|
|
36
|
+
"""
|
|
37
|
+
messages: list of {"role": "user"|"assistant", "content": "..."}
|
|
38
|
+
returns: plain text
|
|
39
|
+
"""
|
|
40
|
+
try:
|
|
41
|
+
# Build a single prompt from history
|
|
42
|
+
# (GenAI `generate_content` is stateless, so we combine messages manually)
|
|
43
|
+
prompt = ""
|
|
44
|
+
for m in messages:
|
|
45
|
+
# We treat 'assistant' as plain continuation too
|
|
46
|
+
role = m["role"]
|
|
47
|
+
content = m["content"]
|
|
48
|
+
prompt += f"{role}: {content}\n"
|
|
49
|
+
|
|
50
|
+
# Call the GenAI text generation
|
|
51
|
+
response = self.client.models.generate_content(
|
|
52
|
+
model=self.model,
|
|
53
|
+
contents=types.Part.from_text(prompt),
|
|
54
|
+
config=types.GenerateContentConfig(
|
|
55
|
+
temperature=self.temperature,
|
|
56
|
+
max_output_tokens=self.max_output_tokens,
|
|
57
|
+
),
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
# `response.text` contains the full generated output
|
|
61
|
+
text_out = response.text.strip()
|
|
62
|
+
|
|
63
|
+
debug("GeminiClient", {"model": self.model, "text": text_out})
|
|
64
|
+
return text_out
|
|
65
|
+
|
|
66
|
+
except Exception as e:
|
|
67
|
+
return f"[Gemini error] {e}"
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Pavlin Georgiev, Softel Labs
|
|
3
|
+
#
|
|
4
|
+
# This is a proprietary file and may not be copied,
|
|
5
|
+
# distributed, or modified without express permission
|
|
6
|
+
# from the owner. For licensing inquiries, please
|
|
7
|
+
# contact pavlin@softel.bg.
|
|
8
|
+
#
|
|
9
|
+
# 2026
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
from groq import Groq
|
|
13
|
+
from sciveo.tools.logger import *
|
|
14
|
+
from sciveo.agents.base import LLMClientBase
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class GroqClient(LLMClientBase):
|
|
18
|
+
def __init__(self, api_key, model="llama-3.3-70b-versatile", temperature=0.2, max_tokens=4096):
|
|
19
|
+
self.client = Groq(api_key=api_key)
|
|
20
|
+
self.model = model
|
|
21
|
+
self.temperature = temperature
|
|
22
|
+
self.max_tokens = max_tokens
|
|
23
|
+
|
|
24
|
+
def chat(self, messages: list[dict], tools: list[dict] = None) -> str:
|
|
25
|
+
try:
|
|
26
|
+
completion = self.client.chat.completions.create(
|
|
27
|
+
model=self.model,
|
|
28
|
+
messages=messages,
|
|
29
|
+
temperature=self.temperature,
|
|
30
|
+
max_tokens=self.max_tokens
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
return completion.choices[0].message.content.strip()
|
|
34
|
+
|
|
35
|
+
except Exception as e:
|
|
36
|
+
return f"[Groq error] {e}"
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Pavlin Georgiev, Softel Labs
|
|
3
|
+
#
|
|
4
|
+
# This is a proprietary file and may not be copied,
|
|
5
|
+
# distributed, or modified without express permission
|
|
6
|
+
# from the owner. For licensing inquiries, please
|
|
7
|
+
# contact pavlin@softel.bg.
|
|
8
|
+
#
|
|
9
|
+
# 2026
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
from sciveo.tools.logger import *
|
|
13
|
+
from sciveo.agents.base import *
|
|
14
|
+
from sciveo.agents.tools.os import *
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class BaseConsole:
|
|
18
|
+
def __init__(self, agent):
|
|
19
|
+
self.agent = agent
|
|
20
|
+
|
|
21
|
+
def run(self):
|
|
22
|
+
print("Sciveo Agent Console (type 'exit' to quit)")
|
|
23
|
+
while True:
|
|
24
|
+
try:
|
|
25
|
+
user_input = input("> ").strip()
|
|
26
|
+
if user_input.lower() in ("exit", "quit"):
|
|
27
|
+
break
|
|
28
|
+
if len(user_input) < 2:
|
|
29
|
+
continue
|
|
30
|
+
|
|
31
|
+
output = self.agent.loop(user_input)
|
|
32
|
+
|
|
33
|
+
if output:
|
|
34
|
+
info(output)
|
|
35
|
+
except KeyboardInterrupt:
|
|
36
|
+
info("exit")
|
|
37
|
+
break
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
class TestAgent(AgentBase):
|
|
41
|
+
def __init__(self, llm: LLMClientBase):
|
|
42
|
+
super().__init__(llm)
|
|
43
|
+
|
|
44
|
+
self.register_tool(ToolReadFile())
|
|
45
|
+
self.register_tool(ToolWriteFile())
|
|
46
|
+
self.register_tool(ToolPathList())
|
|
47
|
+
self.register_tool(ToolBash())
|
|
48
|
+
self.register_tool(ToolHelp())
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
if __name__ == "__main__":
|
|
52
|
+
from sciveo.agents.clients.gemini import GeminiClient
|
|
53
|
+
from sciveo.agents.clients.groq import GroqClient
|
|
54
|
+
from sciveo.agents.clients.anthropic import AnthropicClient
|
|
55
|
+
|
|
56
|
+
def create_code_agent():
|
|
57
|
+
# llm1 = GeminiClient(api_key=os.getenv("API_KEY_GEMINI"), model="models/gemini-2.5-flash")
|
|
58
|
+
# llm2 = GroqClient(api_key=os.getenv("API_KEY_GROQ"), model="llama-3.1-8b-instant")
|
|
59
|
+
# llm2 = GroqClient(api_key=os.getenv("API_KEY_GROQ"), model="llama-3.3-70b-versatile")
|
|
60
|
+
llm3 = AnthropicClient(api_key=os.getenv("API_KEY_ANTHROPIC"), model="claude-sonnet-4-20250514")
|
|
61
|
+
agent = TestAgent(llm3)
|
|
62
|
+
|
|
63
|
+
return agent
|
|
64
|
+
|
|
65
|
+
agent = create_code_agent()
|
|
66
|
+
BaseConsole(agent).run()
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Pavlin Georgiev, Softel Labs
|
|
3
|
+
#
|
|
4
|
+
# This is a proprietary file and may not be copied,
|
|
5
|
+
# distributed, or modified without express permission
|
|
6
|
+
# from the owner. For licensing inquiries, please
|
|
7
|
+
# contact pavlin@softel.bg.
|
|
8
|
+
#
|
|
9
|
+
# 2026
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
import os
|
|
13
|
+
import subprocess
|
|
14
|
+
|
|
15
|
+
from sciveo.tools.logger import *
|
|
16
|
+
from sciveo.agents.base import ToolBase
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ToolReadFile(ToolBase):
|
|
20
|
+
schema = {
|
|
21
|
+
"name": "read_file",
|
|
22
|
+
"description": "Read contents of a file",
|
|
23
|
+
"input_schema": {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"properties": {
|
|
26
|
+
"path": { "type": "string", "description": "File path to read" },
|
|
27
|
+
},
|
|
28
|
+
"required": ["path"],
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
def run(self, args, agent):
|
|
33
|
+
path = args
|
|
34
|
+
if not os.path.exists(path):
|
|
35
|
+
return f"File not found: {path}"
|
|
36
|
+
try:
|
|
37
|
+
with open(path, "r", encoding="utf-8") as f:
|
|
38
|
+
return f.read()
|
|
39
|
+
except Exception as e:
|
|
40
|
+
return f"Error reading file: {e}"
|
|
41
|
+
return f"FAIL: {args}"
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class ToolWriteFile(ToolBase):
|
|
45
|
+
schema = {
|
|
46
|
+
"name": "write_file",
|
|
47
|
+
"description": "Write content to a file",
|
|
48
|
+
"input_schema": {
|
|
49
|
+
"type": "object",
|
|
50
|
+
"properties": {
|
|
51
|
+
"path": { "type": "string", "description": "File path to write" },
|
|
52
|
+
"content": { "type": "string", "description": "Content to write" },
|
|
53
|
+
},
|
|
54
|
+
"required": ["path", "content"],
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
def run(self, args, agent):
|
|
59
|
+
path, content = args
|
|
60
|
+
|
|
61
|
+
try:
|
|
62
|
+
with open(path, "w", encoding="utf-8") as f:
|
|
63
|
+
f.write(content)
|
|
64
|
+
return f"Written: {path}"
|
|
65
|
+
except Exception as e:
|
|
66
|
+
return f"Error writing file: {e}"
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class ToolPathList(ToolBase):
|
|
70
|
+
schema = {
|
|
71
|
+
"name": "list_dir",
|
|
72
|
+
"description": "List directory contents",
|
|
73
|
+
"input_schema": {
|
|
74
|
+
"type": "object",
|
|
75
|
+
"properties": {
|
|
76
|
+
"path": { "type": "string", "description": "Directory path" },
|
|
77
|
+
},
|
|
78
|
+
"required": ["path"],
|
|
79
|
+
},
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
def run(self, args, agent):
|
|
83
|
+
path = args
|
|
84
|
+
try:
|
|
85
|
+
return "\n".join(os.listdir(path))
|
|
86
|
+
except Exception as e:
|
|
87
|
+
return f"Error listing directory: {e}"
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
class ToolBash(ToolBase):
|
|
91
|
+
schema = {
|
|
92
|
+
"name": "bash",
|
|
93
|
+
"description": "Run a shell command",
|
|
94
|
+
"input_schema": {
|
|
95
|
+
"type": "object",
|
|
96
|
+
"properties": {
|
|
97
|
+
"command": { "type": "string", "description": "Command to run" },
|
|
98
|
+
},
|
|
99
|
+
"required": ["command"],
|
|
100
|
+
},
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
def run(self, args: str, agent):
|
|
104
|
+
try:
|
|
105
|
+
result = subprocess.run(
|
|
106
|
+
args,
|
|
107
|
+
shell=True,
|
|
108
|
+
capture_output=True,
|
|
109
|
+
text=True
|
|
110
|
+
)
|
|
111
|
+
out = result.stdout.strip()
|
|
112
|
+
err = result.stderr.strip()
|
|
113
|
+
return out if out else err if err else "OK"
|
|
114
|
+
except Exception as e:
|
|
115
|
+
return f"Bash error: {e}"
|
|
@@ -60,15 +60,17 @@ def main():
|
|
|
60
60
|
parser.add_argument('--execute', type=str, default=None, help='Execute command')
|
|
61
61
|
parser.add_argument('--pid', type=int, default=None, help='Process PID')
|
|
62
62
|
parser.add_argument('--serial', type=str, default=None, help='Serial Name')
|
|
63
|
-
parser.add_argument('--data-json', type=
|
|
63
|
+
parser.add_argument('--data-json', type=json.loads, default={}, help='Json Data')
|
|
64
64
|
parser.add_argument('--display', type=int, default=None, help='Display number')
|
|
65
|
+
parser.add_argument('--list-shell', type=json.loads, default=[], help='List of Shell commands')
|
|
66
|
+
parser.add_argument('--list-logs', type=json.loads, default=[], help='List of Log files')
|
|
65
67
|
|
|
66
68
|
args = parser.parse_args()
|
|
67
69
|
|
|
68
70
|
if args.command == 'monitor':
|
|
69
71
|
if args.src is None:
|
|
70
72
|
from sciveo.monitoring.start import MonitorStart
|
|
71
|
-
MonitorStart(period=args.period, block=args.block, output_path=args.output_path)()
|
|
73
|
+
MonitorStart(period=args.period, block=args.block, output_path=args.output_path, shell=args.list_shell, logs=args.list_logs)()
|
|
72
74
|
elif args.src.startswith("power"):
|
|
73
75
|
from sciveo.monitoring.power.ems300 import PowerEMS300
|
|
74
76
|
mon = PowerEMS300(serial=args.serial, host=args.host, port=args.port, period=args.period, output_path=args.output_path)
|
|
@@ -124,7 +126,7 @@ def main():
|
|
|
124
126
|
else:
|
|
125
127
|
# warning("RTSP src", args.src, "not recognised")
|
|
126
128
|
server = CamFactory(args.src, args.width, args.height, args.fps, configuration=data, display=args.display)
|
|
127
|
-
|
|
129
|
+
server.serve(host=args.host, port=args.port, stream=args.stream)
|
|
128
130
|
elif args.command == 'capture':
|
|
129
131
|
from sciveo.media.capture.cam import CameraDaemon, ScreenDaemon, CapturePlayer
|
|
130
132
|
if args.src == "screen":
|