prompt_context

Async context builder for system-prompt template variables.

Gathers runtime data from the incoming message, platform adapter, bot configuration, and (optionally) Redis to produce the full dictionary that PromptRenderer feeds into the Jinja2 template.

class prompt_context.ConfigSingleton[source]

Bases: object

PUBLIC_IP: str = '127.0.0.1'
IP_RESOLVED: bool = False
async prompt_context.resolve_public_ip_once()[source]

Resolve and cache the host’s outbound public IPv4 exactly once.

Memoizes the result on the ConfigSingleton so the inference worker pays the network cost a single time at bootstrap rather than on every prompt build; later calls short-circuit on the cached value. This matters because the IP feeds the (whitelist-gated) bot_ip field of the system prompt and must never block the message hot path.

Makes one outbound HTTP GET to api.ipify.org via httpx under a 3-second timeout, mutating ConfigSingleton.PUBLIC_IP and ConfigSingleton.IP_RESOLVED. On any failure it logs, raises an observability WARNING alert, and falls back to 127.0.0.1 while still marking resolution complete so it is not retried per message. Called by PromptContextBuilder._build_public_ips() (lazily, if not yet resolved) and exercised directly by the whitelisting test suite.

Returns:

The resolved public IPv4 address, or "127.0.0.1" on failure.

Return type:

str

prompt_context.build_whitelisted_prompt_context(channel_id, user_name, raw_vector)[source]

Build the user/environment context block, gating secrets by whitelist.

Assembles the user and environment sub-dicts that feed the system prompt, parsing valence/arousal out of a heterogeneous raw_vector (list, tuple, or dict keyed by name or index). Sensitive fields — the bot’s public IP, real limbic resonance, and a secret-metadata-access flag — are only populated when the channel passes _is_channel_in_whitelist() against STAR_CONTEXT_CHANNEL_WHITELIST; otherwise they are redacted to safe defaults. This is the choke point that keeps host secrets out of prompts rendered for untrusted channels.

Reads the STAR_CONTEXT_CHANNEL_WHITELIST environment variable and ConfigSingleton.PUBLIC_IP, and emits whitelisted_context_injected or context_redacted observability counters as a side effect. Called by PromptContextBuilder._build_runtime() (which merges the result into the runtime context) and directly by the whitelisting test suite.

Parameters:
  • channel_id (str) – Channel the prompt is being built for; decides whether secrets are injected.

  • user_name (str) – Display name of the interacting user.

  • raw_vector (list[float] | dict[str, Any] | None) – Optional limbic vector from which valence (index/key 0) and arousal (index/key 1) are extracted; malformed values are logged and treated as 0.0.

Returns:

A nested {"user": ..., "environment": ...} context dict, with sensitive fields either populated or redacted.

Return type:

dict[str, Any]

async prompt_context.fetch_git_metadata_async(project_root)[source]

Resolve the current commit hash and ref decoration via async git.

Shells out to git log -1 --format=%h%d in a non-blocking asyncio.create_subprocess_exec() so the event loop is never blocked, parsing the short hash and any ref decoration (branch/tag) into a small metadata dict. The result drives the self-awareness release_tag shown in the system prompt, so it must degrade gracefully rather than raise. A 3-second asyncio.wait_for() timeout bounds the call, and any timeout or error is logged and folded into a static fallback.

Touches the filesystem only by reading the git repository at project_root; no Redis, network, or other side effects. Called by PromptContextBuilder._build_git_metadata() and exercised by the prompt-context safeguard and whitelisting tests.

Parameters:

project_root (str) – Path to the git working tree to inspect (passed as the subprocess cwd).

Returns:

{"hash": ..., "tag": ...} with the parsed values, or fallback values ("unknown" / "v3.0.0-release") on any failure.

Return type:

dict[str, str]

prompt_context.resolve_skills_corpus_roots(cfg)[source]

Resolve the configured Agent Skills corpus roots to absolute paths.

Normalizes each entry of cfg.skills_corpus_roots so the system prompt can advertise unambiguous on-disk locations for skill files: relative segments are joined to the current working directory and resolved, while unresolvable paths fall back to their original string. Surfacing absolute roots is what lets the model (and the activate_skill tool) locate SKILL.md directories reliably on this deployment.

Reads cfg.skills_corpus_roots and the process working directory and touches the filesystem only via pathlib.Path.resolve() (which may stat paths); no other side effects. Called by PromptContextBuilder._build_skills_storage_paths().

Parameters:

cfg (Any) – Config object expected to expose a skills_corpus_roots iterable (treated as empty if missing).

Returns:

Absolute (or best-effort) path strings, one per configured root.

Return type:

list[str]

prompt_context.format_mention(user_id, platform)[source]

Format a user mention appropriate for platform.

Produces the platform-native ping syntax so the rendered system prompt can reference the bot and owner in a form the user’s client will linkify. Discord wraps the snowflake as <@USER_ID>; Matrix user IDs (@user:server) are already display-ready and returned verbatim. Pure string formatting with no I/O or side effects.

Called by PromptContextBuilder._build_runtime() for both the bot_mention and owner_mention template variables.

Parameters:
  • user_id (str) – The platform user identifier to mention.

  • platform (str) – Platform name; "discord" / "discord-self" trigger Discord-style wrapping, anything else is passed through.

Returns:

The formatted mention string.

Return type:

str

prompt_context.invalidate_self_json_cache()[source]

Invalidate the process-level prompts/self.json cache.

Resets the module-global _self_json_cache to None so the next _load_self_json() call re-reads the persona blob from disk. This is how an in-place edit to the bot’s self description (via the modify_self_json tool) becomes visible without restarting the worker.

Mutates module global state only — no Redis, network, or filesystem access — and logs the invalidation. Called by tools/modify_self_json.py after it writes the file, and by the SWORD adversarial test suite.

Return type:

None

Returns:

None

class prompt_context.PromptContextBuilder(config, kg_manager=None, threadweave_manager=None, status_manager=None, message_cache=None, task_manager=None, conversation_manager=None, openrouter_client=None, persona_pref_manager=None, sword_graph_manager=None)[source]

Bases: object

Build the template-variable dict consumed by the system prompt.

Parameters:
  • config (Config) – The global Config instance (provides model, redis_url, etc.).

  • kg_manager (KnowledgeGraphManager | None) – Optional KnowledgeGraphManager for injecting knowledge graph context into the system prompt. None when Redis is not configured.

  • threadweave_manager (ThreadweaveManager | None)

  • status_manager (Any | None)

  • message_cache (MessageCache | None)

  • task_manager (TaskManager | None)

  • conversation_manager (ConversationManager | None)

  • openrouter_client (Any | None)

  • persona_pref_manager (Any | None)

  • sword_graph_manager (Any | None)

__init__(config, kg_manager=None, threadweave_manager=None, status_manager=None, message_cache=None, task_manager=None, conversation_manager=None, openrouter_client=None, persona_pref_manager=None, sword_graph_manager=None)[source]

Initialize the instance.

Parameters:
  • config (Config) – Bot configuration object.

  • kg_manager (KnowledgeGraphManager | None) – The kg manager value.

  • threadweave_manager (ThreadweaveManager | None) – The threadweave manager value.

  • status_manager (Any | None) – The status manager value.

  • message_cache (MessageCache | None) – The message cache value.

  • task_manager (TaskManager | None) – The task manager value.

  • conversation_manager (ConversationManager | None) – The conversation manager value.

  • openrouter_client (Any | None) – Shared OpenRouterClient for embedding connection pooling.

  • persona_pref_manager (Any | None) – PersonaPreferenceManager instance.

  • sword_graph_manager (Any | None) – SWORD graph manager instance.

Return type:

None

all_adapters: list[PlatformAdapter]
async build(msg, platform, query_embedding=None)[source]

Collect every context section and return a merged dict.

Sections that depend on Redis silently return empty values when Redis is not configured. Sections that depend on Discord- specific data gracefully degrade on other platforms.

Return type:

dict[str, Any]

Parameters:
build_minimal(msg, platform)[source]

Return a context dict using only synchronous, I/O-free sections.

Guarantees every unconditional template variable is present so the Jinja2 renderer never receives a bare Undefined object. Used as the fallback when the full async build() call times out or raises an unexpected exception.

Return type:

dict[str, Any]

Parameters:
async warm_golden_goddess_chroma()[source]

Pre-warm the Golden Goddess pgvector pool. Idempotent.

Safe to call at service startup before platforms connect; also used by _divine_reflex() on first query. (Method name kept for back-compat; the backing store is now Postgres + pgvector.)

Return type:

None