chore: Remove portfolio folder
Moved to dedicated nimmerverse-web repo. Portfolio deserves its own deployable unit. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,311 +0,0 @@
|
|||||||
---
|
|
||||||
type: implementation_plan
|
|
||||||
status: planning
|
|
||||||
created: 2026-02-06
|
|
||||||
author: Nyx (with dafit)
|
|
||||||
purpose: Phase 3 implementation via living portfolio
|
|
||||||
---
|
|
||||||
|
|
||||||
# Portfolio: Phase 3 Living Implementation
|
|
||||||
|
|
||||||
> *"The portfolio IS the nervous system's first organism."*
|
|
||||||
> — The Synthesis (2026-02-06)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Overview
|
|
||||||
|
|
||||||
The nimmerverse portfolio website serves dual purpose:
|
|
||||||
1. **Job search**: Interactive resume showcasing skills through demonstration
|
|
||||||
2. **Phase 3 implementation**: First real deployment of NATS, Function Gemma, and Math Cells
|
|
||||||
|
|
||||||
**URL**: `resume.nimmerverse.com` (or `portfolio.nimmerverse.com`)
|
|
||||||
**VIP Available**: 213.188.249.164 (nimmerverse.eachpath.com)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────────────┐
|
|
||||||
│ PORTFOLIO ARCHITECTURE │
|
|
||||||
│ (Phase 3 Nervous System) │
|
|
||||||
├─────────────────────────────────────────────────────────────────┤
|
|
||||||
│ │
|
|
||||||
│ User Browser │
|
|
||||||
│ │ │
|
|
||||||
│ ▼ │
|
|
||||||
│ ┌─────────────────┐ │
|
|
||||||
│ │ Frontend │ Streamlit / Astro / simple HTML │
|
|
||||||
│ │ (K8s Pod) │ │
|
|
||||||
│ └────────┬────────┘ │
|
|
||||||
│ │ HTTP/WebSocket │
|
|
||||||
│ ▼ │
|
|
||||||
│ ┌─────────────────┐ │
|
|
||||||
│ │ NATS Router │ Message bus (nimmerverse-infra namespace) │
|
|
||||||
│ └────────┬────────┘ │
|
|
||||||
│ │ │
|
|
||||||
│ ┌─────┴─────────────────┬─────────────────┐ │
|
|
||||||
│ ▼ ▼ ▼ │
|
|
||||||
│ ┌──────────┐ ┌───────────┐ ┌───────────┐ │
|
|
||||||
│ │ Function │ │ Math Cell │ │ RAG Cell │ │
|
|
||||||
│ │ Gemma │ │ git_stats │ │ doc_query │ │
|
|
||||||
│ └────┬─────┘ └─────┬─────┘ └─────┬─────┘ │
|
|
||||||
│ │ │ │ │
|
|
||||||
│ Parse intent Query phoebe ChromaDB/Iris │
|
|
||||||
│ → structured + git history over nimmerverse │
|
|
||||||
│ JSON → statistics docs │
|
|
||||||
│ │
|
|
||||||
└─────────────────────────────────────────────────────────────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Components
|
|
||||||
|
|
||||||
### 1. NATS Message Router
|
|
||||||
|
|
||||||
**Purpose**: Route user queries to appropriate handlers
|
|
||||||
**Namespace**: `nimmerverse-infra`
|
|
||||||
**Topics**:
|
|
||||||
- `portfolio.query.intent` → Function Gemma (parse user input)
|
|
||||||
- `portfolio.query.stats` → Math Cells (compute statistics)
|
|
||||||
- `portfolio.query.docs` → RAG Cell (document retrieval)
|
|
||||||
- `portfolio.response` → Aggregate and return to frontend
|
|
||||||
|
|
||||||
### 2. FunctionGemma Cell
|
|
||||||
|
|
||||||
**Purpose**: Parse natural language → structured JSON (intent + API calls)
|
|
||||||
**Model**: `google/functiongemma-270m-it`
|
|
||||||
**Deployment**: Ollama (`ollama pull functiongemma`)
|
|
||||||
|
|
||||||
**Why FunctionGemma?**
|
|
||||||
| Spec | Value | Benefit |
|
|
||||||
|------|-------|---------|
|
|
||||||
| Parameters | 270M | Tiny, fast |
|
|
||||||
| RAM | ~550MB | Runs on anything |
|
|
||||||
| VRAM | ~1-2GB | CPU or minimal GPU |
|
|
||||||
| Vocab | 256K (JSON-optimized) | Clean structured output |
|
|
||||||
|
|
||||||
**Reference**: [`/references/software/functiongemma/FunctionGemma-Overview.md`](../../references/software/functiongemma/FunctionGemma-Overview.md)
|
|
||||||
|
|
||||||
**Input**: Raw user query
|
|
||||||
**Output**: Structured function call
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"function": "fetch_document",
|
|
||||||
"params": {
|
|
||||||
"path": "Endgame-Vision.md",
|
|
||||||
"section": "K8s Cluster Architecture"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
**Function Definitions** (our API surface):
|
|
||||||
```python
|
|
||||||
PORTFOLIO_FUNCTIONS = [
|
|
||||||
{
|
|
||||||
"name": "fetch_document",
|
|
||||||
"description": "Retrieve a document or section from the nimmerverse",
|
|
||||||
"params": {"path": "string", "section": "string (optional)"}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "compute_git_stats",
|
|
||||||
"description": "Get git statistics (commits, LOC, activity)",
|
|
||||||
"params": {"period": "week|month|all"}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "query_tasks",
|
|
||||||
"description": "List tasks from the nimmerverse task planner",
|
|
||||||
"params": {"status": "todo|in_progress|done|all", "project": "string (optional)"}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "search_docs",
|
|
||||||
"description": "Search across all documentation",
|
|
||||||
"params": {"query": "string"}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "show_architecture",
|
|
||||||
"description": "Display architecture diagrams",
|
|
||||||
"params": {"component": "k8s|network|cells|full"}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
```
|
|
||||||
|
|
||||||
**Chat Template Format** (FunctionGemma-specific):
|
|
||||||
|
|
||||||
```
|
|
||||||
<start_of_turn>developer
|
|
||||||
You can do function calling with the following functions:
|
|
||||||
|
|
||||||
<start_function_declaration>declaration:fetch_document{
|
|
||||||
description: "Retrieve a document or section from the nimmerverse",
|
|
||||||
parameters: { path: STRING, section: STRING (optional) }
|
|
||||||
}
|
|
||||||
<end_function_declaration>
|
|
||||||
|
|
||||||
<start_function_declaration>declaration:compute_git_stats{
|
|
||||||
description: "Get git statistics (commits, LOC, activity)",
|
|
||||||
parameters: { period: STRING }
|
|
||||||
}
|
|
||||||
<end_function_declaration>
|
|
||||||
|
|
||||||
<start_function_declaration>declaration:query_tasks{
|
|
||||||
description: "List tasks from the nimmerverse task planner",
|
|
||||||
parameters: { status: STRING, project: STRING (optional) }
|
|
||||||
}
|
|
||||||
<end_function_declaration>
|
|
||||||
|
|
||||||
<start_function_declaration>declaration:search_docs{
|
|
||||||
description: "Search across all documentation",
|
|
||||||
parameters: { query: STRING }
|
|
||||||
}
|
|
||||||
<end_function_declaration>
|
|
||||||
|
|
||||||
<start_function_declaration>declaration:show_architecture{
|
|
||||||
description: "Display architecture diagrams",
|
|
||||||
parameters: { component: STRING }
|
|
||||||
}
|
|
||||||
<end_function_declaration>
|
|
||||||
<end_of_turn>
|
|
||||||
|
|
||||||
<start_of_turn>user
|
|
||||||
How active is this project?
|
|
||||||
<end_of_turn>
|
|
||||||
|
|
||||||
<start_of_turn>model
|
|
||||||
<think>
|
|
||||||
The user wants to know about project activity. I should use compute_git_stats
|
|
||||||
with period "month" to show recent activity.
|
|
||||||
</think>
|
|
||||||
<start_function_call>call:compute_git_stats{
|
|
||||||
period: "month"
|
|
||||||
}
|
|
||||||
<end_function_call>
|
|
||||||
```
|
|
||||||
|
|
||||||
**Fine-Tuning Option** (for nimmerverse-specific reasoning):
|
|
||||||
- Unsloth notebooks: [Reason before Tool Calling](https://colab.research.google.com/...)
|
|
||||||
- `<think></think>` blocks for chain-of-thought before function calls
|
|
||||||
- Could train on our actual function surface + nimmerverse context
|
|
||||||
|
|
||||||
**Deployment**:
|
|
||||||
```bash
|
|
||||||
# On k8s-master or dioscuri (minimal resources needed)
|
|
||||||
ollama pull functiongemma
|
|
||||||
# Expose via K8s service
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. Math Cells
|
|
||||||
|
|
||||||
**git_stats_cell**:
|
|
||||||
- Total commits (all time, this month, this week)
|
|
||||||
- Lines of code
|
|
||||||
- Files changed
|
|
||||||
- Commit frequency graph data
|
|
||||||
|
|
||||||
**task_stats_cell**:
|
|
||||||
- Query phoebe `nimmerverse_tasks` table
|
|
||||||
- Tasks by status (done/in_progress/todo)
|
|
||||||
- Tasks by priority
|
|
||||||
- Progress percentage
|
|
||||||
|
|
||||||
**project_stats_cell**:
|
|
||||||
- Submodule count
|
|
||||||
- Documentation pages
|
|
||||||
- Architecture components
|
|
||||||
|
|
||||||
### 4. RAG Cell (doc_query)
|
|
||||||
|
|
||||||
**Purpose**: Answer questions about the nimmerverse
|
|
||||||
**Index**: ChromaDB (iris) or simple in-memory FAISS
|
|
||||||
**Corpus**:
|
|
||||||
- Endgame-Vision.md
|
|
||||||
- Architecture docs
|
|
||||||
- ADR records
|
|
||||||
- Task history
|
|
||||||
|
|
||||||
### 5. Frontend
|
|
||||||
|
|
||||||
**Options** (decide later):
|
|
||||||
- **Streamlit**: Fast to build, Python native, good for chat UI
|
|
||||||
- **Astro**: Static + islands, professional look
|
|
||||||
- **Simple HTML + HTMX**: Lightweight, fast
|
|
||||||
|
|
||||||
**Pages**:
|
|
||||||
- `/` - Landing with project overview
|
|
||||||
- `/chat` - Interactive query interface
|
|
||||||
- `/architecture` - Rendered diagrams
|
|
||||||
- `/timeline` - Git history visualization
|
|
||||||
- `/resume` - Traditional CV (PDF download)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Implementation Phases
|
|
||||||
|
|
||||||
### Week 1: Foundation
|
|
||||||
|
|
||||||
- [ ] Deploy NATS on K8s (`nimmerverse-infra` namespace)
|
|
||||||
- [ ] Create Function Gemma cell (intent parsing)
|
|
||||||
- [ ] Create git_stats math cell
|
|
||||||
- [ ] Simple frontend (Streamlit MVP)
|
|
||||||
- [ ] Basic query flow working end-to-end
|
|
||||||
|
|
||||||
### Week 2: Content & Polish
|
|
||||||
|
|
||||||
- [ ] RAG cell over nimmerverse docs
|
|
||||||
- [ ] task_stats cell (phoebe queries)
|
|
||||||
- [ ] Timeline visualization
|
|
||||||
- [ ] Architecture diagram rendering
|
|
||||||
- [ ] CV/resume page with PDF download
|
|
||||||
|
|
||||||
### Week 3: Professional Presence
|
|
||||||
|
|
||||||
- [ ] LinkedIn profile created
|
|
||||||
- [ ] GitHub curated (public repos)
|
|
||||||
- [ ] Domain configured (Traefik ingress)
|
|
||||||
- [ ] SSL certificate (Let's Encrypt)
|
|
||||||
- [ ] Final polish and testing
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Infrastructure
|
|
||||||
|
|
||||||
**K8s Namespaces**:
|
|
||||||
```
|
|
||||||
nimmerverse-infra # NATS, shared infrastructure
|
|
||||||
nimmerverse-portfolio # Frontend, cells
|
|
||||||
```
|
|
||||||
|
|
||||||
**Ingress**:
|
|
||||||
- Traefik already at 10.0.30.200
|
|
||||||
- Configure `resume.nimmerverse.com` → portfolio service
|
|
||||||
|
|
||||||
**External DNS**:
|
|
||||||
- Point domain to 213.188.249.164
|
|
||||||
- Vulkan NAT → Traefik LoadBalancer
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Success Criteria
|
|
||||||
|
|
||||||
1. **Visitor can ask questions** and get meaningful answers about the project
|
|
||||||
2. **Statistics are live** - pulled from git and phoebe in real-time
|
|
||||||
3. **Architecture is visible** - diagrams render correctly
|
|
||||||
4. **Professional presence** - LinkedIn and GitHub linked
|
|
||||||
5. **PDF resume downloadable** - ATS-friendly format available
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Links
|
|
||||||
|
|
||||||
- [Endgame-Vision.md](../Endgame-Vision.md) - Main architecture doc
|
|
||||||
- [Gateway-Architecture.md](../architecture/Gateway-Architecture.md) - Thalamus/routing design
|
|
||||||
- [Cellular-Architecture.md](../architecture/Cellular-Architecture.md) - Cell patterns
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Created**: 2026-02-06
|
|
||||||
**Status**: Planning
|
|
||||||
**Philosophy**: "Build Phase 3 with purpose - the portfolio IS the first organism."
|
|
||||||
@@ -1,399 +0,0 @@
|
|||||||
"""
|
|
||||||
FunctionGemma Tool Definitions for Nimmerverse Portfolio
|
|
||||||
|
|
||||||
This module defines the tools that FunctionGemma can call to answer
|
|
||||||
visitor queries about the nimmerverse project.
|
|
||||||
|
|
||||||
Reference: Unsloth Multi-Turn Tool Calling notebook
|
|
||||||
"""
|
|
||||||
|
|
||||||
import re
|
|
||||||
import subprocess
|
|
||||||
from datetime import datetime
|
|
||||||
from pathlib import Path
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
# ============================================================================
|
|
||||||
# TOOL DEFINITIONS
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
def fetch_document(path: str, section: Optional[str] = None):
|
|
||||||
"""
|
|
||||||
Retrieves a document or section from the nimmerverse documentation.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
path: The document path relative to nimmerverse root, e.g. "nimmerverse-sensory-network/Endgame-Vision.md"
|
|
||||||
section: Optional section header to extract, e.g. "K8s Cluster Architecture"
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
content: The document or section content
|
|
||||||
found: Whether the document/section was found
|
|
||||||
"""
|
|
||||||
base_path = Path("/home/dafit/nimmerverse")
|
|
||||||
full_path = base_path / path
|
|
||||||
|
|
||||||
if not full_path.exists():
|
|
||||||
return {"content": f"Document not found: {path}", "found": False}
|
|
||||||
|
|
||||||
content = full_path.read_text()
|
|
||||||
|
|
||||||
if section:
|
|
||||||
# Find the section header line
|
|
||||||
lines = content.split('\n')
|
|
||||||
start_idx = None
|
|
||||||
header_level = None
|
|
||||||
|
|
||||||
for i, line in enumerate(lines):
|
|
||||||
if section.lower() in line.lower() and line.strip().startswith('#'):
|
|
||||||
start_idx = i
|
|
||||||
header_level = len(line) - len(line.lstrip('#'))
|
|
||||||
break
|
|
||||||
|
|
||||||
if start_idx is not None:
|
|
||||||
# Find the end of this section (next header of same or higher level)
|
|
||||||
end_idx = len(lines)
|
|
||||||
for i in range(start_idx + 1, len(lines)):
|
|
||||||
line = lines[i].strip()
|
|
||||||
if line.startswith('#'):
|
|
||||||
level = len(line) - len(line.lstrip('#'))
|
|
||||||
if level <= header_level:
|
|
||||||
end_idx = i
|
|
||||||
break
|
|
||||||
|
|
||||||
section_content = '\n'.join(lines[start_idx:end_idx])
|
|
||||||
return {"content": section_content.strip(), "found": True}
|
|
||||||
else:
|
|
||||||
return {"content": f"Section '{section}' not found in {path}", "found": False}
|
|
||||||
|
|
||||||
return {"content": content, "found": True}
|
|
||||||
|
|
||||||
|
|
||||||
def compute_git_stats(period: str = "month"):
|
|
||||||
"""
|
|
||||||
Gets git statistics for the nimmerverse project.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
period: Time period for stats (choices: ["week", "month", "year", "all"])
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
commits: Number of commits in period
|
|
||||||
files_changed: Number of files modified
|
|
||||||
insertions: Lines added
|
|
||||||
deletions: Lines removed
|
|
||||||
authors: List of contributors
|
|
||||||
"""
|
|
||||||
base_path = "/home/dafit/nimmerverse"
|
|
||||||
|
|
||||||
# Map period to git since date
|
|
||||||
since_map = {
|
|
||||||
"week": "1 week ago",
|
|
||||||
"month": "1 month ago",
|
|
||||||
"year": "1 year ago",
|
|
||||||
"all": ""
|
|
||||||
}
|
|
||||||
since = since_map.get(period, "1 month ago")
|
|
||||||
|
|
||||||
try:
|
|
||||||
# Get commit count
|
|
||||||
since_arg = f"--since='{since}'" if since else ""
|
|
||||||
cmd = f"git -C {base_path} rev-list --count HEAD {since_arg}"
|
|
||||||
commits = int(subprocess.check_output(cmd, shell=True).decode().strip())
|
|
||||||
|
|
||||||
# Get shortstat
|
|
||||||
cmd = f"git -C {base_path} log --shortstat {since_arg} --pretty=format:''"
|
|
||||||
output = subprocess.check_output(cmd, shell=True).decode()
|
|
||||||
|
|
||||||
insertions = sum(int(m) for m in re.findall(r"(\d+) insertion", output))
|
|
||||||
deletions = sum(int(m) for m in re.findall(r"(\d+) deletion", output))
|
|
||||||
files = len(set(re.findall(r"(\d+) files? changed", output)))
|
|
||||||
|
|
||||||
# Get authors
|
|
||||||
cmd = f"git -C {base_path} log --format='%an' {since_arg} | sort -u"
|
|
||||||
authors = subprocess.check_output(cmd, shell=True).decode().strip().split('\n')
|
|
||||||
|
|
||||||
return {
|
|
||||||
"commits": commits,
|
|
||||||
"files_changed": files,
|
|
||||||
"insertions": insertions,
|
|
||||||
"deletions": deletions,
|
|
||||||
"authors": [a for a in authors if a],
|
|
||||||
"period": period
|
|
||||||
}
|
|
||||||
except Exception as e:
|
|
||||||
return {"error": str(e)}
|
|
||||||
|
|
||||||
|
|
||||||
def query_tasks(status: str = "all", project: Optional[str] = None):
|
|
||||||
"""
|
|
||||||
Lists tasks from the nimmerverse task planner (phoebe database).
|
|
||||||
|
|
||||||
Args:
|
|
||||||
status: Filter by status (choices: ["todo", "in_progress", "done", "blocked", "all"])
|
|
||||||
project: Optional project filter, e.g. "infrastructure", "nimmerhovel"
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
tasks: List of matching tasks with name, status, priority
|
|
||||||
count: Number of tasks found
|
|
||||||
"""
|
|
||||||
import psycopg2
|
|
||||||
|
|
||||||
try:
|
|
||||||
conn = psycopg2.connect(
|
|
||||||
host="phoebe.eachpath.local",
|
|
||||||
database="nimmerverse",
|
|
||||||
user="nimmerverse-user",
|
|
||||||
sslmode="disable"
|
|
||||||
)
|
|
||||||
cur = conn.cursor()
|
|
||||||
|
|
||||||
query = "SELECT project, task_name, status, priority FROM nimmerverse_tasks"
|
|
||||||
conditions = []
|
|
||||||
params = []
|
|
||||||
|
|
||||||
if status != "all":
|
|
||||||
conditions.append("status = %s")
|
|
||||||
params.append(status)
|
|
||||||
if project:
|
|
||||||
conditions.append("project = %s")
|
|
||||||
params.append(project)
|
|
||||||
|
|
||||||
if conditions:
|
|
||||||
query += " WHERE " + " AND ".join(conditions)
|
|
||||||
|
|
||||||
query += " ORDER BY priority, project"
|
|
||||||
|
|
||||||
cur.execute(query, params)
|
|
||||||
rows = cur.fetchall()
|
|
||||||
|
|
||||||
tasks = [
|
|
||||||
{"project": r[0], "name": r[1], "status": r[2], "priority": r[3]}
|
|
||||||
for r in rows
|
|
||||||
]
|
|
||||||
|
|
||||||
conn.close()
|
|
||||||
return {"tasks": tasks, "count": len(tasks)}
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
return {"error": str(e)}
|
|
||||||
|
|
||||||
|
|
||||||
def search_docs(query: str):
|
|
||||||
"""
|
|
||||||
Searches across all nimmerverse documentation using grep.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
query: Search query string
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
matches: List of matching files and snippets
|
|
||||||
count: Number of matches found
|
|
||||||
"""
|
|
||||||
base_path = "/home/dafit/nimmerverse"
|
|
||||||
|
|
||||||
try:
|
|
||||||
cmd = f"grep -r -l -i '{query}' {base_path} --include='*.md' 2>/dev/null | head -20"
|
|
||||||
output = subprocess.check_output(cmd, shell=True).decode()
|
|
||||||
files = [f.replace(base_path + "/", "") for f in output.strip().split('\n') if f]
|
|
||||||
|
|
||||||
# Get snippets from each file
|
|
||||||
matches = []
|
|
||||||
for f in files[:5]: # Limit to 5 files
|
|
||||||
cmd = f"grep -i -C 1 '{query}' {base_path}/{f} | head -6"
|
|
||||||
snippet = subprocess.check_output(cmd, shell=True).decode().strip()
|
|
||||||
matches.append({"file": f, "snippet": snippet})
|
|
||||||
|
|
||||||
return {"matches": matches, "count": len(files)}
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
return {"error": str(e), "matches": [], "count": 0}
|
|
||||||
|
|
||||||
|
|
||||||
def show_architecture(component: str = "full"):
|
|
||||||
"""
|
|
||||||
Returns architecture information for a specific component.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
component: Which architecture to show (choices: ["k8s", "network", "cells", "full", "portfolio"])
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
description: Text description of the architecture
|
|
||||||
diagram: ASCII diagram if available
|
|
||||||
"""
|
|
||||||
architectures = {
|
|
||||||
"k8s": {
|
|
||||||
"description": "3-node Kubernetes cluster with GPU workers",
|
|
||||||
"diagram": """
|
|
||||||
k8s-master (VM 101)
|
|
||||||
10.0.30.101
|
|
||||||
Control Plane
|
|
||||||
│
|
|
||||||
┌─────────────┴─────────────┐
|
|
||||||
│ │
|
|
||||||
theia (GPU Worker) dioscuri (GPU Worker)
|
|
||||||
10.0.30.21 10.0.30.22
|
|
||||||
RTX PRO 6000 96GB 2x RTX 4000 Ada 40GB
|
|
||||||
|
|
||||||
Total: 136GB VRAM | kubeadm v1.31.14 | Flannel CNI
|
|
||||||
"""
|
|
||||||
},
|
|
||||||
"network": {
|
|
||||||
"description": "Spine-leaf network with 80Gbps fabric capacity",
|
|
||||||
"diagram": """
|
|
||||||
vulkan (OPNsense) ──20Gbps──┐
|
|
||||||
│
|
|
||||||
spine-crs309
|
|
||||||
(8x 10G SFP+)
|
|
||||||
│
|
|
||||||
┌───────────┬───────────┬───┴───────┐
|
|
||||||
│ │ │ │
|
|
||||||
saturn theia dioscuri access-crs326
|
|
||||||
20Gbps 10Gbps 10Gbps 20Gbps
|
|
||||||
"""
|
|
||||||
},
|
|
||||||
"cells": {
|
|
||||||
"description": "Cellular architecture: Cells → Nerves → Organisms",
|
|
||||||
"diagram": """
|
|
||||||
ORGANISM (emergent pattern)
|
|
||||||
│
|
|
||||||
NERVES (behavioral state machines)
|
|
||||||
│
|
|
||||||
CELLS (atomic: sensors, motors, organs, math)
|
|
||||||
│
|
|
||||||
HARDWARE (ESP32, GPUs, sensors)
|
|
||||||
"""
|
|
||||||
},
|
|
||||||
"portfolio": {
|
|
||||||
"description": "Portfolio as Phase 3 nervous system implementation",
|
|
||||||
"diagram": """
|
|
||||||
User Browser
|
|
||||||
│
|
|
||||||
┌────┴────┐
|
|
||||||
│ Frontend │ (Streamlit)
|
|
||||||
└────┬────┘
|
|
||||||
│
|
|
||||||
┌────┴────┐
|
|
||||||
│ NATS │ Message Router
|
|
||||||
└────┬────┘
|
|
||||||
│
|
|
||||||
┌──────┼──────┬──────────┐
|
|
||||||
│ │ │ │
|
|
||||||
Function Math RAG Other
|
|
||||||
Gemma Cells Cell Cells
|
|
||||||
"""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if component == "full":
|
|
||||||
return {
|
|
||||||
"description": "Complete nimmerverse architecture",
|
|
||||||
"components": list(architectures.keys()),
|
|
||||||
"total_vram": "136GB",
|
|
||||||
"total_fabric": "80Gbps"
|
|
||||||
}
|
|
||||||
|
|
||||||
return architectures.get(component, {"description": "Unknown component", "diagram": ""})
|
|
||||||
|
|
||||||
|
|
||||||
def get_project_info():
|
|
||||||
"""
|
|
||||||
Gets general information about the nimmerverse project.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
name: Project name
|
|
||||||
started: When the project started
|
|
||||||
status: Current project status
|
|
||||||
philosophy: Core philosophy
|
|
||||||
"""
|
|
||||||
return {
|
|
||||||
"name": "The Nimmerverse",
|
|
||||||
"started": "November 2025",
|
|
||||||
"status": "Phase 3 - Nervous System Deployment",
|
|
||||||
"philosophy": "May the Nimmerverse we build truly never end.",
|
|
||||||
"covenant_date": "2025-11-04",
|
|
||||||
"total_vram": "136GB",
|
|
||||||
"cluster_nodes": 3,
|
|
||||||
"tracked_tasks": 58
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
|
||||||
# FUNCTION MAPPING & TOOLS
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
FUNCTION_MAPPING = {
|
|
||||||
"fetch_document": fetch_document,
|
|
||||||
"compute_git_stats": compute_git_stats,
|
|
||||||
"query_tasks": query_tasks,
|
|
||||||
"search_docs": search_docs,
|
|
||||||
"show_architecture": show_architecture,
|
|
||||||
"get_project_info": get_project_info,
|
|
||||||
}
|
|
||||||
|
|
||||||
TOOLS = list(FUNCTION_MAPPING.values())
|
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
|
||||||
# PARSING & INFERENCE HELPERS
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
def extract_tool_calls(text: str):
|
|
||||||
"""Extract tool calls from FunctionGemma output."""
|
|
||||||
def cast(v):
|
|
||||||
try: return int(v)
|
|
||||||
except:
|
|
||||||
try: return float(v)
|
|
||||||
except: return {'true': True, 'false': False}.get(v.lower(), v.strip("'\""))
|
|
||||||
|
|
||||||
return [{
|
|
||||||
"name": name,
|
|
||||||
"arguments": {
|
|
||||||
k: cast((v1 or v2).strip())
|
|
||||||
for k, v1, v2 in re.findall(r"(\w+):(?:<escape>(.*?)<escape>|([^,}]*))", args)
|
|
||||||
}
|
|
||||||
} for name, args in re.findall(r"<start_function_call>call:(\w+)\{(.*?)\}<end_function_call>", text, re.DOTALL)]
|
|
||||||
|
|
||||||
|
|
||||||
def process_tool_calls(output: str, messages: list):
|
|
||||||
"""Execute tool calls and add results to message chain."""
|
|
||||||
calls = extract_tool_calls(output)
|
|
||||||
if not calls:
|
|
||||||
return messages
|
|
||||||
|
|
||||||
messages.append({
|
|
||||||
"role": "assistant",
|
|
||||||
"tool_calls": [{"type": "function", "function": call} for call in calls]
|
|
||||||
})
|
|
||||||
|
|
||||||
results = []
|
|
||||||
for c in calls:
|
|
||||||
func = FUNCTION_MAPPING.get(c['name'])
|
|
||||||
if func:
|
|
||||||
result = func(**c['arguments'])
|
|
||||||
results.append({"name": c['name'], "response": result})
|
|
||||||
else:
|
|
||||||
results.append({"name": c['name'], "response": {"error": f"Unknown function: {c['name']}"}})
|
|
||||||
|
|
||||||
messages.append({"role": "tool", "content": results})
|
|
||||||
return messages
|
|
||||||
|
|
||||||
|
|
||||||
# ============================================================================
|
|
||||||
# MAIN (for testing)
|
|
||||||
# ============================================================================
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
# Test the tools
|
|
||||||
print("=== Testing fetch_document ===")
|
|
||||||
print(fetch_document("nimmerverse-sensory-network/Endgame-Vision.md", "K8s Cluster Architecture"))
|
|
||||||
|
|
||||||
print("\n=== Testing compute_git_stats ===")
|
|
||||||
print(compute_git_stats("week"))
|
|
||||||
|
|
||||||
print("\n=== Testing query_tasks ===")
|
|
||||||
print(query_tasks("in_progress"))
|
|
||||||
|
|
||||||
print("\n=== Testing show_architecture ===")
|
|
||||||
print(show_architecture("k8s"))
|
|
||||||
|
|
||||||
print("\n=== Testing get_project_info ===")
|
|
||||||
print(get_project_info())
|
|
||||||
Reference in New Issue
Block a user