Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
c3adf0f
fix: raise error if signature verify fails (#317)
aledefra Nov 27, 2025
3ec013b
fix: ora_sync logging
cristibleotiu Nov 28, 2025
88741c9
fix: submit node update on pipeline update (#318)
aledefra Dec 1, 2025
bb712ac
feat: added test_llm_servings.py script and updated the system prompt…
cristibleotiu Dec 2, 2025
30ff6d4
fix: error handling for size conflict when loading LLM
cristibleotiu Dec 2, 2025
fa8cdb4
fix: removed unnecessary eval
cristibleotiu Dec 3, 2025
3d05b88
fix: removed llama-cpp-python from requirements.txt and added specifi…
cristibleotiu Dec 3, 2025
9355c8d
fix: added no-deps flag to llama-cpp-python
cristibleotiu Dec 3, 2025
8df2c48
fix: fixed llama-cpp-python installation
cristibleotiu Dec 3, 2025
f9d9a9f
CAR tunnels start (#319)
toderian Dec 4, 2025
fa30bdc
Fix Cstore & R1FS API (#321)
toderian Dec 4, 2025
7335d11
Fix car tunnel start (#320)
toderian Dec 4, 2025
5318c46
feat: semaphore plugin start (#322)
toderian Dec 8, 2025
780f75d
fix: added context to devcontainer.json
cristibleotiu Dec 8, 2025
e621cc0
Fix semaphored plugin setup (#324)
toderian Dec 9, 2025
4dce097
feat: moved llama-cpp-python to device.py additional package installa…
cristibleotiu Dec 9, 2025
1efa3f4
chore: inc ver
cristibleotiu Dec 9, 2025
ec9816a
Fix chainstore responses setup (#326)
toderian Dec 11, 2025
7a9edd4
TCP Tunnels support in CAR and Tunnels Manager (#327)
aledefra Dec 11, 2025
16f2810
chore: inc ver
cristibleotiu Dec 11, 2025
9328821
Add auto semaphore & auto set up of cstore auth env (#328)
toderian Dec 15, 2025
789b522
Cstore (#329)
toderian Dec 15, 2025
3225f75
chore: increment version
toderian Dec 16, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ RUN set -eux; \
# COPY ./cmds /usr/local/bin/
# RUN chmod +x /usr/local/bin/*

RUN npm install -g npm@latest @openai/codex
RUN npm install -g @openai/codex

WORKDIR /edge_node
#COPY . .
Expand Down
19 changes: 16 additions & 3 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"dockerFile" : "Dockerfile",
// "image": "aidamian/ds101_2024",


"workspaceMount": "source=${localWorkspaceFolder},target=/edge_node,type=bind",
"workspaceFolder": "/edge_node",

"runArgs": [
//"--gpus=all", // Use this option if you have a GPU
Expand All @@ -14,9 +15,21 @@
"r1edge",

"--privileged"
],

],


"build": {
"context": "../",
},


"customizations": {
"jetbrains": {
"settings": {
"org.jetbrains.plugins.github:app:GithubSettings.clone_git_using_ssh": true,
"org.jetbrains.plugins.terminal:app:TerminalOptionsProvider.myShellPath": "C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\powershell.exe"
}
},
"vscode" : {
"extensions": [
"ms-python.python",
Expand Down
4 changes: 3 additions & 1 deletion device.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

if __name__ == '__main__':
mp.set_start_method('spawn') # if moved at import will generate errors in subprocs
exit_code, eng = main()
exit_code, eng = main(
additional_packages=['llama-cpp-python'],
)

# TODO: configured with flag in startup
SYS_EXIT = False
Expand Down
47 changes: 47 additions & 0 deletions extensions/business/cerviguard/local_serving_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,12 @@
# AI Engine for image processing
'AI_ENGINE': 'CERVIGUARD_IMAGE_ANALYZER',

# Semaphore key for paired plugin synchronization (e.g., with WAR containers)
# When set, this plugin will signal readiness and expose env vars to paired plugins
"SEMAPHORE": None,

"VERBOSE": 10,

'VALIDATION_RULES': {
**FastApiWebAppPlugin.CONFIG['VALIDATION_RULES'],
'REQUEST_TIMEOUT': {
Expand All @@ -90,6 +96,30 @@ class LocalServingApiPlugin(FastApiWebAppPlugin):

CONFIG = _CONFIG

def Pd(self, s, *args, score=-1, **kwargs):
"""
Print debug message if verbosity level allows.

Parameters
----------
s : str
Message to print
score : int, optional
Verbosity threshold (default: -1). Message prints if cfg_verbose > score
*args
Additional positional arguments passed to P()
**kwargs
Additional keyword arguments passed to P()

Returns
-------
None
"""
if self.cfg_verbose > score:
s = "[DEBUG] " + s
self.P(s, *args, **kwargs)
return

def on_init(self):
super(LocalServingApiPlugin, self).on_init()
# Initialize request tracking
Expand All @@ -102,6 +132,23 @@ def on_init(self):
self.P(f" Loopback key: loopback_dct_{self._stream_id}", color='g')
return


def _setup_semaphore_env(self):
"""Set semaphore environment variables for bundled plugins."""
localhost_ip = self.log.get_localhost_ip()
port = self.cfg_port
self.semaphore_set_env('API_HOST', localhost_ip)
if port:
self.semaphore_set_env('API_PORT', str(port))
self.semaphore_set_env('API_URL', 'http://{}:{}'.format(localhost_ip, port))
return


def on_close(self):
super(LocalServingApiPlugin, self).on_close()
return


def _get_payload_field(self, data: dict, key: str, default=None):
if not isinstance(data, dict):
return default
Expand Down
221 changes: 221 additions & 0 deletions extensions/business/container_apps/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
# Container Apps

Container application plugins for running Docker containers with Cloudflare tunnel support.

## Table of Contents

- [Summary](#summary)
- [Plugins](#plugins)
- [Features](#features)
- [Health Check Configuration](#health-check-configuration)
- [Configuration Reference](#configuration-reference)
- [Future Enhancements](#future-enhancements)
- [Continuous Health Monitoring](#continuous-health-monitoring)
- [Per-Port Health Checks](#per-port-health-checks)

---

## Summary

The Container Apps module provides plugins for managing Docker containers with integrated tunnel support. Key capabilities:

- **Container lifecycle management**: Start, stop, restart with configurable policies
- **Tunnel integration**: Automatic Cloudflare tunnel creation for exposed ports
- **Health probing**: Wait for app readiness before starting tunnels
- **Git integration**: Auto-restart on repository updates (WorkerAppRunner)

---

## Plugins

| Plugin | Description |
|--------|-------------|
| `ContainerAppRunnerPlugin` | Base plugin for running Docker containers with tunnel support |
| `WorkerAppRunnerPlugin` | Extends base with Git repository cloning and update monitoring |

---

## Features

### Health Check Configuration

The plugin uses a consolidated `HEALTH_CHECK` configuration dict to determine when the application is ready before starting tunnels.

```python
"HEALTH_CHECK": {
"MODE": "auto", # "auto" | "tcp" | "endpoint" | "delay"
"PATH": None, # HTTP endpoint path (e.g., "/health", "/api/ready")
"PORT": None, # Container port for health check (None = use main PORT)
"DELAY": 30, # Seconds before first probe / full delay for "delay" mode
"INTERVAL": 5, # Seconds between probe attempts (tcp/endpoint modes)
"TIMEOUT": 300, # Max wait time in seconds (0 = unlimited)
"ON_FAILURE": "start", # "start" | "skip" - behavior when timeout reached
}
```

**Health Check Modes:**

| Mode | Description |
|------|-------------|
| `"auto"` | Smart detection (default): uses "endpoint" if `PATH` is set, otherwise "tcp" if PORT is configured |
| `"tcp"` | TCP port check - works for any protocol (HTTP, WebSocket, gRPC, raw TCP). Simply checks if the port is accepting connections |
| `"endpoint"` | HTTP probe to `PATH` - expects 2xx response. Requires PATH to be configured |
| `"delay"` | Simple time-based delay using `DELAY` - no active probing |

**Configuration Options:**

| Key | Default | Description |
|-----|---------|-------------|
| `MODE` | "auto" | Health check strategy |
| `PATH` | None | HTTP endpoint path for "endpoint" mode |
| `PORT` | None | Container port (None = use main PORT) |
| `DELAY` | 30 | Initial delay before probing / full delay for "delay" mode |
| `INTERVAL` | 5 | Seconds between probe attempts |
| `TIMEOUT` | 300 | Max wait time (0 = unlimited, probe forever) |
| `ON_FAILURE` | "start" | Behavior on timeout: "start" (tunnel anyway) or "skip" (no tunnel) |

**Examples:**

```python
# TCP mode (default) - works for any protocol
"PORT": 3000,
"HEALTH_CHECK": {}
# → TCP probe to allocated host port until connection accepted

# Explicit TCP mode - useful for non-HTTP services (WebSocket, gRPC, etc.)
"PORT": 8080,
"HEALTH_CHECK": {"MODE": "tcp"}
# → TCP probe regardless of other settings

# HTTP endpoint mode - for apps with health endpoints
"PORT": 3000,
"HEALTH_CHECK": {"PATH": "/health"}
# → HTTP GET http://{localhost_ip}:{allocated_host_port}/health

# HTTP endpoint with custom timeout
"PORT": 3000,
"HEALTH_CHECK": {
"PATH": "/api/health",
"TIMEOUT": 300, # Wait up to 5 minutes
}

# Unlimited timeout - probe forever until success
"PORT": 3000,
"HEALTH_CHECK": {
"PATH": "/health",
"TIMEOUT": 0, # 0 = unlimited
}

# Health on different container port
"PORT": 3000,
"CONTAINER_RESOURCES": {"ports": [3000, 8080]},
"HEALTH_CHECK": {
"PATH": "/api/health",
"PORT": 8080,
}
# → HTTP GET http://{localhost_ip}:{host_port_for_8080}/api/health

# Simple delay mode (no probing)
"PORT": 3000,
"HEALTH_CHECK": {
"MODE": "delay",
"DELAY": 60,
}
# → Wait 60 seconds, then assume ready

# Skip tunnel on health failure
"PORT": 3000,
"HEALTH_CHECK": {
"PATH": "/health",
"TIMEOUT": 60,
"ON_FAILURE": "skip", # Don't start tunnel if health check fails
}
```

**Security (for "endpoint" mode):**
- Only host-local URLs allowed (no external URLs)
- Uses `get_localhost_ip()` for reliable host access across different Docker/network configurations
- Port must be a configured container port (validated against `ports_mapping`)
- Invalid port configuration triggers soft error (logs warning, falls back to "delay" mode)

---

## Configuration Reference

See `ContainerAppRunnerPlugin.CONFIG` for full configuration options.

---

## Future Enhancements

### Continuous Health Monitoring

**Status**: Planned

Currently, health probing only runs at startup to gate tunnel initialization. Once `_app_ready = True`, no further health checks occur. For production environments where apps can become unresponsive while the container stays running (memory leaks, deadlocks, etc.), continuous health monitoring could be added:

```python
"HEALTH_CHECK": {
"PATH": "/health",
"MONITOR_INTERVAL": 30, # Seconds between health checks (0 = disabled)
"MONITOR_MAX_FAILURES": 3, # Consecutive failures before restart
}
```

**Implementation approach:**
- Use HTTP endpoint probing for continuous monitoring (more thorough than TCP)
- TCP check confirms "port is open", HTTP check confirms "app is responding correctly"
- Track consecutive failures in `_health_monitor_failures` counter
- Trigger restart with `StopReason.HEALTH_CHECK_FAILED` after max failures
- Reset counter on successful probe
- Integrate with existing restart backoff system

**Flow:**
```
Phase 1: Startup Probing (existing)
├─ Wait DELAY
├─ Probe every INTERVAL (TCP or HTTP based on mode)
├─ Timeout after TIMEOUT (or probe forever if TIMEOUT=0)
└─ Success → _app_ready = True, enable tunnels

Phase 2: Continuous Monitoring (future)
├─ Requires PATH (HTTP-based monitoring)
├─ Probe every MONITOR_INTERVAL
├─ Track consecutive failures
├─ After MONITOR_MAX_FAILURES → restart
└─ Reset counter on success
```

---

### Per-Port Health Checks

**Status**: Planned

Currently, a single health check gates all tunnels (main + extra). For multi-service containers where different ports become ready at different times, per-port health configuration could be added:

```python
# Main port health
"HEALTH_CHECK": {"PATH": "/health"}, # For main PORT

# Extra tunnels with optional per-port health
"EXTRA_TUNNELS": {
# Simple form (follows main tunnel timing)
8080: "cf_token_xxx",

# Extended form with own health check
9090: {
"token": "cf_token_yyy",
"health_path": "/api/health",
"health_delay": 30, # Optional override
}
}
```

**Implementation requirements:**
- Per-port readiness state tracking
- Per-port probe timing
- `_is_port_ready(port)` method
- Modified extra tunnel startup logic to check per-port readiness

---
Loading
Loading