Deploy/797th manifests#1269
Open
Nideesh1 wants to merge 38 commits into
Open
Conversation
New tool that calls Ollama's /api/chat with JSON schema enforcement. Agents can use this for precise computed values (timestamps, numbers, classifications) without relying on LLM math. Also fixes non_exhaustive struct construction in mcp.rs for newer Rust versions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Pipes the Telegram chat_id from the channel bridge through the kernel, agent loop, and tool runner to cron_create. When a cron job is created with delivery: last_channel, the tool automatically replaces it with the sender's actual chat_id. Prevents race conditions where multiple users messaging the bot would cause reminders to deliver to the wrong chat. Changes: - bridge.rs: Add send_message_with_sender trait method, pass platform_id - channel_bridge.rs: Implement send_message_with_sender on KernelBridgeAdapter - kernel.rs: Add send_message_with_sender, pass sender_id to agent loop - agent_loop.rs: Accept sender_id, pass to execute_tool - tool_runner.rs: Accept sender_id, replace last_channel in cron_create - routes.rs: Pass None for sender_id in MCP HTTP context Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- kernel.rs: When a cron job with Channel delivery fires, deliver the message text directly to Telegram without going through the LLM. Prevents rephrasing and "I need your channel ID" responses. - tool_runner.rs: Normalize system_event to agent_turn in cron_create so reminders always deliver via channels. Also catch delivery "none" alongside "last_channel" for sender_id replacement. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Recurring schedules (every, cron) keep one_shot false so they persist. One-time reminders auto-delete after firing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ecution - Add check_interval_secs field to HandAgentConfig in HAND.toml - Wire it into kernel hand-to-agent mapping (was hardcoded to 3600s) - Defaults to 3600s if not set, so existing hands are unaffected - Allows polling hands to set faster tick intervals (e.g. 30s) - Fix shell skill execution: run script file directly instead of -s flag Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a user switches agents via /agent <name>, the target agent now receives the delivery channel context (channel type + chat ID). This allows hands and autonomous agents to use channel_send without needing a hardcoded default_chat_id in config. Changes: - Add set_delivery_context to BridgeHandle trait (default no-op) - Implement in BridgeKernelImpl: writes delivery.last_channel to agent structured memory on /agent switch - Add get_delivery_context to KernelHandle trait - Implement in kernel: reads delivery.last_channel from structured memory - channel_send now falls back to delivery.last_channel when recipient is empty and no default_chat_id is configured - Pass channel_name to handle_command for context propagation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…scade Change search_auto() priority: SearXNG (self-hosted) first, then DuckDuckGo as zero-config fallback. Third-party providers (Tavily, Brave, Perplexity) only tried if SearXNG URL is not configured. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…mand After rebase, 6 router.resolve() calls in handle_command still referenced user_id (the old upstream param name) which no longer exists — the param was renamed to channel_name in the custom commit. Replace all 6 with sender.platform_id.as_str() which is the correct routing key.
Adds nideesh-agent manifest and entrypoint shim that copies /opt/openfang/agents/* into /data/agents/ on container start (cp -rn = no-clobber, so PVC writes win). Enables k8s pods to have agents present without manual kubectl cp into the volume. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Add .gstack/ plus daemon_out.log, daemon_err.log, build_log.txt, body.html, dash.html, and headers.txt to .gitignore. These are local runtime logs and curl/dashboard output dumps produced during local integration testing and should not be tracked. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Makes a fresh deployment come up ready to run with the Dewansh research agent connected to Telegram, instead of an empty default assistant. - kernel: seed agents from <home>/agents/*/agent.toml on first boot of a fresh data volume. The DB-restore path only *updates* agents already in the DB from disk; it never created new ones, so baked agents seeded onto a fresh PVC were never loaded. Gated on an empty DB so it behaves as a one-time seed: API deletes stay deleted (no resurrection from leftover on-disk TOML) and existing installs are never force-populated. - deploy/agents: curated baked set (Dewansh + assistant) using the nvidia default model. Kept separate from the repo example gallery under ./agents so the image ships only these two. - deploy/config.default.toml: default config seeded to the data volume on first boot (api_listen 0.0.0.0:4200, nvidia default model, Telegram channel routed to Dewansh). Secrets stay env-var references only. - Dockerfile: bake deploy/agents + deploy/config.default.toml; entrypoint seeds the config if the volume has none (never overwrites existing). - deploy/rancher/openfang.yaml: k8s template (Deployment + PVC + Service + Secret stub) documenting the required NVIDIA_API_KEY / TELEGRAM_BOT_TOKEN. Verified on a simulated fresh volume: exactly Dewansh + assistant load, and Dewansh performs web_search/web_fetch end-to-end. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ures) Addresses CodeRabbit review: the inline ENTRYPOINT used `2>/dev/null || true` around the agent/config seeding, so a failed seed (bad volume permissions, full disk) would be swallowed and the daemon would come up with no agents/config and no diagnostic. - deploy/entrypoint.sh: dedicated script that seeds baked agents + default config with explicit per-step logging and warnings on failure, then execs the daemon. set -eu; cp -n preserves existing volume files. - Dockerfile: COPY + chmod the script, ENTRYPOINT calls it. - .gitattributes: force LF on *.sh so the entrypoint runs under /bin/sh regardless of the checkout host. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- deploy/agents/Dewansh/agent.toml: remove redundant skills=[web-search] from [capabilities]; the same skill is already declared at the top-level skills field, so the duplicate triggered loader warnings. - agents/Dewansh/agent.toml: add the source-of-truth agent manifest (was previously untracked) and fix a split-word typo in the system prompt (If s\neach -> If search) that would have corrupted the rendered prompt.
The duplicate skills=[web-search] under [capabilities] is silently ignored by the loader (ManifestCapabilities has no skills field; the top-level skills on AgentManifest is what gets read). Keeping it as a no-op duplicate only invites confusion and future drift from the canonical pattern used by nideesh-agent.
…ifest - Dewansh agent.toml: move system_prompt under [model]. It's a ModelConfig field; at the manifest root serde silently drops it, so the agent was falling back to the default prompt instead of the research persona. - kernel: gate one-time agent seeding on a persisted .agents_seeded marker on the data volume instead of an empty registry. Prevents baked agents from being resurrected when an operator deletes them via the API but the on-disk TOML remains (the entrypoint re-seeds it each boot). - kernel: dedup imported agents by name within a single seed cycle so two disk manifests sharing a name can't both spawn. - rancher: add pod/container securityContext (non-root, drop caps, readOnlyRootFilesystem + writable /tmp), set OPENFANG_HOME explicitly, and lengthen probe initialDelaySeconds for first-boot seeding. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Feat/deploy dewansh rancher
Repo-tracked manifest so the pipeline can reference a file instead of an
inline paste (which corrupted the YAML with line-number prefixes and lost
indentation). Fixes the truncated ${VAR} tokens, image path, and POD_*
fieldRefs from the failing deploy.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Dockerfile: switch runtime image from rust:1-slim to debian:bookworm-slim (no compiler/toolchain in prod), add libssl3, run as non-root uid 1000 with HOME=/data so pip/npm caches land on the volume. - rancher manifest: pod/container securityContext (runAsNonRoot, fsGroup 1000, drop ALL caps, allowPrivilegeEscalation=false, readOnlyRootFilesystem with a /tmp emptyDir), bump memory limit to 1Gi and PVC to 2Gi. All daemon writes go to the /data PVC (OPENFANG_HOME) and /tmp; entrypoint seeds agents/config with cp -n (never clobbers volume data). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds an opt-in `exclusive_agent` flag to TelegramConfig. When set together with `default_agent`, the bot becomes single-purpose: every message routes to that one agent regardless of bindings/user selection, and the multi-agent discovery/switching commands (/agents, /agent <name>) plus the agent-list welcome are disabled — so a dedicated bot never exposes or lets users switch to other agents. - router: per-channel exclusive map; resolve() returns the locked agent first, overriding bindings, direct routes, and user/channel/system defaults. - bridge: suppress /start, /help, /agents, /agent for exclusive bots (other session commands still work and resolve to the one agent). - channel_bridge: wire the flag at adapter setup (warns if default_agent unset). - docs + a router unit test covering the override precedence. Inert unless exclusive_agent=true: exclusive_agent() returns None otherwise and routing/commands are unchanged for every existing bot and agent. Also underscore-prefixes two unused params in a default trait method to keep clippy -D warnings clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- bake deploy/agents/EbayWatcher (research profile + channel_send; eBay price-watch + dedup-by-listing-id prompt, also does general web research). - config.default.toml: route Telegram -> EbayWatcher with exclusive_agent=true using TELEGRAM_BOT_TOKEN_EBAY (@openfang_ebay_1_bot). Dewansh and assistant stay baked and reachable via the dashboard/API, just not on Telegram. - rancher manifest: swap the injected secret TELEGRAM_BOT_TOKEN -> TELEGRAM_BOT_TOKEN_EBAY and update the required-env notes. Stacked on / depends on the exclusive_agent feature in PR #2 (feat/telegram-exclusive-agent) — that flag is what locks the bot to one agent. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Feat/ebay watcher deploy
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
feat(tools): secure_fetch — env-resolved, allowlisted secret headers
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- lettre 0.11.21 -> 0.11.22 (RUSTSEC-2026-0141, critical) - quinn-proto 0.11.14 -> 0.11.15 (RUSTSEC-2026-0185, high) - rmcp 1.3.0 -> 1.4.0 (RUSTSEC-2026-0189, high) - rustls-webpki 0.103.10 -> 0.103.13 (RUSTSEC-2026-0104/0098/0099) - wasmtime 43.0.1 -> 43.0.2 (RUSTSEC-2026-0114, medium) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
handle_command keyed the default-agent map and session-command resolves on sender.platform_id, which is the *channel* id on Discord/Slack — so test_handle_command_agent_select_keys_on_user_id_not_platform_id failed. A prior rebase had collapsed the upstream user_id param into channel_name (see f67c4e8 / 98e1634); this restores a distinct user_id parameter (callers pass sender_user_id(message)) and keys set_user_default plus the 6 session-command resolves on it, matching the read path. channel_name is retained for exclusive-agent lookup and delivery context. No behavior change for adapters where platform_id already is the user (CLI/Telegram). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
chore: green up CI (fmt + audit + test warnings)
# Conflicts: # Cargo.lock # crates/openfang-kernel/src/kernel.rs # crates/openfang-runtime/src/agent_loop.rs # crates/openfang-runtime/src/tool_runner.rs # crates/openfang-types/src/config.rs
Absorbs upstream's 68 commits (skills system, agent lifecycle clone/activate/ uninstall, requesty provider, security hardening: ws auth/signed/redacted) while preserving 797th's work (secure_fetch tool, sender_id threading, the user_id default-agent fix, CI-green fmt+dep bumps). Conflicts resolved in 5 files: Cargo.lock (regenerated), config.rs (additive), tool_runner.rs (combined tool arms + re-threaded secure_fetch), agent_loop.rs (kept sender_id + upstream features), kernel.rs (preserved user_id fix). Fixed 2 new upstream create_directory test call sites for the sender_id arg. Verified on rustc 1.96: build, fmt, cargo audit, clippy, and RUSTFLAGS=-D warnings cargo test --workspace all green (0 failures); the user_id regression guard test_handle_command_agent_select_keys_on_user_id_not_platform_id passes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
sync: absorb upstream RightNow-AI (skills, agent lifecycle, hardening) — preserve secure_fetch + user_id fix
The kamd1 deployment existed only in-cluster. deploy/rancher/ targets a
different cluster, so nothing in the repo described what serves
openfang.pageapp.net.
Captured live and templated: Deployment, Service, PVC, Traefik IngressRoute
and oauth2-proxy Middleware, plus the mounted config.toml.
No secrets are committed. api_key and the image tag are ${OPENFANG_API_KEY}
and ${IMAGE_TAG}; the referenced secrets are documented by key name only and
must be created out-of-band. Named config.template.toml because .gitignore
ignores config.toml at any depth.
Captured as-is rather than modified: the IngressRoute still uses the
deprecated traefik.containo.us/v1alpha1 API group, and the pod
securityContext is empty.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The captured manifests carried fields written by controllers rather than by
an operator, which made them describe one bound instance instead of desired
state. Reapplying to an empty namespace would have failed.
Removed:
- PVC volumeName, pinned to an existing PV that exists only on kamd1
- PVC pvc-protection finalizer and bind-completed/bound-by-controller
annotations
- Service clusterIP/clusterIPs and the assigned nodePort, plus
ipFamilies, ipFamilyPolicy and other cluster-assigned defaults
- deployment.kubernetes.io/revision, kubectl restartedAt, and Rancher
field.cattle.io/publicEndpoints and metallb pool annotations
Also templated the VERSION env var to ${IMAGE_TAG}. It was pinned at v0.1.2
while the image ran v0.1.3, so it was reporting a stale version.
Header now records the two known gaps in the live deployment left as-is: the
deprecated traefik.containo.us/v1alpha1 API group, and the empty pod
securityContext with no container resource limits.
Verified structurally against the parsed YAML rather than by grep: all five
documents load and no controller-managed field remains.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Match the layout used by the other pageapp deployments: self-contained from
Namespace down, regcred${DOMAIN} inline with ${DOCKER_CONFIG_JSON}, and every
environment variable declared explicitly on the pod rather than bulk-imported.
Replaces envFrom: secretRef: openfang-secrets, which pulled the whole secret
in blind, with one env entry per variable. Each is now visible in the manifest
next to a comment explaining what it is for.
Values stay as ${PLACEHOLDER} rather than literals because this branch is
public. The deploy UI substitutes them the same way it does for
${DOCKER_CONFIG_JSON} elsewhere.
Also added, all absent from the earlier capture:
- Namespace and PVC, so the file stands alone
- POD_NAME/POD_NAMESPACE downward-API vars
- strategy: Recreate, documented: the PVC is RWO and SQLite is
single-writer, so two pods must never hold /data at once
- imagePullPolicy: Always, matching the other deployments
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
docs(deploy): capture kamd1 manifests for openfang.pageapp.net
Adds deploy/797th/ alongside the existing kamd1 and rancher targets. Same
house layout: self-contained from Namespace down, regcred${DOMAIN} inline,
one explicit env entry per variable, values left as ${PLACEHOLDER} for the
deploy UI to substitute.
Differs from deploy/kamd1/ only in domain: harbor.797th.com for the image,
Host(`openfang.797th.com`) on both routes, 797th-com-tls, and forwardAuth
against auth.797th.com.
The /hooks/ route keeps priority 100 with no oauth2-proxy middleware.
ScreenBuddy callbacks authenticate in-app with their own bearer token, so
edge SSO would redirect them and break the callback path.
Unverified against the target cluster, since it is not reachable from here:
the registry host, the 797th-com-tls secret name, the presence of an
oauth2-proxy at auth.797th.com, the longhorn storageclass, and the
traefik-external ingress class are all assumed to match kamd1 conventions.
Confirm before the first apply.
Co-Authored-By: Claude Opus 4.8 <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
Changes
Testing
cargo clippy --workspace --all-targets -- -D warningspassescargo test --workspacepassesSecurity