fix(stage): fix message type collision and switcher logic in chat ui
This commit is contained in:
parent
8222ef68be
commit
61c8f709c4
6 changed files with 191 additions and 11 deletions
|
|
@ -18,12 +18,12 @@ jobs:
|
|||
git pull
|
||||
git submodule update --init --recursive botlib botserver
|
||||
cargo build -p botserver
|
||||
- name: Deploy
|
||||
- name: Deploy to Stage
|
||||
run: |
|
||||
sudo incus exec system -- systemctl stop botserver || true
|
||||
sudo incus exec system -- pkill -x botserver || true
|
||||
sudo incus exec system --project STAGE-GBO -- systemctl stop botserver || true
|
||||
sudo incus exec system --project STAGE-GBO -- pkill -x botserver || true
|
||||
sleep 1
|
||||
sudo incus file push /opt/gbo/work/botserver/target/debug/botserver system:/opt/gbo/bin/botserver --mode=0755
|
||||
sudo incus exec system -- systemctl start botserver
|
||||
sudo incus file push /opt/gbo/work/botserver/target/debug/botserver system/opt/gbo/bin/botserver --project STAGE-GBO --mode=0755
|
||||
sudo incus exec system --project STAGE-GBO -- systemctl start botserver
|
||||
sleep 2
|
||||
sudo incus exec system -- pgrep -x botserver && echo "✅ BotServer Deployed" || echo "❌ Failed"
|
||||
sudo incus exec system --project STAGE-GBO -- pgrep -x botserver && echo "✅ BotServer Deployed to Stage" || echo "❌ Failed"
|
||||
|
|
|
|||
67
STAGE.md
Normal file
67
STAGE.md
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
# Staging Environment Guide (STAGE-GBO)
|
||||
|
||||
## Infrastructure Overview
|
||||
|
||||
The staging environment is implemented using an isolated **Incus Project** named `STAGE-GBO`. This guarantees that the stage containers, network, and storage are entirely separated from the production environment (`default` project), preventing any accidental interference with `PROD-GBO` containers.
|
||||
|
||||
To work within the staging environment, you must switch to its project first:
|
||||
```bash
|
||||
sudo incus project switch STAGE-GBO
|
||||
```
|
||||
To switch back to production:
|
||||
```bash
|
||||
sudo incus project switch default
|
||||
```
|
||||
|
||||
### Container Architecture
|
||||
|
||||
The stage environment consists of clones of the following production containers, restricted to a maximum of 10GB disk space and mapped to a dedicated 10.0.3.x subnet (`stagebr0` network):
|
||||
|
||||
| Container | Internal IP | Data Status | Purpose |
|
||||
|-----------|-------------|-------------|---------|
|
||||
| **system** | `10.0.3.10` | Wiped (`/opt/gbo/work/`) | Main BotServer + BotUI |
|
||||
| **tables** | `10.0.3.11` | Intact (schema & DB preserved) | PostgreSQL database |
|
||||
| **vault** | `10.0.3.12` | Intact | Secrets management |
|
||||
| **cache** | `10.0.3.13` | Wiped (RDB/AOF deleted) | Valkey cache |
|
||||
| **drive** | `10.0.3.14` | Wiped (started from scratch) | MinIO object storage |
|
||||
| **llm** | `10.0.3.15` | Intact | llama.cpp local inference |
|
||||
|
||||
## Automation Script
|
||||
|
||||
The setup process was automated using `setup-stage-gbo.sh`. The script performs the following tasks:
|
||||
1. **Creates `STAGE-GBO` Project:** Configured with `features.networks=true` and `features.profiles=true` to isolate networks and profiles from PROD.
|
||||
2. **Creates `stagebr0` Network:** A dedicated NAT network for 10.0.3.x.
|
||||
3. **Sets Resource Limits:** Configures the `default` profile in `STAGE-GBO` with a 10GB root disk size limit.
|
||||
4. **Clones Containers:** Uses `incus copy` to securely copy containers from `default` to `STAGE-GBO` using ZFS/BTRFS copy-on-write without consuming immediate space.
|
||||
5. **Configures IPs:** Updates `/etc/network/interfaces` inside each stage container to assign the static 10.0.3.x IPs.
|
||||
6. **Cleans Data:** Wipes `/opt/gbo/logs/` in all containers, wipes MinIO data in `drive`, wipes the AST cache in `system`, and clears Valkey data in `cache`. The BotServer database in `tables` is preserved for testing.
|
||||
|
||||
## Daily Operations & Access
|
||||
|
||||
### Accessing Stage Containers
|
||||
|
||||
Because the project is isolated, running commands requires switching the project or specifying it explicitly:
|
||||
```bash
|
||||
# Explicitly access the system container in STAGE-GBO
|
||||
sudo incus exec STAGE-GBO:system -- bash
|
||||
|
||||
# Or switch context entirely
|
||||
sudo incus project switch STAGE-GBO
|
||||
sudo incus list
|
||||
sudo incus exec system -- bash
|
||||
```
|
||||
|
||||
### Resetting Data
|
||||
|
||||
If you need to completely reset a specific component in the staging environment without affecting production, simply stop it, clear its data, and restart it:
|
||||
```bash
|
||||
sudo incus project switch STAGE-GBO
|
||||
sudo incus stop drive
|
||||
sudo incus exec drive -- rm -rf /opt/gbo/data/minio/*
|
||||
sudo incus start drive
|
||||
```
|
||||
|
||||
### Security Directives
|
||||
|
||||
- **NO External Exposure:** The staging environment is internally isolated. Do not map public DNS or Caddy proxy rules to the `10.0.3.x` IPs unless testing is specifically required via a staging domain.
|
||||
- **Data Protection:** Although it's an isolated project, `incus copy` relies on the host's underlying storage. Running aggressive I/O operations or writing massive amounts of data in stage could potentially exhaust the host's shared disk space. The 10GB hard limit per container mitigates this, but monitor `df -h` on the host to ensure `PROD` is not impacted.
|
||||
|
|
@ -18,6 +18,7 @@ impl MessageType {
|
|||
pub const CONTEXT_CHANGE: Self = Self(5);
|
||||
|
||||
pub const TOOL_EXEC: Self = Self(6);
|
||||
pub const SYSTEM: Self = Self(7);
|
||||
}
|
||||
|
||||
impl From<i32> for MessageType {
|
||||
|
|
@ -48,6 +49,7 @@ impl std::fmt::Display for MessageType {
|
|||
4 => "SUGGESTION",
|
||||
5 => "CONTEXT_CHANGE",
|
||||
6 => "TOOL_EXEC",
|
||||
7 => "SYSTEM",
|
||||
_ => "UNKNOWN",
|
||||
};
|
||||
write!(f, "{name}")
|
||||
|
|
|
|||
|
|
@ -438,6 +438,16 @@ impl BotOrchestrator {
|
|||
}
|
||||
}
|
||||
|
||||
// Handle SYSTEM messages (type 7) - inject into history as system role
|
||||
if message.message_type == MessageType::SYSTEM {
|
||||
if !message_content.is_empty() {
|
||||
info!("SYSTEM message injection for session {}", session_id);
|
||||
let mut sm = self.state.session_manager.blocking_lock();
|
||||
sm.save_message(session_id, user_id, 3, &message_content, 1)?; // role 3 = System
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
// Legacy: Handle direct tool invocation via __TOOL__: prefix
|
||||
if message_content.starts_with("__TOOL__:") {
|
||||
let tool_name = message_content.trim_start_matches("__TOOL__:").trim();
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@
|
|||
CONTINUE: 3,
|
||||
SUGGESTION: 4,
|
||||
CONTEXT_CHANGE: 5,
|
||||
SYSTEM: 6, // For switcher/modifier injection - doesn't appear in chat history
|
||||
SYSTEM: 7, // For switcher/modifier injection - doesn't appear in chat history
|
||||
};
|
||||
|
||||
var EntityTypes = {
|
||||
|
|
@ -989,10 +989,10 @@ function hideThinkingIndicator() {
|
|||
|
||||
chip.textContent = suggestion.text || "Suggestion";
|
||||
|
||||
chip.onclick = (function (sugg, act, name) {
|
||||
chip.onclick = (function (sugg, act, name, isSw) {
|
||||
return function () {
|
||||
console.log("Suggestion clicked:", sugg, "as switcher:", isSwitcher);
|
||||
if (isSwitcher) {
|
||||
console.log("Suggestion clicked:", sugg, "as switcher:", isSw);
|
||||
if (isSw) {
|
||||
// Toggle switcher logic
|
||||
if (activeSwitchers.has(name)) {
|
||||
activeSwitchers.delete(name);
|
||||
|
|
@ -1032,7 +1032,7 @@ function hideThinkingIndicator() {
|
|||
// Default fallback: send suggestion text
|
||||
window.sendMessage(sugg.text);
|
||||
};
|
||||
})(suggestion, action, switcherName);
|
||||
})(suggestion, action, switcherName, isSwitcher);
|
||||
|
||||
suggestionsEl.appendChild(chip);
|
||||
});
|
||||
|
|
|
|||
101
setup-stage-gbo.sh
Normal file
101
setup-stage-gbo.sh
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
#!/bin/bash
|
||||
# setup-stage-gbo.sh
|
||||
# Run this on the Incus host (administrator@63.141.255.9)
|
||||
#
|
||||
# This script sets up a STAGE-GBO project that completely isolates the stage
|
||||
# environment from PROD, clones the essential containers, changes their IPs
|
||||
# to 10.0.3.x, restricts disk size to 10GB max, and wipes data where requested.
|
||||
|
||||
set -e
|
||||
|
||||
PROJECT="STAGE-GBO"
|
||||
NETWORK="stagebr0"
|
||||
|
||||
echo "=== 1. Creating Isolated Project: $PROJECT ==="
|
||||
# features.networks and features.profiles isolate the network and profiles from default
|
||||
sudo incus project create $PROJECT \
|
||||
-c features.networks=true \
|
||||
-c features.profiles=true \
|
||||
-c features.storage.volumes=true || echo "Project might already exist."
|
||||
|
||||
sudo incus project switch $PROJECT
|
||||
|
||||
echo "=== 2. Creating Stage Network (10.0.3.x) ==="
|
||||
sudo incus network create $NETWORK ipv4.address=10.0.3.1/24 ipv4.nat=true ipv6.address=none || echo "Network might already exist."
|
||||
|
||||
echo "=== 3. Configuring Stage Default Profile (10GB Limit) ==="
|
||||
# Configure the default profile for the STAGE-GBO project to use the new network
|
||||
sudo incus profile device add default eth0 nic network=$NETWORK name=eth0 || \
|
||||
sudo incus profile device set default eth0 network $NETWORK || true
|
||||
|
||||
# Limit root disk size to 10GB
|
||||
sudo incus profile device add default root disk path=/ pool=default size=10GB || \
|
||||
sudo incus profile device set default root size=10GB || true
|
||||
|
||||
# Containers to clone
|
||||
CONTAINERS=("system" "tables" "vault" "cache" "drive" "llm")
|
||||
|
||||
# Target IPs for stage environment
|
||||
declare -A IPS=(
|
||||
["system"]="10.0.3.10"
|
||||
["tables"]="10.0.3.11"
|
||||
["vault"]="10.0.3.12"
|
||||
["cache"]="10.0.3.13"
|
||||
["drive"]="10.0.3.14"
|
||||
["llm"]="10.0.3.15"
|
||||
)
|
||||
|
||||
echo "=== 4. Cloning Containers from PROD (default project) ==="
|
||||
sudo incus project switch PROD-GBO1
|
||||
|
||||
for c in "${CONTAINERS[@]}"; do
|
||||
echo "Copying $c to $PROJECT..."
|
||||
sudo incus copy PROD-GBO1:$c $PROJECT:$c || echo " Warning: Failed to copy $c. It might already exist."
|
||||
done
|
||||
|
||||
echo "=== 5. Reconfiguring and Cleaning Data in STAGE-GBO ==="
|
||||
sudo incus project switch $PROJECT
|
||||
|
||||
for c in "${CONTAINERS[@]}"; do
|
||||
IP="${IPS[$c]}"
|
||||
echo "--> Starting $c for reconfiguration..."
|
||||
sudo incus start $c || true
|
||||
sleep 3 # Wait for container to initialize
|
||||
|
||||
echo " Setting static IP $IP in /etc/network/interfaces..."
|
||||
sudo incus exec $c -- bash -c "cat > /etc/network/interfaces << 'EOF'
|
||||
auto lo
|
||||
iface lo inet loopback
|
||||
|
||||
auto eth0
|
||||
iface eth0 inet static
|
||||
address $IP
|
||||
netmask 255.255.255.0
|
||||
gateway 10.0.3.1
|
||||
dns-nameservers 8.8.8.8 8.8.4.4
|
||||
EOF"
|
||||
|
||||
echo " Cleaning logs..."
|
||||
sudo incus exec $c -- bash -c 'rm -rf /opt/gbo/logs/* || true'
|
||||
|
||||
# Apply specific data wipe rules
|
||||
if [ "$c" == "drive" ]; then
|
||||
echo " Wiping MinIO data (starting from scratch)..."
|
||||
sudo incus exec $c -- bash -c 'rm -rf /opt/gbo/data/minio/* || true'
|
||||
elif [ "$c" == "tables" ]; then
|
||||
echo " Keeping tables data (database botserver intact as requested)."
|
||||
elif [ "$c" == "cache" ]; then
|
||||
echo " Wiping Valkey cache..."
|
||||
sudo incus exec $c -- bash -c 'rm -rf /opt/gbo/data/valkey/*.rdb /opt/gbo/data/valkey/*.aof || true'
|
||||
elif [ "$c" == "system" ]; then
|
||||
echo " Wiping work directory and compiled ASTs..."
|
||||
sudo incus exec $c -- bash -c 'rm -rf /opt/gbo/work/* || true'
|
||||
fi
|
||||
|
||||
echo " Restarting $c to apply new IP..."
|
||||
sudo incus restart $c || true
|
||||
done
|
||||
|
||||
echo "=== STAGE-GBO Setup Complete ==="
|
||||
echo "You are currently in the default project."
|
||||
sudo incus project switch PROD-GBO1
|
||||
Loading…
Add table
Reference in a new issue