pulsebot 0.3.0__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.
- pulsebot-0.3.0/.claude/settings.local.json +23 -0
- pulsebot-0.3.0/.gitignore +66 -0
- pulsebot-0.3.0/CLAUDE.md +94 -0
- pulsebot-0.3.0/Dockerfile +29 -0
- pulsebot-0.3.0/Dockerfile.proton +68 -0
- pulsebot-0.3.0/Dockerfile.timeplus +71 -0
- pulsebot-0.3.0/Makefile +140 -0
- pulsebot-0.3.0/PKG-INFO +277 -0
- pulsebot-0.3.0/README.md +241 -0
- pulsebot-0.3.0/config.yaml.example +128 -0
- pulsebot-0.3.0/deploy/QUICKSTART_LOCAL.md +51 -0
- pulsebot-0.3.0/deploy/proton/docker-compose.yaml +26 -0
- pulsebot-0.3.0/deploy/timeplus/docker-compose.yaml +30 -0
- pulsebot-0.3.0/docker/entrypoint-proton.sh +15 -0
- pulsebot-0.3.0/docker/entrypoint-timeplus.sh +15 -0
- pulsebot-0.3.0/docker/start-all-in-one.sh +103 -0
- pulsebot-0.3.0/docker-compose.yaml +101 -0
- pulsebot-0.3.0/docs/configuration.md +115 -0
- pulsebot-0.3.0/docs/design.md +511 -0
- pulsebot-0.3.0/docs/memory.md +878 -0
- pulsebot-0.3.0/docs/skills.md +362 -0
- pulsebot-0.3.0/docs/telegram.md +150 -0
- pulsebot-0.3.0/docs/web_search.md +230 -0
- pulsebot-0.3.0/docs/workspace.md +147 -0
- pulsebot-0.3.0/init-proton.sh +23 -0
- pulsebot-0.3.0/pulsebot/__init__.py +3 -0
- pulsebot-0.3.0/pulsebot/api/__init__.py +8 -0
- pulsebot-0.3.0/pulsebot/api/server.py +325 -0
- pulsebot-0.3.0/pulsebot/channels/__init__.py +10 -0
- pulsebot-0.3.0/pulsebot/channels/base.py +76 -0
- pulsebot-0.3.0/pulsebot/channels/telegram.py +244 -0
- pulsebot-0.3.0/pulsebot/cli.py +419 -0
- pulsebot-0.3.0/pulsebot/config.py +361 -0
- pulsebot-0.3.0/pulsebot/core/__init__.py +16 -0
- pulsebot-0.3.0/pulsebot/core/agent.py +763 -0
- pulsebot-0.3.0/pulsebot/core/context.py +306 -0
- pulsebot-0.3.0/pulsebot/core/executor.py +144 -0
- pulsebot-0.3.0/pulsebot/core/prompts.py +205 -0
- pulsebot-0.3.0/pulsebot/core/router.py +233 -0
- pulsebot-0.3.0/pulsebot/embeddings/__init__.py +11 -0
- pulsebot-0.3.0/pulsebot/embeddings/base.py +55 -0
- pulsebot-0.3.0/pulsebot/embeddings/ollama.py +227 -0
- pulsebot-0.3.0/pulsebot/embeddings/openai.py +143 -0
- pulsebot-0.3.0/pulsebot/factory.py +136 -0
- pulsebot-0.3.0/pulsebot/providers/__init__.py +16 -0
- pulsebot-0.3.0/pulsebot/providers/anthropic.py +209 -0
- pulsebot-0.3.0/pulsebot/providers/base.py +114 -0
- pulsebot-0.3.0/pulsebot/providers/gemini.py +207 -0
- pulsebot-0.3.0/pulsebot/providers/nvidia.py +193 -0
- pulsebot-0.3.0/pulsebot/providers/ollama.py +340 -0
- pulsebot-0.3.0/pulsebot/providers/openai.py +195 -0
- pulsebot-0.3.0/pulsebot/skills/__init__.py +11 -0
- pulsebot-0.3.0/pulsebot/skills/agentskills/__init__.py +22 -0
- pulsebot-0.3.0/pulsebot/skills/agentskills/loader.py +139 -0
- pulsebot-0.3.0/pulsebot/skills/agentskills/models.py +39 -0
- pulsebot-0.3.0/pulsebot/skills/base.py +141 -0
- pulsebot-0.3.0/pulsebot/skills/builtin/__init__.py +13 -0
- pulsebot-0.3.0/pulsebot/skills/builtin/agentskills_bridge.py +169 -0
- pulsebot-0.3.0/pulsebot/skills/builtin/file_ops.py +218 -0
- pulsebot-0.3.0/pulsebot/skills/builtin/shell.py +184 -0
- pulsebot-0.3.0/pulsebot/skills/builtin/web_search.py +188 -0
- pulsebot-0.3.0/pulsebot/skills/builtin/workspace.py +497 -0
- pulsebot-0.3.0/pulsebot/skills/loader.py +262 -0
- pulsebot-0.3.0/pulsebot/timeplus/__init__.py +12 -0
- pulsebot-0.3.0/pulsebot/timeplus/client.py +236 -0
- pulsebot-0.3.0/pulsebot/timeplus/memory.py +570 -0
- pulsebot-0.3.0/pulsebot/timeplus/setup.py +226 -0
- pulsebot-0.3.0/pulsebot/timeplus/streams.py +228 -0
- pulsebot-0.3.0/pulsebot/timeplus/tasks.py +216 -0
- pulsebot-0.3.0/pulsebot/utils/__init__.py +22 -0
- pulsebot-0.3.0/pulsebot/utils/helpers.py +45 -0
- pulsebot-0.3.0/pulsebot/utils/logging.py +79 -0
- pulsebot-0.3.0/pulsebot/web/assets/pulsebot_logo_pink.svg +27 -0
- pulsebot-0.3.0/pulsebot/web/index.html +1012 -0
- pulsebot-0.3.0/pulsebot/workspace/__init__.py +45 -0
- pulsebot-0.3.0/pulsebot/workspace/config.py +55 -0
- pulsebot-0.3.0/pulsebot/workspace/manager.py +419 -0
- pulsebot-0.3.0/pulsebot/workspace/proxy_registry.py +90 -0
- pulsebot-0.3.0/pulsebot/workspace/proxy_router.py +166 -0
- pulsebot-0.3.0/pulsebot/workspace/registration_router.py +147 -0
- pulsebot-0.3.0/pulsebot/workspace/registry_client.py +116 -0
- pulsebot-0.3.0/pulsebot/workspace/server.py +281 -0
- pulsebot-0.3.0/pyproject.toml +84 -0
- pulsebot-0.3.0/searxng/settings.yml +6 -0
- pulsebot-0.3.0/skills/timeplus-app-builder/SKILL.md +322 -0
- pulsebot-0.3.0/skills/timeplus-app-builder/references/PROTON_DRIVER.md +223 -0
- pulsebot-0.3.0/skills/timeplus-app-builder/references/STYLE_GUIDE.md +201 -0
- pulsebot-0.3.0/skills/timeplus-app-builder/references/VISTRAL_API.md +359 -0
- pulsebot-0.3.0/skills/timeplus-sql-guide/SKILL.md +280 -0
- pulsebot-0.3.0/skills/timeplus-sql-guide/references/INGESTION.md +303 -0
- pulsebot-0.3.0/skills/timeplus-sql-guide/references/Python_TABLE_FUNCTION.md +307 -0
- pulsebot-0.3.0/skills/timeplus-sql-guide/references/RANDOM_STREAMS.md +434 -0
- pulsebot-0.3.0/skills/timeplus-sql-guide/references/SINKS.md +289 -0
- pulsebot-0.3.0/skills/timeplus-sql-guide/references/SQL_REFERENCE.md +420 -0
- pulsebot-0.3.0/skills/timeplus-sql-guide/references/TRANSFORMATIONS.md +399 -0
- pulsebot-0.3.0/skills/timeplus-sql-guide/references/UDFS.md +406 -0
- pulsebot-0.3.0/tests/__init__.py +0 -0
- pulsebot-0.3.0/tests/test_agentskills.py +288 -0
- pulsebot-0.3.0/uv.lock +2467 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"permissions": {
|
|
3
|
+
"allow": [
|
|
4
|
+
"Bash(tree:*)",
|
|
5
|
+
"Bash(docker compose logs:*)",
|
|
6
|
+
"Bash(python -m py_compile:*)",
|
|
7
|
+
"Bash(docker compose build:*)",
|
|
8
|
+
"Bash(docker compose:*)",
|
|
9
|
+
"Bash(curl:*)",
|
|
10
|
+
"Bash(timeout:*)",
|
|
11
|
+
"Bash(pip install:*)",
|
|
12
|
+
"Bash(gh issue view:*)",
|
|
13
|
+
"WebFetch(domain:github.com)",
|
|
14
|
+
"WebFetch(domain:gist.github.com)",
|
|
15
|
+
"Bash(gh api:*)",
|
|
16
|
+
"Bash(docker-compose logs:*)",
|
|
17
|
+
"Bash(docker logs:*)",
|
|
18
|
+
"Bash(python -m pytest:*)",
|
|
19
|
+
"Bash(.venv/bin/pip install:*)",
|
|
20
|
+
"Bash(.venv/bin/python -m pytest:*)"
|
|
21
|
+
]
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
workspaces/
|
|
2
|
+
.pypirc
|
|
3
|
+
|
|
4
|
+
# Python
|
|
5
|
+
__pycache__/
|
|
6
|
+
*.py[cod]
|
|
7
|
+
*$py.class
|
|
8
|
+
*.so
|
|
9
|
+
.Python
|
|
10
|
+
build/
|
|
11
|
+
develop-eggs/
|
|
12
|
+
dist/
|
|
13
|
+
downloads/
|
|
14
|
+
eggs/
|
|
15
|
+
.eggs/
|
|
16
|
+
lib/
|
|
17
|
+
lib64/
|
|
18
|
+
parts/
|
|
19
|
+
sdist/
|
|
20
|
+
var/
|
|
21
|
+
wheels/
|
|
22
|
+
*.egg-info/
|
|
23
|
+
.installed.cfg
|
|
24
|
+
*.egg
|
|
25
|
+
|
|
26
|
+
# Virtual environments
|
|
27
|
+
.venv/
|
|
28
|
+
venv/
|
|
29
|
+
ENV/
|
|
30
|
+
|
|
31
|
+
# IDE
|
|
32
|
+
.idea/
|
|
33
|
+
.vscode/
|
|
34
|
+
*.swp
|
|
35
|
+
*.swo
|
|
36
|
+
*~
|
|
37
|
+
|
|
38
|
+
# Testing
|
|
39
|
+
.tox/
|
|
40
|
+
.nox/
|
|
41
|
+
.coverage
|
|
42
|
+
.coverage.*
|
|
43
|
+
htmlcov/
|
|
44
|
+
.pytest_cache/
|
|
45
|
+
.mypy_cache/
|
|
46
|
+
|
|
47
|
+
# Jupyter
|
|
48
|
+
.ipynb_checkpoints/
|
|
49
|
+
|
|
50
|
+
# Environment variables
|
|
51
|
+
.env
|
|
52
|
+
.env.local
|
|
53
|
+
.env.*.local
|
|
54
|
+
|
|
55
|
+
# Logs
|
|
56
|
+
*.log
|
|
57
|
+
logs/
|
|
58
|
+
|
|
59
|
+
# macOS
|
|
60
|
+
.DS_Store
|
|
61
|
+
|
|
62
|
+
# Docker
|
|
63
|
+
docker-compose.override.yml
|
|
64
|
+
|
|
65
|
+
# Project specific
|
|
66
|
+
config.yaml
|
pulsebot-0.3.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
PulseBot is a stream-native AI agent framework powered by Timeplus (streaming SQL database). All communication, events, and state changes flow through Timeplus streams rather than traditional file systems or databases.
|
|
8
|
+
|
|
9
|
+
## Common Commands
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
# CLI commands (after installation)
|
|
13
|
+
pulsebot run # Start agent main loop (listens to message streams)
|
|
14
|
+
pulsebot serve # Start FastAPI server on port 8000
|
|
15
|
+
pulsebot chat # Interactive CLI chat
|
|
16
|
+
pulsebot init # Generate default config.yaml
|
|
17
|
+
pulsebot task list # List scheduled tasks
|
|
18
|
+
|
|
19
|
+
# Development
|
|
20
|
+
pytest # Run all tests
|
|
21
|
+
pytest -v # Verbose test output
|
|
22
|
+
pytest --cov # Run tests with coverage
|
|
23
|
+
ruff check . # Lint code
|
|
24
|
+
mypy pulsebot/ # Type checking
|
|
25
|
+
|
|
26
|
+
# Docker deployment
|
|
27
|
+
docker-compose up -d # Start all services (proton, agent, api)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Architecture
|
|
31
|
+
|
|
32
|
+
### Stream-Native Communication
|
|
33
|
+
|
|
34
|
+
All components communicate via Timeplus streams (unbounded append-only data):
|
|
35
|
+
|
|
36
|
+
1. **Input Channels** (Telegram, Webchat) → Write to `messages` stream
|
|
37
|
+
2. **Agent Core** → Reads from `messages`, processes via LLM, writes responses back
|
|
38
|
+
3. **Skills/Tools** → Execute when called, results flow back through messages
|
|
39
|
+
4. **Observability** → All LLM calls logged to `llm_logs` stream, memories to `memory` stream
|
|
40
|
+
|
|
41
|
+
### Agent Loop (core/agent.py)
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
1. Listen for messages targeting 'agent' on messages stream
|
|
45
|
+
2. For each message:
|
|
46
|
+
a. Build context (conversation history + relevant memories via vector search)
|
|
47
|
+
b. Get available tools from loaded skills
|
|
48
|
+
c. Loop (max 10 iterations):
|
|
49
|
+
- Call LLM with context + tools
|
|
50
|
+
- Log call to llm_logs stream
|
|
51
|
+
- If tool calls: execute tools, add results to context
|
|
52
|
+
- Else: send response, extract/store memories, break
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Key Source Directories
|
|
56
|
+
|
|
57
|
+
- `pulsebot/core/` - Agent loop, context building, tool execution, routing
|
|
58
|
+
- `pulsebot/providers/` - LLM provider implementations (Anthropic, OpenAI, OpenRouter, Ollama, NVIDIA)
|
|
59
|
+
- `pulsebot/skills/` - Tool/skill system with builtin skills (web_search, file_ops, shell)
|
|
60
|
+
- `pulsebot/channels/` - Input channels (Telegram bot integration)
|
|
61
|
+
- `pulsebot/timeplus/` - Timeplus client, stream reader/writer, vector memory, scheduled tasks
|
|
62
|
+
- `pulsebot/api/` - FastAPI server with REST and WebSocket endpoints
|
|
63
|
+
- `pulsebot/web/` - Web chat UI (served at http://localhost:8000/)
|
|
64
|
+
|
|
65
|
+
### Timeplus Streams
|
|
66
|
+
|
|
67
|
+
| Stream | Purpose |
|
|
68
|
+
|--------|---------|
|
|
69
|
+
| `messages` | Central communication hub (source, target, session_id, content) |
|
|
70
|
+
| `llm_logs` | LLM call observability (model, tokens, latency, status) |
|
|
71
|
+
| `memory` | Vector-indexed knowledge base with embeddings |
|
|
72
|
+
| `events` | System events and alerts |
|
|
73
|
+
|
|
74
|
+
### Design Patterns
|
|
75
|
+
|
|
76
|
+
**Provider Pattern**: All LLM providers implement `LLMProvider` base class with `async chat()` returning `LLMResponse`
|
|
77
|
+
|
|
78
|
+
**Skill Pattern**: Skills inherit from `BaseSkill` with `get_tools()` → `ToolDefinition` and `async execute()` → `ToolResult`
|
|
79
|
+
|
|
80
|
+
**Stream Operations**: `StreamReader` for async iteration, `StreamWriter` for writes, `TimeplusClient` for low-level protocol
|
|
81
|
+
|
|
82
|
+
## Configuration
|
|
83
|
+
|
|
84
|
+
`config.yaml` uses Pydantic validation with environment variable substitution (`${VAR_NAME}` or `${VAR_NAME:-default}`):
|
|
85
|
+
- `agent`: name, model, provider, temperature
|
|
86
|
+
- `timeplus`: host, port, credentials
|
|
87
|
+
- `providers`: API keys for Anthropic, OpenAI, OpenRouter, Ollama, NVIDIA
|
|
88
|
+
- `channels`: Telegram settings
|
|
89
|
+
- `skills`: enabled builtin skills
|
|
90
|
+
|
|
91
|
+
## Requirements
|
|
92
|
+
|
|
93
|
+
- Python 3.11+
|
|
94
|
+
- Timeplus/Proton (streaming database, port 8463)
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
FROM python:3.12-slim
|
|
2
|
+
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
|
|
5
|
+
# Install system dependencies
|
|
6
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
7
|
+
gcc \
|
|
8
|
+
libpq-dev \
|
|
9
|
+
curl \
|
|
10
|
+
nodejs \
|
|
11
|
+
npm \
|
|
12
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
13
|
+
|
|
14
|
+
# Copy project files needed for installation
|
|
15
|
+
COPY pyproject.toml README.md ./
|
|
16
|
+
COPY pulsebot/ ./pulsebot/
|
|
17
|
+
|
|
18
|
+
# Install Python dependencies (non-editable for Docker)
|
|
19
|
+
RUN pip install --no-cache-dir --extra-index-url https://d.timeplus.com/simple/ .
|
|
20
|
+
|
|
21
|
+
# Copy config template
|
|
22
|
+
COPY config.yaml ./
|
|
23
|
+
|
|
24
|
+
# Create non-root user
|
|
25
|
+
RUN useradd --create-home appuser && chown -R appuser:appuser /app
|
|
26
|
+
USER appuser
|
|
27
|
+
|
|
28
|
+
# Default command
|
|
29
|
+
CMD ["pulsebot", "run"]
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# All-in-One Docker Image for PulseBot with Proton
|
|
2
|
+
FROM d.timeplus.com/timeplus-io/proton:latest
|
|
3
|
+
|
|
4
|
+
# Suppress interactive prompts for all apt-get calls in this build
|
|
5
|
+
ENV DEBIAN_FRONTEND=noninteractive
|
|
6
|
+
|
|
7
|
+
# Switch to root to install dependencies
|
|
8
|
+
USER root
|
|
9
|
+
|
|
10
|
+
# Install Python 3.12 via deadsnakes PPA (agent-free key import for Docker builds)
|
|
11
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
12
|
+
curl \
|
|
13
|
+
gpg \
|
|
14
|
+
lsb-release \
|
|
15
|
+
ca-certificates \
|
|
16
|
+
&& mkdir -p /etc/apt/keyrings \
|
|
17
|
+
&& curl -fsSL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xF23C5A6CF475977595C89F51BA6932366A755776" \
|
|
18
|
+
| gpg --batch --no-tty --no-autostart --dearmor -o /etc/apt/keyrings/deadsnakes.gpg \
|
|
19
|
+
&& echo "deb [signed-by=/etc/apt/keyrings/deadsnakes.gpg] https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu $(lsb_release -cs) main" \
|
|
20
|
+
> /etc/apt/sources.list.d/deadsnakes.list \
|
|
21
|
+
&& curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
|
|
22
|
+
&& apt-get update \
|
|
23
|
+
&& apt-get install -y --no-install-recommends \
|
|
24
|
+
python3.12 \
|
|
25
|
+
python3.12-venv \
|
|
26
|
+
nodejs \
|
|
27
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
28
|
+
|
|
29
|
+
# Create symlinks for python and pip
|
|
30
|
+
RUN ln -sf /usr/bin/python3.12 /usr/bin/python
|
|
31
|
+
RUN ln -sf /usr/bin/python3.12 /usr/bin/python3
|
|
32
|
+
|
|
33
|
+
# Install pip for Python 3.12
|
|
34
|
+
RUN curl -sS https://bootstrap.pypa.io/get-pip.py | python3.12
|
|
35
|
+
|
|
36
|
+
WORKDIR /app
|
|
37
|
+
|
|
38
|
+
# Copy project files needed for installation
|
|
39
|
+
COPY pyproject.toml README.md ./
|
|
40
|
+
COPY pulsebot/ ./pulsebot/
|
|
41
|
+
COPY skills/ ./skills/
|
|
42
|
+
|
|
43
|
+
# Install Python dependencies (non-editable for Docker)
|
|
44
|
+
RUN python3.12 -m pip install --no-cache-dir --extra-index-url https://d.timeplus.com/simple/ .
|
|
45
|
+
|
|
46
|
+
# Copy config template and scripts
|
|
47
|
+
COPY docker/config.yaml ./config.yaml
|
|
48
|
+
COPY docker/start-all-in-one.sh /usr/local/bin/
|
|
49
|
+
COPY docker/entrypoint-proton.sh /usr/local/bin/
|
|
50
|
+
|
|
51
|
+
# Make scripts executable
|
|
52
|
+
RUN chmod +x /usr/local/bin/start-all-in-one.sh /usr/local/bin/entrypoint-proton.sh
|
|
53
|
+
|
|
54
|
+
# Change ownership of app directory to timeplus user
|
|
55
|
+
RUN chown -R timeplus:timeplus /app
|
|
56
|
+
|
|
57
|
+
# Switch back to timeplus user
|
|
58
|
+
USER timeplus
|
|
59
|
+
|
|
60
|
+
# Expose ports
|
|
61
|
+
# 8123: HTTP port (batch queries)
|
|
62
|
+
# 3218: Streaming port
|
|
63
|
+
# 8463: Native TCP
|
|
64
|
+
# 8001: PulseBot API Server
|
|
65
|
+
EXPOSE 8123 3218 8463 8001
|
|
66
|
+
|
|
67
|
+
# Use our custom entrypoint
|
|
68
|
+
ENTRYPOINT ["/usr/local/bin/entrypoint-proton.sh"]
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# All-in-One Docker Image for PulseBot with Timeplus Enterprise
|
|
2
|
+
FROM timeplus/timeplus-enterprise:3.1.2-rc.2
|
|
3
|
+
|
|
4
|
+
# Suppress interactive prompts for all apt-get calls in this build
|
|
5
|
+
ENV DEBIAN_FRONTEND=noninteractive
|
|
6
|
+
|
|
7
|
+
# Switch to root to install dependencies
|
|
8
|
+
USER root
|
|
9
|
+
|
|
10
|
+
# Install Python 3.12 via deadsnakes PPA (agent-free key import for Docker builds)
|
|
11
|
+
RUN apt-get update && apt-get install -y --no-install-recommends \
|
|
12
|
+
curl \
|
|
13
|
+
gpg \
|
|
14
|
+
lsb-release \
|
|
15
|
+
ca-certificates \
|
|
16
|
+
&& mkdir -p /etc/apt/keyrings \
|
|
17
|
+
&& curl -fsSL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0xF23C5A6CF475977595C89F51BA6932366A755776" \
|
|
18
|
+
| gpg --batch --no-tty --no-autostart --dearmor -o /etc/apt/keyrings/deadsnakes.gpg \
|
|
19
|
+
&& echo "deb [signed-by=/etc/apt/keyrings/deadsnakes.gpg] https://ppa.launchpadcontent.net/deadsnakes/ppa/ubuntu $(lsb_release -cs) main" \
|
|
20
|
+
> /etc/apt/sources.list.d/deadsnakes.list \
|
|
21
|
+
&& curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
|
|
22
|
+
&& apt-get update \
|
|
23
|
+
&& apt-get install -y --no-install-recommends \
|
|
24
|
+
python3.12 \
|
|
25
|
+
python3.12-venv \
|
|
26
|
+
nodejs \
|
|
27
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
28
|
+
|
|
29
|
+
# Create symlinks for python and pip
|
|
30
|
+
RUN ln -sf /usr/bin/python3.12 /usr/bin/python
|
|
31
|
+
RUN ln -sf /usr/bin/python3.12 /usr/bin/python3
|
|
32
|
+
|
|
33
|
+
# Install pip for Python 3.12
|
|
34
|
+
RUN curl -sS https://bootstrap.pypa.io/get-pip.py | python3.12
|
|
35
|
+
|
|
36
|
+
WORKDIR /app
|
|
37
|
+
|
|
38
|
+
# Copy project files needed for installation
|
|
39
|
+
COPY pyproject.toml README.md ./
|
|
40
|
+
COPY pulsebot/ ./pulsebot/
|
|
41
|
+
COPY skills/ ./skills/
|
|
42
|
+
|
|
43
|
+
# Install Python dependencies (non-editable for Docker)
|
|
44
|
+
RUN python3.12 -m pip install --no-cache-dir --extra-index-url https://d.timeplus.com/simple/ .
|
|
45
|
+
|
|
46
|
+
# Copy config template and scripts
|
|
47
|
+
COPY docker/config.yaml ./config.yaml
|
|
48
|
+
COPY docker/start-all-in-one.sh /usr/local/bin/
|
|
49
|
+
COPY docker/entrypoint-timeplus.sh /usr/local/bin/
|
|
50
|
+
|
|
51
|
+
# Make scripts executable
|
|
52
|
+
RUN chmod +x /usr/local/bin/start-all-in-one.sh /usr/local/bin/entrypoint-timeplus.sh
|
|
53
|
+
|
|
54
|
+
# Set ownership and switch back to the base image's default user if one exists
|
|
55
|
+
RUN if getent passwd timeplus > /dev/null 2>&1; then \
|
|
56
|
+
chown -R timeplus:timeplus /app; \
|
|
57
|
+
elif getent passwd proton > /dev/null 2>&1; then \
|
|
58
|
+
chown -R proton:proton /app; \
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
# Expose ports
|
|
62
|
+
# 8000: Timeplus Enterprise Web UI
|
|
63
|
+
# 8123: HTTP port (batch queries)
|
|
64
|
+
# 3218: Streaming port
|
|
65
|
+
# 8463: Native TCP
|
|
66
|
+
# 8001: PulseBot API Server
|
|
67
|
+
EXPOSE 8000 8123 3218 8463 8001
|
|
68
|
+
|
|
69
|
+
# Try to switch back to timeplus or proton user if available, otherwise stay as root
|
|
70
|
+
# Use our custom entrypoint
|
|
71
|
+
ENTRYPOINT ["/usr/local/bin/entrypoint-timeplus.sh"]
|
pulsebot-0.3.0/Makefile
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# PulseBot Docker Makefile
|
|
2
|
+
# Build and push Docker images to Docker Hub
|
|
3
|
+
|
|
4
|
+
# Variables
|
|
5
|
+
IMAGE_NAME := pulsebot
|
|
6
|
+
IMAGE_TAG ?= 0.3.0
|
|
7
|
+
DOCKER_REPO := timeplus
|
|
8
|
+
FULL_IMAGE_NAME := $(DOCKER_REPO)/$(IMAGE_NAME):$(IMAGE_TAG)
|
|
9
|
+
ALL_IN_ONE_PROTON_NAME := $(DOCKER_REPO)/$(IMAGE_NAME)-proton:$(IMAGE_TAG)
|
|
10
|
+
ALL_IN_ONE_TIMEPLUS_NAME := $(DOCKER_REPO)/$(IMAGE_NAME)-timeplus:$(IMAGE_TAG)
|
|
11
|
+
|
|
12
|
+
# Default registry (Docker Hub)
|
|
13
|
+
REGISTRY := docker.io
|
|
14
|
+
|
|
15
|
+
# Multi-platform support
|
|
16
|
+
PLATFORMS ?= linux/amd64,linux/arm64
|
|
17
|
+
SINGLE_PLATFORM ?= linux/amd64
|
|
18
|
+
|
|
19
|
+
# Docker build arguments
|
|
20
|
+
DOCKER_BUILD_ARGS ?=
|
|
21
|
+
|
|
22
|
+
# Help target
|
|
23
|
+
.PHONY: help
|
|
24
|
+
help:
|
|
25
|
+
@echo "PulseBot Docker Makefile"
|
|
26
|
+
@echo ""
|
|
27
|
+
@echo "Targets:"
|
|
28
|
+
@echo " build Build Docker image locally (single platform)"
|
|
29
|
+
@echo " build-multi Build Docker image for multiple platforms"
|
|
30
|
+
@echo " tag Tag the image for Docker Hub"
|
|
31
|
+
@echo " push Push image to Docker Hub"
|
|
32
|
+
@echo " build-push Build and push image to Docker Hub (single platform)"
|
|
33
|
+
@echo " build-push-multi Build and push multi-platform image to Docker Hub"
|
|
34
|
+
@echo " build-all-in-one-proton Build all-in-one image with Proton"
|
|
35
|
+
@echo " build-all-in-one-timeplus Build all-in-one image with Timeplus Enterprise"
|
|
36
|
+
@echo " push-all-in-one-proton Push all-in-one Proton image to registry"
|
|
37
|
+
@echo " push-all-in-one-timeplus Push all-in-one Timeplus image to registry"
|
|
38
|
+
@echo " clean Remove local Docker image"
|
|
39
|
+
@echo ""
|
|
40
|
+
@echo "Variables:"
|
|
41
|
+
@echo " IMAGE_TAG Docker image tag (default: 0.1.1)"
|
|
42
|
+
@echo " DOCKER_REPO Docker Hub repository (default: timeplus)"
|
|
43
|
+
@echo " PLATFORMS Platforms for multi-platform build (default: linux/amd64,linux/arm64)"
|
|
44
|
+
@echo " SINGLE_PLATFORM Platform for single platform build (default: linux/amd64)"
|
|
45
|
+
@echo " DOCKER_BUILD_ARGS Additional docker build arguments"
|
|
46
|
+
|
|
47
|
+
# Build the Docker image (single platform)
|
|
48
|
+
.PHONY: build
|
|
49
|
+
build:
|
|
50
|
+
docker build --platform=$(SINGLE_PLATFORM) $(DOCKER_BUILD_ARGS) -t $(IMAGE_NAME):$(IMAGE_TAG) .
|
|
51
|
+
|
|
52
|
+
# Build the Docker image (multi-platform)
|
|
53
|
+
.PHONY: build-multi
|
|
54
|
+
build-multi:
|
|
55
|
+
docker buildx build --platform=$(PLATFORMS) $(DOCKER_BUILD_ARGS) -t $(IMAGE_NAME):$(IMAGE_TAG) .
|
|
56
|
+
|
|
57
|
+
# Build all-in-one image with Proton
|
|
58
|
+
.PHONY: build-all-in-one-proton
|
|
59
|
+
build-all-in-one-proton:
|
|
60
|
+
docker build --platform=$(SINGLE_PLATFORM) $(DOCKER_BUILD_ARGS) -t $(ALL_IN_ONE_PROTON_NAME) -f Dockerfile.proton .
|
|
61
|
+
|
|
62
|
+
# Build all-in-one image with Timeplus Enterprise
|
|
63
|
+
.PHONY: build-all-in-one-timeplus
|
|
64
|
+
build-all-in-one-timeplus:
|
|
65
|
+
docker build --platform=$(SINGLE_PLATFORM) $(DOCKER_BUILD_ARGS) -t $(ALL_IN_ONE_TIMEPLUS_NAME) -f Dockerfile.timeplus .
|
|
66
|
+
|
|
67
|
+
# Tag the image for Docker Hub
|
|
68
|
+
.PHONY: tag
|
|
69
|
+
tag:
|
|
70
|
+
docker tag $(IMAGE_NAME):$(IMAGE_TAG) $(FULL_IMAGE_NAME)
|
|
71
|
+
|
|
72
|
+
# Push the image to Docker Hub (single platform)
|
|
73
|
+
.PHONY: push
|
|
74
|
+
push:
|
|
75
|
+
docker push $(FULL_IMAGE_NAME)
|
|
76
|
+
|
|
77
|
+
# Push all-in-one Proton image to registry
|
|
78
|
+
.PHONY: push-all-in-one-proton
|
|
79
|
+
push-all-in-one-proton:
|
|
80
|
+
docker push $(ALL_IN_ONE_PROTON_NAME)
|
|
81
|
+
|
|
82
|
+
# Push all-in-one Timeplus image to registry
|
|
83
|
+
.PHONY: push-all-in-one-timeplus
|
|
84
|
+
push-all-in-one-timeplus:
|
|
85
|
+
docker push $(ALL_IN_ONE_TIMEPLUS_NAME)
|
|
86
|
+
|
|
87
|
+
# Build and push the image to Docker Hub (single platform)
|
|
88
|
+
.PHONY: build-push
|
|
89
|
+
build-push: build tag push
|
|
90
|
+
|
|
91
|
+
# Build and push the image to Docker Hub (multi-platform)
|
|
92
|
+
.PHONY: build-push-multi
|
|
93
|
+
build-push-multi: buildx-setup
|
|
94
|
+
docker buildx build --platform=$(PLATFORMS) $(DOCKER_BUILD_ARGS) -t $(FULL_IMAGE_NAME) --push .
|
|
95
|
+
|
|
96
|
+
# Build and push all-in-one Proton image
|
|
97
|
+
.PHONY: build-push-all-in-one-proton
|
|
98
|
+
build-push-all-in-one-proton: build-all-in-one-proton
|
|
99
|
+
docker tag $(ALL_IN_ONE_PROTON_NAME) $(REGISTRY)/$(ALL_IN_ONE_PROTON_NAME)
|
|
100
|
+
docker push $(REGISTRY)/$(ALL_IN_ONE_PROTON_NAME)
|
|
101
|
+
|
|
102
|
+
# Build and push all-in-one Timeplus image
|
|
103
|
+
.PHONY: build-push-all-in-one-timeplus
|
|
104
|
+
build-push-all-in-one-timeplus: build-all-in-one-timeplus
|
|
105
|
+
docker tag $(ALL_IN_ONE_TIMEPLUS_NAME) $(REGISTRY)/$(ALL_IN_ONE_TIMEPLUS_NAME)
|
|
106
|
+
docker push $(REGISTRY)/$(ALL_IN_ONE_TIMEPLUS_NAME)
|
|
107
|
+
|
|
108
|
+
# Setup Docker buildx builder
|
|
109
|
+
.PHONY: buildx-setup
|
|
110
|
+
buildx-setup:
|
|
111
|
+
docker buildx create --name pulsebot-builder --use 2>/dev/null || docker buildx use pulsebot-builder
|
|
112
|
+
|
|
113
|
+
# Remove local Docker image
|
|
114
|
+
.PHONY: clean
|
|
115
|
+
clean:
|
|
116
|
+
docker rmi $(IMAGE_NAME):$(IMAGE_TAG) || true
|
|
117
|
+
docker rmi $(FULL_IMAGE_NAME) || true
|
|
118
|
+
|
|
119
|
+
# Login to Docker Hub (optional target)
|
|
120
|
+
.PHONY: login
|
|
121
|
+
login:
|
|
122
|
+
docker login
|
|
123
|
+
|
|
124
|
+
# Display image information
|
|
125
|
+
.PHONY: info
|
|
126
|
+
info:
|
|
127
|
+
@echo "Image Name: $(IMAGE_NAME)"
|
|
128
|
+
@echo "Image Tag: $(IMAGE_TAG)"
|
|
129
|
+
@echo "Docker Repository: $(DOCKER_REPO)"
|
|
130
|
+
@echo "Full Image Name: $(FULL_IMAGE_NAME)"
|
|
131
|
+
@echo "Registry: $(REGISTRY)"
|
|
132
|
+
@echo "Single Platform: $(SINGLE_PLATFORM)"
|
|
133
|
+
@echo "Multi Platforms: $(PLATFORMS)"
|
|
134
|
+
|
|
135
|
+
# Publish to PyPI
|
|
136
|
+
.PHONY: publish
|
|
137
|
+
publish:
|
|
138
|
+
rm -rf dist/*
|
|
139
|
+
uvx --from build pyproject-build --installer uv
|
|
140
|
+
uvx --from twine twine upload --config-file .pypirc dist/*
|