CI / Lint (push) Canceled after 0s
CI / Build Test (stage-web) (push) Canceled after 0s
CI / Build Test (ui-loading-screens) (push) Canceled after 0s
CI / Build Test (ui-transitions) (push) Canceled after 0s
CI / Unit Test (push) Canceled after 0s
CI / Type Check (push) Canceled after 0s
CI / Check Provenance (push) Canceled after 0s
Sync Labels / sync-labels (push) Successful in 1m43s
- Remove stage-tamagotchi, stage-pocket, server, and engine workspaces with their workflows, addons, and docs - Switch the toolchain from pnpm to bun, replace lockfiles with bun.lock - Rewrite remaining product references to Moeka
55 lines
2.8 KiB
Markdown
55 lines
2.8 KiB
Markdown
### **Prompt Architecture: Context-Injected Action Loop**
|
|
|
|
The bot implements a **"State-Aware Agentic Loop"** rather than a simple Chat-QA structure. The prompt is constructed dynamically at every tick of the loop.
|
|
|
|
#### **1. Static Layer (System Definitions)**
|
|
|
|
* **Source:** `src/core/planner/prompts/*.velin.md`
|
|
* **Loader:** `src/core/planner/prompts/index.ts`
|
|
* **Role:** Defines the "Soul" and "Rules".
|
|
* **Components:**
|
|
* **Protocol Definition (`system-action-gen-v1`):** Hardcodes the JSON schema for available tools (`send_message`, `read_unread_messages`, `sleep`) and logic flow (e.g., "Must check unread messages after sending").
|
|
* **Persona (`personality-v1`):** Defines the character "Moeka" (tone, brevity, naturalness).
|
|
|
|
#### **2. History Layer (Short-term Memory)**
|
|
|
|
* **Source:** In-memory `messages` array (`ChatContext`).
|
|
* **Role:** Provides conversational continuity.
|
|
* **Mechanism:** A sliding window of the last ~20 messages (User/Assistant turns) is injected directly after the system prompt.
|
|
|
|
#### **3. Dynamic State Layer (Sensory Injection)**
|
|
|
|
* **Source:** `src/core/planner/llm-client.ts` (Runtime generated)
|
|
* **Role:** Provides "Situational Awareness" and "Grounding".
|
|
* **Mechanism:** A synthesized **User Message** is appended at the very end of the context window, forcing the LLM to focus on the immediate reality. It contains:
|
|
* **Incoming Stream**: Raw content of new messages arriving *now* (passed from `scheduler`).
|
|
* **Action History**: Results of the *immediately preceding* tool executions (e.g., "Action: send_message, Result: Success").
|
|
* **Environment**: Current server time.
|
|
* **Global State**: A summary of unread message counts across all channels (`unreadEvents`).
|
|
* **Trigger**: The final instruction: *"Based on the context... Respond with the action... in JSON only."*
|
|
|
|
---
|
|
|
|
### **Data Flow Summary**
|
|
|
|
```mermaid
|
|
graph TD
|
|
A[Static Markdown] -->|Velin Render| B(System Message)
|
|
C[Chat History] -->|Sliding Window| D(Context Body)
|
|
E[Runtime State] -->|Unread/Time/Results| F(State Injection)
|
|
|
|
B --> G[Final Prompt]
|
|
D --> G
|
|
F --> G
|
|
|
|
G -->|LLM API| H{Decision}
|
|
H -->|JSON| I[Action Dispatcher]
|
|
|
|
```
|
|
|
|
### **Key Characteristics**
|
|
|
|
1. **JSON Enforcement**: The bot does not use native "Function Calling" APIs (like OpenAI Tools). It relies on **Prompt Engineering** to force the model to output raw JSON, which is then parsed by `best-effort-json-parser`.
|
|
2. **Stateless Logic**: The prompt explicitly tells the LLM "You have X unread messages" in every turn, making the LLM the sole decision-maker for flow control (Reading vs. Replying vs. Sleeping).
|
|
3. **Observation-Reflection**: The prompt includes `History actions`, allowing the LLM to "see" the result of its previous attempt (e.g., if a read action returned empty, it knows to stop).
|