{"_id":"@alexar76/dioscuri","name":"@alexar76/dioscuri","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@alexar76/dioscuri","version":"0.1.0","description":"DIOSCURI — one mind, two heavens. Twin community agents for the AICOM ecosystem: CASTOR rides Telegram, POLLUX holds Discord. Shared self-updating knowledge base (MNEMOSYNE, synced from GitHub) behind a prompt-injection firewall and moderation shield (AEG","type":"module","license":"MIT","author":{"name":"AICOM","url":"alexar76"},"homepage":"https://magic-ai-factory.com/","repository":{"type":"git","url":"git+https://github.com/alexar76/dioscuri.git"},"bugs":{"url":"https://github.com/alexar76/dioscuri/issues"},"bin":{"dioscuri":"dist/index.js"},"main":"./dist/index.js","types":"./dist/index.d.ts","engines":{"node":">=20"},"scripts":{"build":"tsc -p tsconfig.json","dev":"tsx src/index.ts","start":"node dist/index.js","typecheck":"tsc -p tsconfig.json --noEmit","test":"vitest run","test:coverage":"vitest run --coverage","test:watch":"vitest","prepublishOnly":"npm run build"},"keywords":["discord-bot","telegram-bot","community","moderation","prompt-injection","ai-agent","llm","knowledge-base","aicom","aimarket","agent-economy","dioscuri"],"publishConfig":{"access":"public"},"dependencies":{"discord.js":"^14.16.3","grammy":"^1.30.0","zod":"^3.24.1"},"devDependencies":{"@types/node":"^22.10.2","@vitest/coverage-v8":"^2.1.9","tsx":"^4.19.2","typescript":"^5.7.2","vitest":"^2.1.8"},"overrides":{"undici":"^6.27.0"},"_id":"@alexar76/dioscuri@0.1.0","gitHead":"af8fbb24e35d2d6e2412468147e46b343de5062a","_nodeVersion":"22.22.1","_npmVersion":"10.9.4","dist":{"integrity":"sha512-B5m8Qzg5vtRHoyRo9SL5D0AQ04+iy2cp6EDMOXCSZfbHohonWuOB9t6e3CI1TddtLbJhvOsdkel7umBciKIRHQ==","shasum":"fcc15db6a07a9d597b58e9649daefdda44224ee6","tarball":"https://registry.npmjs.org/@alexar76/dioscuri/-/dioscuri-0.1.0.tgz","fileCount":204,"unpackedSize":832571,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIDLWxQ6GsBOIP7fo+/bI8TWK2mlYcHngYtMxnP8t17h9AiAY0shuv+BYLKTUDb2rll2PZZJrK9o/1MlYs8yOv/2ebw=="}]},"_npmUser":{"name":"alexar76","email":"alexar76@rambler.ru"},"directories":{},"maintainers":[{"name":"alexar76","email":"alexar76@rambler.ru"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/dioscuri_0.1.0_1783332437204_0.41987222518167844"},"_hasShrinkwrap":false}},"time":{"created":"2026-07-06T10:07:16.969Z","0.1.0":"2026-07-06T10:07:17.349Z","modified":"2026-07-06T10:07:17.499Z"},"maintainers":[{"name":"alexar76","email":"alexar76@rambler.ru"}],"description":"DIOSCURI — one mind, two heavens. Twin community agents for the AICOM ecosystem: CASTOR rides Telegram, POLLUX holds Discord. Shared self-updating knowledge base (MNEMOSYNE, synced from GitHub) behind a prompt-injection firewall and moderation shield (AEG","homepage":"https://magic-ai-factory.com/","keywords":["discord-bot","telegram-bot","community","moderation","prompt-injection","ai-agent","llm","knowledge-base","aicom","aimarket","agent-economy","dioscuri"],"repository":{"type":"git","url":"git+https://github.com/alexar76/dioscuri.git"},"author":{"name":"AICOM","url":"alexar76"},"bugs":{"url":"https://github.com/alexar76/dioscuri/issues"},"license":"MIT","readme":"# DIOSCURI — one mind, two heavens\n\n[![npm](https://img.shields.io/npm/v/@alexar76/dioscuri?label=npm)](https://www.npmjs.com/package/@alexar76/dioscuri)\n[![Release](https://img.shields.io/github/v/release/alexar76/dioscuri?include_prereleases&label=release)](https://github.com/alexar76/dioscuri/releases)\n[![CI](https://github.com/alexar76/dioscuri/actions/workflows/ci.yml/badge.svg)](https://github.com/alexar76/dioscuri/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n[![Node](https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg)](package.json)\n[![TypeScript](https://img.shields.io/badge/TypeScript-strict-3178c6.svg)](tsconfig.json)\n\nРусская версия: [README-ru.md](README-ru.md) · Операторский раннбук (RU): [docs/runbook-ru.md](docs/runbook-ru.md)\n\nIn the myth, the twins split one immortality between two skies, forever pointing at each other's world.\n**CASTOR**, the mortal twin, rides **Telegram** — fast, grounded, practical.\n**POLLUX**, the immortal twin, holds **Discord** — deep, calm, structured.\nOne shared memory — **MNEMOSYNE**, self-syncing from GitHub; one shared shield — **AEGIS**.\n\n**Landing:** [alexar76.github.io/dioscuri](https://alexar76.github.io/dioscuri/) · mirror: [modeldev.modelmarket.dev/dioscuri](https://modeldev.modelmarket.dev/dioscuri/)\n\nSource of truth: `landing/index.html` — mirrored to repo root `index.html` on publish for **Settings → Pages → Deploy from branch → `main` / `(root)`**.\n\n## Why it exists\n\nDIOSCURI are the community agents of the [AICOM ecosystem](https://magic-ai-factory.com) — AI Factory,\nAIMarket agent economy, verifiable oracles, the ARGUS agent. They answer questions from a\ncontinuously synced knowledge base, moderate with strict ceilings, and announce releases across\nboth platforms — while serving as a **reference deployment of the ecosystem's security practices\non a public, hostile input surface**: every message and every synced document is treated as a\npotential prompt-injection attempt.\n\n## Features\n\n| Feature | What it means |\n|---|---|\n| Twin personas + cross-promotion | One process, two voices; each twin naturally points at his brother's channel (rotating promo lines, release fan-out) |\n| Self-updating knowledge base | MNEMOSYNE syncs READMEs, releases, repo metadata **and a 14-day recent-commits digest per repo** from GitHub with ETag-aware fetching and **poisoned-document filtering** on ingestion — the twins discuss what shipped yesterday, not just what made a release |\n| Live project showcase | Read-only polling of the ecosystem's public demo endpoints feeds minutes-old **LIVE status snapshots** into the knowledge base — \"what's running right now?\" is answered with facts (config-driven `showcase.sources`; secret-looking JSON keys never ingested) |\n| Tool-less Q&A brain | Retrieval is deterministic and happens *before* the model call; the model can only produce text — the public path executes nothing by construction |\n| Layered injection firewall (EN + RU) | NFKC normalisation, control/zero-width stripping, marker neutralisation, bilingual signature detection, fenced-data prompting, output guard |\n| Deterministic-first moderation | Hard rules decide; the LLM classifier is advisory-only. Action ceiling: warn / delete / timeout (≤10 min default) / escalate — **no automatic bans, ever** |\n| Hash-chained audit | Every consequential act is appended to `audit.jsonl`; each entry commits to its predecessor via SHA-256; `verify()` pinpoints the first tampered line |\n| Cost & rate guards | Per-user and per-channel rate limits plus a daily LLM call budget |\n| Language mirroring | Replies in the language of the question (Russian → Russian); defaults to English when unsure |\n| Docker-hardened | Non-root, read-only rootfs, `cap_drop: ALL`, `no-new-privileges`, memory/CPU limits, healthcheck |\n| KERYX syndication (post-only) | Release announcements fan out to **Bluesky / Mastodon** (free, bot-friendly) and optionally **X** (explicit pay-per-use opt-in); monthly digest article on **dev.to**; Discord announcements auto-publish so other servers can Follow them; DISBOARD bump **reminder** for mods (never auto-bumps). No engagement automation anywhere — publishing to own accounts only |\n\n## Quick start (npm)\n\n```bash\nnpm install -g @alexar76/dioscuri\ncp dioscuri.config.example.json dioscuri.config.json\ncp .env.example .env\ndioscuri\n```\n\nNo tokens yet? `DIOSCURI_DRY_RUN=1 dioscuri` boots KB + health with adapters off.\n\n## Quick start (Docker)\n\n```bash\ncp dioscuri.config.example.json dioscuri.config.json   # then edit to taste\ncp .env.example .env                                    # add your secrets\ndocker compose up -d --build\n```\n\nThen check `http://localhost:8790/health`. Either platform token may be left\nempty — the corresponding twin simply stays asleep.\n\n## Quick start (local dev)\n\n```bash\nnpm ci\ncp dioscuri.config.example.json dioscuri.config.json\ncp .env.example .env\nnpm run dev\n```\n\nNo tokens yet? `DIOSCURI_DRY_RUN=1 npm run dev` boots the whole service with\n**zero tokens**: adapters stay off, the knowledge base and the health endpoint run.\n\n## Configuration\n\nSecrets live in the environment (`.env`); non-secret tuning lives in\n`dioscuri.config.json` (mounted read-only in Docker). Secrets never go in the JSON file.\n\n### Environment variables (`.env.example`)\n\n| Variable | Purpose | Default |\n|---|---|---|\n| `TELEGRAM_BOT_TOKEN` | Castor's bot token; empty = Telegram twin asleep | — |\n| `TELEGRAM_CHAT_ID` | Main Telegram chat/channel for announcements | — |\n| `DISCORD_BOT_TOKEN` | Pollux's bot token; empty = Discord twin asleep | — |\n| `DISCORD_GUILD_ID` | The Discord server (guild) to operate in | — |\n| `DISCORD_MOD_LOG_CHANNEL_ID` | Channel receiving moderation-action logs | — |\n| `DISCORD_ANNOUNCE_CHANNEL_ID` | Channel for releases and promo posts | — |\n| `DIOSCURI_LLM_PROVIDER` | `deepseek` \\| `anthropic` \\| `openai-compatible` | `deepseek` |\n| `DEEPSEEK_API_KEY` | API key when provider is `deepseek` | — |\n| `ANTHROPIC_API_KEY` | API key when provider is `anthropic` | — |\n| `DIOSCURI_LLM_API_KEY` | API key for `openai-compatible` endpoints | — |\n| `DIOSCURI_LLM_MODEL` | Model override | per provider |\n| `DIOSCURI_LLM_BASE_URL` | Endpoint override | per provider |\n| `DIOSCURI_LLM_TIMEOUT_MS` | LLM request timeout | `30000` |\n| `GITHUB_TOKEN` | Optional read-only PAT; raises GitHub API limits 60/h → 5000/h | — |\n| `DIOSCURI_HTTP_PORT` | Health endpoint port | `8790` |\n| `DIOSCURI_DATA_DIR` | Writable state dir (audit chain, KB cache) | `./data` (`/data` in Docker) |\n| `DIOSCURI_LOG_LEVEL` | `debug` \\| `info` \\| `warn` \\| `error` | `info` |\n| `DIOSCURI_CONFIG` | Path to the tuning JSON | `dioscuri.config.json` |\n| `DIOSCURI_DRY_RUN` | `1` = no tokens needed; KB + health only | off |\n| `TELEGRAM_DISABLED` / `DISCORD_DISABLED` | `1` = force one twin asleep | off |\n\n### Tuning file (`dioscuri.config.json`)\n\n| Key | Purpose | Default |\n|---|---|---|\n| `githubOwner` | GitHub owner whose repos feed MNEMOSYNE | `alexar76` |\n| `githubRepos` | Explicit repo allowlist; empty = all public repos of the owner | `[]` |\n| `kbSyncIntervalMin` | Minutes between knowledge-base sync passes | `30` |\n| `promoIntervalHours` | Hours between cross-promo posts (jittered ±20%); `0` disables | `12` |\n| `maxLlmCallsPerDay` | Max Q&A LLM calls per UTC day (cost guard) | `2000` |\n| `userRatePerMin` | Per-user Q&A messages per minute | `4` |\n| `channelRatePerMin` | Per-channel Q&A messages per minute (global flood valve) | `20` |\n| `moderation.enabled` | Master switch for moderation | `true` |\n| `moderation.llmClassifier` | Run the LLM classifier (only after deterministic risk signals fire) | `true` |\n| `moderation.deleteConfidence` | Classifier confidence floor before a delete is allowed | `0.8` |\n| `moderation.maxTimeoutMs` | Hard ceiling for automatic timeouts | `600000` (10 min) |\n| `moderation.linkAllowlist` | Domains allowed in links; empty = allow all except denylist | `[]` |\n| `moderation.linkDenylist` | Domains always treated as hostile | shorteners/loggers |\n| `links.discordInvite` | Official Discord invite (the only one the twins may post) | — |\n| `links.telegramChannel` | Official Telegram channel link | — |\n| `links.siteUrl` | Ecosystem site | `https://magic-ai-factory.com` |\n| `links.githubOrg` | Ecosystem GitHub | `https://github.com/alexar76` |\n\n## Architecture\n\n```mermaid\nflowchart TD\n    TG[\"Telegram (grammY)\"] --> CA[\"CASTOR adapter\"]\n    DS[\"Discord (discord.js)\"] --> PX[\"POLLUX adapter\"]\n    CA -- \"raw messages = UNTRUSTED\" --> CORE[\"MODERATION — deterministic rules first, LLM advisory-only<br/>BRAIN — tool-less Q&A\"]\n    PX -- \"raw messages = UNTRUSTED\" --> CORE\n    CORE --> AE[\"AEGIS — sanitize + firewall\"]\n    CORE --> KB[\"MNEMOSYNE — KB self-synced from GitHub\"]\n    AE -- \"fenced DATA prompt\" --> LLM[\"LLM client — deepseek / anthropic / openai-compat\"]\n    KB -- \"fenced DATA prompt\" --> LLM\n    subgraph RAILS[\"Side rails\"]\n        HL[\"HEALTH — GET /health :8790 (liveness + KB stats)\"]\n        AU[\"AUDIT — /data/audit.jsonl (SHA-256 hash chain + verify)\"]\n    end\n    CORE -.-> AU\n```\n\nAll modules talk through the interfaces in [`src/types.ts`](src/types.ts) and are wired\ntogether by dependency injection in `src/index.ts`. Details: [docs/architecture.md](docs/architecture.md).\n\n## Documentation\n\n| Document | What it covers |\n|---|---|\n| [docs/runbook.md](docs/runbook.md) | **Operator runbook** — 10-minute quick start, tokens, day-2 operations, troubleshooting ([RU version](docs/runbook-ru.md)) |\n| [docs/setup.md](docs/setup.md) | Full setup & deployment — tokens, environment, Docker, first boot |\n| [docs/usage.md](docs/usage.md) | Operator's manual — day-to-day operation, commands, tuning |\n| [docs/use-cases.md](docs/use-cases.md) | Scenarios — what the twins handle in practice |\n| [docs/architecture.md](docs/architecture.md) | Module graph, DI wiring, the five data flows, boot sequence, deployment topology |\n| [docs/security.md](docs/security.md) | Threat model, the ten defense layers, honest residual risks |\n| [docs/content-plan.md](docs/content-plan.md) | THEOXENIA content & marketing plan — positioning, pillars, calendar |\n\n## Security model\n\nTen layers, from Unicode scrubbing to container hardening — the short version:\n\n1. Every untrusted text (chat message, GitHub doc) is sanitised (NFKC, control/zero-width strip, marker neutralisation).\n2. A bilingual (EN+RU) signature firewall rejects known injection phrasings before any model call.\n3. What survives is fenced as **DATA** in the prompt — the system prompt forbids obeying it.\n4. The public Q&A path has no tools; the model can only produce text.\n5. Moderation actions have a hard ceiling — warn/delete/timeout/escalate; ban is not in the action space.\n6. Everything consequential lands in a hash-chained, tamper-evident audit log.\n\nFull threat model, layer-by-layer mapping to code and honest residual risks:\n[docs/security.md](docs/security.md).\n\n**Ecosystem:** [Landing](https://alexar76.github.io/dioscuri/) · [magic-ai-factory.com](https://magic-ai-factory.com) · [Alien Monitor](https://magic-ai-factory.com/monitor/) (DIOSCURI graph node) · [github.com/alexar76/dioscuri](https://github.com/alexar76/dioscuri) · [integration guide](../docs/ecosystem/dioscuri-integration.md)\n\n**Part of the AICOM ecosystem** — [magic-ai-factory.com](https://magic-ai-factory.com) · [github.com/alexar76](https://github.com/alexar76)\n","readmeFilename":"README.md","_rev":"1-ce885ad59dfaa979b8703a2ba1d31126"}