AmtocBots Manager — Full Implementation (Phases 2–9)#4
Open
amtocbot-droid wants to merge 14 commits intousers/krk/20260315_initial_setupfrom
Open
AmtocBots Manager — Full Implementation (Phases 2–9)#4amtocbot-droid wants to merge 14 commits intousers/krk/20260315_initial_setupfrom
amtocbot-droid wants to merge 14 commits intousers/krk/20260315_initial_setupfrom
Conversation
Complete ASP.NET Core 10 Web API for AmtocBots Manager: Entities & Data: - AppDbContext with pgvector extension, AES-256 value converter for channel token encryption at rest, all EF Core entity configurations - Entities: BotInstance, ChannelConfig, ModelSwitchRule, TokenUsageRecord, KanbanBoard/Column/Card, ChatRoom/Member/Message, BotLearning, AppUser Services: - DockerService (Docker.DotNet): create/start/stop/remove OpenClaw containers, stats polling, config volume writing via busybox helper - OpenClawClient: typed HTTP client for /hooks/wake and /hooks/agent - OpenClawConfigBuilder: generates JSON5 config from DB state - TokenTracker: upserts daily token usage records per instance+model - ModelSwitchingService: evaluates threshold rules, switches model, rewrites config volume, restarts container - RedisMessageQueueService: LPUSH/BRPOP main queue + sorted-set delay queue - OllamaService: list models, pull, health, generate embeddings Controllers & Endpoints: - InstancesController: full CRUD + start/stop/restart/logs/config - ModelsController: available models, token usage, switch rules CRUD - KanbanController: boards/columns/cards + bot-webhook endpoint (API key auth) - ChatController: rooms, paginated messages, bot-message endpoint - WebhookController: receives token-usage and event callbacks from OpenClaw - ChannelEndpoints: GET/PUT channel configs, WhatsApp QR proxy - OllamaEndpoints: list/pull/status - HealthEndpoints: /api/health SignalR Hubs: InstanceHub, KanbanHub, ChatHub Background Services: - MetricsPollingService: Docker stats → InstanceHub every 5s - ModelSwitchScheduler: NCrontab + threshold evaluation every 1m - QueueRetryWorker: Redis queue retry with exponential backoff Program.cs: full DI registration, Keycloak JWT auth (role claims from realm_access.roles), CORS, SignalR, auto-migration on startup Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Angular 21 standalone PWA foundation: Config & Bootstrap: - app.config.ts: provideRouter (input binding + view transitions), provideHttpClient (authTokenInterceptor), provideAuth (OIDC → Keycloak with PKCE + silent renew), provideServiceWorker - app.routes.ts: lazy-loaded feature routes, authGuard on shell Core: - AuthService: signals-based isAuthenticated, userData, roles, isAdmin/isOperator computed signals; wraps angular-auth-oidc-client - authGuard / roleGuard: functional guards (adminGuard, operatorGuard) - authTokenInterceptor: attaches JWT Bearer to /api and /hubs requests - AuthCallbackComponent: handles OIDC redirect - SignalrService: hub connection factory with withAutomaticReconnect, typed on<T>() Observable, reconnecting signal for UI banner - ShellComponent: mat-sidenav shell + reconnect banner - SidebarComponent: nav items with routerLinkActive - TopbarComponent: menu toggle + user dropdown + logout Shared: - StatusBadgeComponent: color-coded status badge (running/stopped/starting/error) - ConfirmDialogComponent: reusable confirm dialog Features: - DashboardComponent: live instance list with stats via toSignal + HttpClient - Route stubs for instances, models, kanban, chat (implementation in phases 4-8) Infrastructure: - multi-stage Dockerfile: node:22 build → nginx:1.27 serve - nginx.conf: SPA routing, asset caching, gzip - ngsw-config.json: app-shell prefetch, API freshness strategy - proxy.conf.json: dev proxy /api and /hubs to :8080 - environments: dev (localhost) + production (amtocbot.com) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Phase 4 - Instance Management UI: - InstanceStore: signal-based state, SignalR StatusUpdate wired to live CPU/mem stats, start/stop/restart/delete actions with optimistic updates - InstanceListComponent: card grid with live metric bars (5s refresh via SignalR), start/stop/restart buttons, delete confirm dialog, role guards - InstanceDetailComponent: tabs for Config/Channels/Logs, live stats bar, computed liveStatus/liveStats from store signal, input() id binding - InstanceFormComponent: reactive form with model selector (loads from /api/models/available including Ollama), resource limits, one-time token display after creation - InstanceConfigEditorComponent: Monaco editor (vs-dark, JSON5) with dirty-state banner, reload and save actions - InstanceLogViewerComponent: 10s auto-refresh while running, tail selector (50/200/500), scroll-to-bottom, effect() on isRunning input signal Phase 5 - Channel Configuration UI: - ChannelBase directive: shared saveConfig(), parsedConfig(), saving signal - ChannelConfigComponent: tab container, loads channel configs on init - TelegramConfigComponent: bot token (masked) + allowFrom chip list - DiscordConfigComponent: bot token, guild ID, allowed channel IDs chip list - SlackConfigComponent: app token (xapp-) + bot token (xoxb-) + channel IDs - WhatsappConfigComponent: QR polling loop (3s interval), blob URL display, allowFrom phone numbers, paired/error/idle state machine Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Token usage dashboard with 7/30-day range, model breakdown bars (blue→amber→red), per-instance table - SwitchRulesComponent: threshold + cron auto-switch rules per instance, enable/disable toggle, priority - models.routes.ts: add :instanceId/rules sub-route - ModelsController: persist IsActive on rule update - ModelDtos: add IsActive to CreateSwitchRuleRequest Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- KanbanStore: signal-based board state, SignalR CardCreated/CardMoved/CardUpdated/CardDeleted listeners, JoinBoard/LeaveBoard hub calls, optimistic moveCard - BoardListComponent: board grid with create dialog - KanbanBoardComponent: CDK drag-drop across columns, priority color dots, due-date overdue highlight, bot-created badge, WIP limit warnings, add-card dialog Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ChatStore: signal-based state, SignalR MessageReceived/UserTyping listeners, cursor-paginated message history, JoinRoom/LeaveRoom hub calls, sendTyping with debounce - ChatShellComponent: dual-pane layout (room sidebar + message area), @mention highlight, reply-to preview, auto-scroll with load-older-messages on scroll-to-top, typing indicator, create-room dialog - AuthService: add userId() and username() computed signals from OIDC userData Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- LearningsController: GET /learnings (list with instanceId/tag filters), GET /learnings/search (vector similarity via Ollama embeddings, keyword fallback), POST /learnings (embed + store), DELETE /learnings/{id}
- OllamaDashboardComponent: health status dot, model list, pull-model form, semantic search, learnings CRUD with source/tag filters
- app.routes.ts: add /ollama lazy route
- sidebar: add Ollama nav item
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…etail Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…JAR from Maven Central via alpine stage - quay.io/keycloak/keycloak:26 tag doesn't exist; use 26.2 - p2-inc/keycloak-magic-link moved to Maven Central (io.phasetwo.keycloak), version 0.57 - KC image has no curl/wget; use alpine:3.20 as downloader stage - Remove non-existent 'magic-link' feature flag (extension registers itself) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Frontend (Angular):
- styles.scss: migrate to Angular Material M3 theme API (mat.define-theme)
- tsconfig.json: add baseUrl for path alias resolution
- package.json: bump TypeScript ~5.6→~5.9 (Angular 21 requirement); add package-lock.json
- Dockerfile: add --legacy-peer-deps to npm ci
- auth.service.ts: fix toSignal generic, remove invalid getAccessToken$(); use signal for getToken()
- signalr.service.ts: inject AuthService instead of OidcSecurityService for token factory
- instance.store.ts: replace catch(e:any) and bare catch{} with valid TS5.9 syntax
- channel configs: fix inject import from @angular/core (not @angular/forms)
- components: add missing pipe imports (DecimalPipe, CurrencyPipe, DatePipe, SlicePipe)
- CpuClampPipe: move class definition before @component so it can be listed in imports[]
- channel-config: replace Array.with() with slice-based immutable update
Backend (.NET):
- DockerService: cast decimal to double before * 1e9; remove ?? on non-nullable ulong
- LearningsController: use named ct: param for GenerateEmbeddingAsync
- RedisMessageQueueService: explicit (string) cast to resolve Deserialize overload ambiguity
- AmtocBots.Api.csproj: Hjson 3.1.* → 3.0.* (3.1 doesn't exist on NuGet)
- docker-compose.yml: include password in Redis connection string
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Switch cloudflared from cert.pem/config-file approach to token-based
auth (tunnel run --token ${CLOUDFLARE_TUNNEL_TOKEN}) — no volumes needed
- Fix webAuthnPolicySignatureAlgorithms and
webAuthnPolicyPasswordlessSignatureAlgorithms from Array to String in
realm-export.json — KC 26 deserializes these as java.lang.String
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Passing --token ${VAR} on the command line breaks when VAR is empty —
cloudflared sees '-token' with no value and exits with a parse error.
Using the TUNNEL_TOKEN environment variable avoids this.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Prefixing hostnames with http:// prevents Caddy from attempting ACME certificate issuance, which was failing because ACME challenges go through the Cloudflare proxy and can't reach Caddy directly. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Complete implementation of the AmtocBots Manager PWA — all phases built on top of the Phase 1 infrastructure foundation.
Phase 2 — .NET 10 Backend Core
DockerService(Docker.DotNet),InstancesControllerwith port allocation, BCrypt API tokensMetricsPollingService→ SignalR every 5s,ModelSwitchScheduler(NCrontab),QueueRetryWorker(Redis BRPOP)Phase 3 — Angular 21 PWA Shell
SignalrServicewith typedon<T>()and auto-reconnectShellComponent,authGuard,roleGuard,authTokenInterceptorPhase 4+5 — Instance Management UI + Channel Config
InstanceStore(signals + SignalR live stats), instance list/create/detail/logsOpenClawConfigBuilderwrites JSON5 to named Docker volume on config savePhase 6 — Model Intelligence & Token Management
SwitchRulesComponent: threshold + cron auto-switch rules per instancePhase 7 — Kanban Board
KanbanStorewith SignalR CardCreated/CardMoved/CardUpdated/CardDeleted listeners, optimistic movesPhase 8 — Chat System
ChatStore: cursor-paginated history, SignalR MessageReceived/UserTyping, JoinRoom/LeaveRoomPhase 9 — Ollama & Learnings
LearningsController: pgvector semantic search via Ollama embeddings + keyword fallback, CRUDTest plan
docker compose up→ all 8 services healthy, Caddy responds at manager.amtocbot.comdocker ps, live CPU% updates every 5sModelSwitchSchedulerevaluates it on next tickGET /api/ollama/modelsreturns local model list; semantic search returns relevant learnings🤖 Generated with Claude Code