Skip to content

UI - #1

Open
rizalespe wants to merge 72 commits into
mainfrom
ui
Open

UI#1
rizalespe wants to merge 72 commits into
mainfrom
ui

Conversation

@rizalespe

Copy link
Copy Markdown
Contributor

No description provided.

indi9o and others added 30 commits May 13, 2026 23:32
- server.py: FastAPI app exposing agent.py via SSE streaming endpoints
  (/chat, /approve, /metrics, /session/new) with async wrapper for
  sync generators using run_in_executor + call_soon_threadsafe
- frontend/index.html: replace cyber/neon mock UI with NOC console
  design (IBM Plex Mono, dark surfaces, React via CDN); real SSE
  connection to backend replaces all mock setTimeout logic
- frontend/fonts/: IBM Plex Mono/Sans/Condensed woff2 files (local,
  no external CDN)
- frontend/assets/: logo.svg, glyph.svg
- requirements.txt: add fastapi>=0.115, uvicorn[standard]>=0.32

Run: python server.py → open http://localhost:8000

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
agents/nodes.py:
- Add _is_greeting() fast-path in supervisor_node: simple greetings
  (halo, hi, siapa kamu, ≤60 chars) bypass routing LLM and answer
  directly → END, preventing bad routing to monitor_agent
- supervisor.md: add explicit greeting routing rule section

server.py:
- _stream_events: add 3s heartbeat (SSE comment ": ping") so browser
  connection stays alive during long agent execution
- Add CORSMiddleware for cross-origin access
- Add GET /info endpoint returning model name from .env

frontend/index.html:
- bambang starts BERJALAN when user sends (matches tui.py _kanban_reset)
- bambang ALWAYS → SELESAI on routing event (was missing, matches tui.py)
- Elapsed timer: shows live "X s" counter in header + status bar while streaming
- Add elapsed summary event "⏱ selesai dalam X.Xs" at stream end (matches tui.py)
- AbortController cancel: ■ Stop button aborts fetch and resets agent states
- Composer disabled during approval modal (prevents double-send)
- All BERJALAN agents → GAGAL on error event
- ChatEvent: add elapsed type renderer
- consumeStream: approval_required returns early (keeps streaming=true)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
tools/netbox.py: 7 tools baru — get_netbox_devices, get_netbox_device_interfaces,
get_netbox_device_ips, get_netbox_drift_report, add_netbox_ip_address,
update_netbox_interface, populate_netbox_from_router.

Drift detection matching by VLAN ID (bukan nama — nama bisa beda antara
NetBox dan router). Device matching by IP di semua interface sebagai fallback
dari primary_ip yang belum diisi.

netbox_agent (alias: budi) handoff ke config_agent untuk eksekusi perubahan
ke router setelah drift detected. Approval required untuk write ke NetBox.

skills: netbox-read (audit inventaris) + netbox-sync (reconcile + handoff).
supervisor: tambah routing rule untuk permintaan NetBox.
agents/nodes.py: fix _is_greeting pakai word boundary regex.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- netbox_agent.md: standar nama `vlan<ID>`, format description per tipe,
  validasi input operator sebelum buat VLAN baru
- netbox-sync.md: standar penamaan + tabel format description + validasi
  input + koreksi template MikroTik command (name=vlan<id> bukan dari NetBox)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- skills/monitoring/morning-check.md: skill baru untuk pengecekan rutin
  pagi hari — reachability GATE-IDREN + BGP + traffic + log + drift NetBox,
  output format NOC briefing < 5 menit
- monitor_agent.md: tambah get_netbox_drift_report ke tools, morning-check
  ke skills list
- supervisor.md: tambah routing rule untuk trigger morning-check

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…c role-based

- Hapus hardcode GATE-IDREN-UB, ganti dengan list_routers + filter by role
- Tambah langkah resource check untuk router kampus (backbone/access)
- BGP + drift check: semua router gate_idren (dinamis)
- Format output pisahkan reachability kampus vs IDREN
- Log mendalam hanya untuk gate_idren, router kampus hanya jika ada anomali

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Operator bisa tentukan scope: IDREN / kampus / backbone / access / semua (default).
Bagian output yang tidak relevan dengan scope di-skip. Header output tampilkan scope aktif.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- bgp-diagnostics.md: tambah section Incident Response (R1-R6) — multi-router
  scope, klasifikasi session drop, impact assessment, eskalasi ke config_agent
- bgp-prefix-leak.md: skill baru untuk deteksi prefix leak / missing filter —
  audit session tanpa filter, prefix anomali, AS-path, remediation protocol
- diagnose_agent.md: tambah bgp-prefix-leak ke skills list

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
tools/netbox.py:
- get_netbox_vlan_groups: list semua group + range + sisa slot
- get_next_available_vlan: suggest next available VLAN ID dari group
- create_netbox_vlan_interface: buat interface di NetBox (approval required)
  nama otomatis vlan<ID>, validasi parent interface, cek duplikat

agents/tools.py: register 3 tool baru ke TOOL_MAP

netbox_agent.md:
- tambah 3 tool baru + create_netbox_vlan_interface ke approval_required_tools
- tambah vlan-provisioning ke skills list

supervisor.md: routing rule untuk provisioning VLAN baru → netbox_agent

skills/config/vlan-provisioning.md: skill baru — 8 langkah provisioning
NetBox-first (buat di NetBox dulu, lalu handoff ke config_agent untuk router),
validasi input, handling group penuh / group belum ada

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
get_netbox_vlan_groups: breakdown active vs reserved vs kosong (belum ada di NetBox).
  Sebelumnya semua dihitung sebagai 'terpakai' sehingga group terlihat penuh padahal banyak reserved.

get_next_available_vlan: prioritas slot kosong (belum ada di NetBox), jika tidak ada
  laporan reserved sebagai alternatif (ubah manual di NetBox UI).

get_netbox_vlan_group_detail: tool baru — list semua VLAN per group dengan status icon
  (✓ active, ○ reserved) + instruksi untuk update manual di NetBox UI.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… breakdown

- Langkah 1: jelaskan output baru get_netbox_vlan_groups (active/reserved/kosong)
- Langkah 1: jelaskan prioritas get_next_available_vlan (kosong dulu, reserved sebagai alternatif)
- Langkah 1: tambah get_netbox_vlan_group_detail untuk inspect reserved
- Kasus Khusus: pisahkan skenario "ada reserved" vs "benar-benar penuh"
- tools: tambah get_netbox_vlan_group_detail ke daftar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
tools/base.py: load field 'network' dari config per router entry

tools/utility.py: list_routers() tampilkan kolom network

tools/netbox.py:
- _get_netbox_cfg(instance): support format lama + named map baru
- _nb(instance): client per instance
- _resolve_instance(router_name, instance): 'auto' → baca network field
  router; tanpa context → default 'kampus'
- Semua @tool: tambah instance param — get_netbox_* default 'kampus',
  vlan tools default 'idren', drift/populate auto dari network router
- Fix sort dan format NoneType untuk kampus NetBox (2434 devices)

config.yaml (gitignored): ubah ke named map {idren, kampus},
  tambah network: field ke semua router — update manual di server.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ill handoff templates

- tools/config_yaml.py (new): full CRUD for config.yaml — patch_router_host (no approval),
  patch_router_field / add_router_to_config / remove_router_from_config (approval required)
- tools/netbox.py: resolve_router_host tool — auto-discover IP via NetBox primary_ip →
  NetBox interface IPs → BGP peer SSH fallback; adds _nb_url() clickable URL helper to all
  write tool outputs; fixes UnboundLocalError (creds inside loop) in populate_netbox_bgp
  and get_netbox_bgp_drift; adds duplicate IP guard in add_netbox_ip_address
- tools/base.py: empty host guard in ssh_run_command + ssh_get_dhcp_leases; add
  update_router_host() in-memory updater; add get_router_names()
- tools/*.py (7 files): add ssh_creds_for to imports (fixes NameError at runtime)
- agents/nodes.py: inject {router_list} into supervisor prompt + router-discovery
  programmatic override when 'tidak dikenal' detected in recent messages
- agents/tools.py: register resolve_router_host + config_yaml tools
- agents/definitions: config_agent + netbox_agent get router-discovery skill and new tools;
  supervisor.md gets few-shot JSON examples for unknown router routing
- skills/config/router-discovery.md (new): 4-phase autonomous orchestration — NetBox
  IP candidates → validation loop (ping→SSH→ROS confirm, max 3 IPs) → BGP peer fallback
  → report to operator only after validation passes
- skills/** (28 files): add ## Validasi Mandiri + ## Handoff standard sections to all
  skills for agent autonomy and inter-agent collaboration

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…covery

Add optional host param to both tools — when provided, bypass validate_router
and ping/probe the IP directly. Enables router-discovery skill to validate
unregistered router IPs from NetBox or BGP peer without hitting 'tidak dikenal' error.

Also fix router-discovery skill Step 2c: replace run_command (needs registered router)
with check_ssh_access banner inspection — MikroTik always sends SSH-2.0-ROSSSH banner.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
BGP fallback sebelumnya contohkan GATE-IDREN-UB secara eksplisit — LLM ikuti
literal dan berhenti setelah 1 router. Sekarang instruksi eksplisit: kumpulkan
semua router role=gate_idren dari list_routers(), loop satu per satu, jangan
berhenti di router pertama.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…poran

Fase 3: tambah 2-tahap BGP matching — (1) nama session, (2) reasoning dari
semua session via remote-as/comment/subnet jika nama tidak cocok keyword.
Agent tidak lagi terpaku pada nama session — bisa reasoning dari konteks.

Fase 4: laporan wajib cantumkan APA ditemukan, DI MANA (router/sumber),
dan BAGAIMANA (metode: primary_ip / interface IP ke-N / BGP session X di router Y).
Format gagal juga tampilkan jejak pencarian per fase agar operator bisa debug.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add original_intent: str to NetworkOpsState. Supervisor saves the first
HumanMessage as original_intent and persists it across agent hops.

_intent_continuation() (deterministic, no LLM): after config_agent or
netbox_agent finishes, checks if original_intent contains monitoring or
diagnose keywords — if yes, routes to monitor_agent/diagnose_agent instead
of END. Enables: "cek router idren ITB" → config_agent (discovery) →
monitor_agent (actual check) without operator re-prompting.

Early-exit fast path now checks intent continuation first (priority 1),
before file-save routing (priority 2), before END.

Supervisor prompt gets {intent_context} injection on subsequent calls so
LLM also knows original intent when making routing decisions.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… cleanup

Temuan 1: reset_agent() sekarang clear original_intent ("") agar intent lama
tidak merembes ke percakapan baru dalam sesi yang sama.

Temuan 2: thread_id TUI tidak lagi pakai str(id(self)) yang berubah tiap restart.
- Init: "tui-main" (stabil lintas restart, state di-resume dari SQLite)
- Reset (Ctrl+R): "tui-reset-{timestamp}" (fresh thread, terbaca di DB)

Tambah cleanup_orphaned_checkpoints() di agent.py untuk hapus thread
dengan ID numerik warisan id(self). Dijalankan sekali: 39 thread orphan
dihapus, DB turun dari 39MB ke 22.9MB.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Temuan 4 — WAL: PRAGMA wal_checkpoint(TRUNCATE) dijalankan saat startup
agent.py agar WAL tidak tumbuh lintas restart.

Temuan 3+6 — memory.db: implementasi tools/agent_memory.py dengan 4 tools:
  - remember_router_fact: simpan fakta router (discovered_ip, ros_version, dll)
  - recall_router_facts: ambil semua fakta satu router
  - recall_all_router_facts: lihat semua fakta lintas router
  - forget_router_facts: hapus fakta spesifik atau semua fakta router

config_agent + monitor_agent mendapat akses memory tools.
router-discovery skill: simpan IP valid + ros_version ke memory setelah approval.
morning-check skill: recall_all_router_facts() di Langkah 0 sebelum cek router.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rvisor

Tool populate_netbox_bgp + get_netbox_bgp_drift ditambah ke config_agent tools
agar tidak error 'tool tidak ditemukan' ketika supervisor route ke config_agent.

Supervisor.md: tambah contoh eksplisit 'populate bgp ke netbox' → netbox_agent
agar LLM memilih agent yang tepat di routing berikutnya.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
config_agent: num_predict 16384 → 4096
  2 runaway calls (400s, 393s) semua karena thinking chain tidak berhenti.
  p99 successful = 852 tok → 4096 masih 4.8× safety margin. Hemat ~285s/call.

supervisor: num_ctx 32768 → 16384
  Supervisor hanya filter HumanMessage+AIMessage (bukan ToolMessage).
  Max observed input = 12451 tok → 16384 memberi 32% headroom.
  KV cache turun dari ~3.5GB ke ~1.75GB per call, kurangi pressure di Ollama.

monitor_agent: num_predict 16384 → 8192
  8 historical cut-off calls di 4096 tok. Max successful stop = 4074 tok.
  8192 = 2× max observed, cukup headroom untuk laporan panjang.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Bug fixes:
- tools/traffic.py: _fetch() NameError (entry not in scope) — semua traffic tools return kosong
- tools/traffic.py: _parse_iface_stats regex salah — angka RX astronomikal (semua kolom tergabung)
- tools/traffic.py: tambah roles filter ke get_top_interfaces_all (scope IDREN vs kampus)
- tools/netbox.py: drift auto-match gagal untuk 4 router IDREN — tambah name-based lookup sebelum IP lookup
- skills/library.py + agent.py: segfault saat exit — stop_watcher() join thread + atexit.register

Agent tuning (monitor_agent):
- max_iters configurable via frontmatter (default 20, monitor_agent=35) — morning check butuh 27+ tool calls
- context_window 20→5 — history TUI session sebelumnya inflasi start_ctx 14%→25%, agent berhenti prematur di BGP
- AgentDefinition.max_iters field + loader.py parsing + nodes.py pass ke _react_loop

Skill improvements (morning-check):
- Tabel checklist 7 langkah wajib + larangan keras tulis N/A sebelum dikerjakan
- Larangan BGP double-call setelah Langkah 3
- Log lines 100→50 untuk kurangi token pressure
- Traffic roles filter: gate_idren/backbone,access/semua sesuai scope

Result: morning check IDREN 27/27 tool calls selesai (vs 14/25 sebelumnya), 103s, segfault hilang

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
tui_textual.py (Phase 8):
- Composer.Submit bubbles naturally — removed _fwd_submit infinite loop bug
- @work(thread=True) streaming worker with cancel/stop support
- Dynamic model display per active agent from AgentLoader
- Responsive layout: AgentRail w=24, AgentCard h=4, height:1fr on #chat-log
- Clear button resets RichLog + AgentRail + creates new graph thread
- TopBar simplified (removed CTX/TOK labels, uses role abbreviation map)

agents/graph.py:
- Added netbox_agent node (netbox_node already in nodes.py)

skills/interface/link-diagnostics.md:
- Added mandatory BGP/OSPF session check (Langkah 3b) for uplink interfaces
- Frequency calculation must use actual timestamps — no estimation
- LARANGAN KERAS: no hallucinated peer names, no prose handoff
- Handoff uses HANDOFF: <agent> signal format

test_load.py: latency + event count load test utility

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ctrl+y  — copy last AI response to clipboard + notify() toast
ctrl+b  — copy full chat log (plain text) to clipboard + notify() toast
ctrl+e  — open LogViewModal: TextArea read-only full log, mouse-selectable

Implementation:
- ChatPanel._plain_lines: list[str] — parallel plain-text buffer alongside RichLog
- ChatPanel._last_ai: str — updated on each "ai" event
- LogViewModal: ModalScreen with TextArea(read_only=True), Esc to close
- Buffers cleared on btn-clear
- StatusBar hint updated with new shortcuts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…y binding)

ctrl+c di app-level pakai priority=True sehingga TextArea tidak bisa handle
native copy. Fix: tambah ctrl+y di LogViewModal untuk copy selected_text eksplisit.

Empty selection → notify warning. Non-empty → copy_to_clipboard + notify.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ctrl+y / ctrl+b: ganti OSC-52 copy_to_clipboard() dengan xsel subprocess
(OSC-52 tidak reliable di Wayland). Fallback chain: xsel → wl-copy → xclip → OSC-52.

ctrl+e: ganti TextArea modal dengan App.suspend() + less. User bisa select
dan copy teks langsung pakai shortcut terminal native (Shift+drag, Ctrl+Shift+C).
LogViewModal dihapus — tidak diperlukan lagi.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Ganti plain Text line-by-line dengan rich.markdown.Markdown renderable.
AI response sekarang render: header (##), bold, tabel, code block, list.
Plain text buffer (_plain_lines, _last_ai) tetap untuk ctrl+y/b copy.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ctrl+b

subprocess.run() di action handler blokir Textual event loop → UI freeze.
Fix: action_copy_last_ai dan action_copy_full_log jadi async,
_sys_copy dipanggil via asyncio.to_thread().

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ua agent

agents/nodes.py (_SPECIALIST_SYS):
- FORMAT OUTPUT WAJIB berlaku ke semua 6 specialist agent
- ✅ OK/Up/Sinkron · ⚠️ Perhatian · 🚨 Kritis/Down
- Data tabular WAJIB tabel Markdown, satu baris per router/item
- Action Items: 🚨 SEGERA · ⚠️ PERLU · 💡 OPSIONAL
- DILARANG menumpuk data horizontal

skills: update "Output yang Diharapkan" di 5 skill
- morning-check.md: tabel BGP, NetBox, Reachability, Traffic, Log + Action Items
- network-health-check.md: tabel per kategori dengan emoji status
- bgp-diagnostics.md: tabel session summary + detail down
- dhcp-pool-audit.md: tabel pool + utilisasi
- link-diagnostics.md: tabel counter + root cause + action items

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
indi9o and others added 21 commits May 18, 2026 22:10
This commit introduces a new skill for diagnosing MTU mismatch issues in network interfaces. The skill includes a comprehensive procedure for identifying and resolving MTU-related problems, including steps for checking interface statistics, traffic summaries, router logs, and firewall configurations. It also provides recommendations for adjusting MTU settings and handling fragmentation. The documentation is structured with clear sections and expected output tables for effective troubleshooting.
…ation and discovery

- Updated netbox_agent to include new tools for router synchronization and BGP population.
- Added skills for netbox-bgp-sync and router-to-netbox-sync to manage BGP sessions and router data.
- Introduced new scenarios for testing BGP drift detection, netbox drift, and router-to-netbox population.
- Enhanced mock data for NetBox devices, interfaces, and IPs to support new features.
- Improved documentation for agent responsibilities and tool usage in synchronization processes.
- AgentLoader: add `enabled` field; all() filters disabled agents by default
- validate() uses include_disabled=True so disabled agents are still checked
- tui.py: add yanto/wati to AGENT_INFO and _ROLE_TO_ALIAS
- tui.py: NONAKTIF kanban column (C_DIM) for agents with enabled=false
- tui.py: _initial_agents() sets disabled aliases to nonaktif at startup
- tui.py: _kanban_reset() preserves nonaktif state between queries
- tui_textual.py: add yanto/wati to AGENTS_DEF, ALIAS_MAP, _ROLE_ABBR

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- New Agents screen (master-detail: table + edit panel) for editing
  specialist agent config (model, params, tools, skills, system prompt)
  from the browser, backed by new GET/PUT /api/agents/{name}.
- Skills editor moved from a modal to the same master-detail pattern,
  plus a chip/tag input with autocomplete for Tools/Skills/Triggers
  (new GET /api/tool-names) instead of raw comma-separated text.
- Edits to agent/skill definitions stash the pristine repo default on
  first change (data/defaults/) so they can be restored later via new
  POST .../restore endpoints; fixed YAML dumper losing list indentation
  on every save.
- Removed the now-redundant read-only Agents tab from Settings in favor
  of the dedicated Agents screen (deep-linkable via #agents/{name}).
- Sidebar nav grouped into Infrastructure / Agent Platform / Insights
  sections with collapsible, accordion-style headers.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Both screens are unused right now; the underlying tools/agents stay
intact so they can be re-exposed later without backend changes.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Editing an agent via the UI used to overwrite the tracked file in
agents/definitions/, so every edit showed up as repo diff noise. Those
.md files now seed a new agent_definitions table in data/netops.db on
first run only; AgentLoader reads from the DB from then on, and
PUT/restore endpoints write there instead of touching the filesystem.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- routers table gains node_type (router/switch/server, default
  router), threaded through db.py CRUD, base.py in-memory registry,
  config_yaml.py agent tools, server.py request models, and the
  Nodes screen (type column + form dropdown).
- agent.py: list_llm_models() queries an OpenAI-compatible /models
  endpoint so Settings can populate a model dropdown without the
  operator typing an exact model id.
- Settings/agents screens wired up to the model listing endpoint.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
NetOpsUI no longer contains the LangGraph agent, the SSH tools or the TUI.
Agents now run in two external backends, one active at a time, chosen in
Settings: NetOps Agent (palapa-agent REST API) and Hermes (gateway
api_server). What those backends have no API for is handled by a small
manager service that ships with this repo.

Removed: agent.py, agents/, tools/, skills/, server.py, tui*.py, tests/,
legacy/, requirements.txt and the screens that only existed for the old
backend (nodes, reports, backups, metrics, agent roster).

Frontend
- backends/: one adapter per backend behind a shared contract. Events are
  normalised (delta, tool_start/end, approval, ...). Hermes uses
  /v1/runs + /events because only runs support approval and stop.
- Chat: tool-activity panel replaces the agent roster; generic approval
  dialog with the choices Hermes offers; per-backend threads.
- Skills, Agents (prompt profiles) and Settings > File Konfigurasi are
  backed by the manager. Nodes, Reports, Backups, Metrics show
  "Belum tersedia" until a backend exposes an API for them.
- Backend is displayed as "NetOps Agent"; legacy localStorage keys and
  the old 'palapa' backend id are migrated.

Manager (server/, FastAPI + SQLite)
- Skill library with publish/unpublish to each backend's skills folder,
  drift status, and refusal to overwrite files it did not publish.
- Agent profiles; apply to NetOps Agent's SOUL.md (previous one backed up).
- Read-only config views: config.yaml with secrets masked, .env as
  variable names only. Slug validation and path-traversal checks.

Deployment
- docker-compose.yml (frontend nginx + manager, host network) and a dev
  override for hot reload; env-driven nginx proxy that injects the Hermes
  API key and strips Origin. Manager mounts only skills/ and NetOps
  Agent's SOUL.md as writable; DATA_DIR is configurable.
- README rewritten with run/deploy, operations and troubleshooting.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@rizalespe

Copy link
Copy Markdown
Contributor Author

@copilot resolve the merge conflicts in this pull request

Copilot AI commented Sep 24, 2026

Copy link
Copy Markdown

@rizalespe I can’t apply these changes because the pull request’s branch is the repository’s default branch, which I’m not allowed to push to directly.

You can ask me to create a new pull request with the requested changes instead and I'll open a separate PR on a new branch.

Rizal SP and others added 2 commits September 24, 2026 08:40
- Store OpenAI-compatible LLM provider profiles in the manager (API key
  write-only, never returned to the browser)
- Add "Terapkan" flow that writes a provider into a backend's config.yaml
  model block with a timestamped backup; backend restart still required
- Add Settings tabs (Backend, LLM Provider, File Konfigurasi) and nodes screen
- Remove laporan/commissioning-spec-lab.md

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…implified README

- Auth: users/sessions in the manager, login screen (network pattern, footer
  with website/contact), nginx auth_request guard, create_user.py CLI
- Dashboard: Hermes cron jobs panel (run/pause/resume), NetOps devices and
  agent activity panels, capability-gated per backend
- Hermes: new sessions use UUID ids like NetOps threads
- NetOps chat: manager-side runs so replies survive browser refresh
- Nodes screen: list/update/delete devices
- About page and shell footer
- README reduced to what it is and pre-use setup steps

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
rizalespe and others added 4 commits September 24, 2026 15:37
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…n progress

Tool cards show a readable summary of the call instead of raw JSON, with the full
arguments expandable. Clicking another thread during a run detaches from its stream
(the run keeps going on the server) instead of being silently ignored. The manager
forwards the tool call source.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants