/** * sim/prompt.ts — prompt & tool assembly of the planner, ported from mirofish * `engine/agent/prompt.py`. * * Capabilities are injected as TOOLS: the planner's vocabulary is the control * actions (speak/done/give_up) plus — with an executor attached — a * first-class `operate` (semantic intent, grounded by the execution layer). * The planner never sees externally injected uses while an executor exists * (single ownership); without one, uses are promoted to direct planner tools. * * Persona injection is two-tier: small personas reside fully in the system * prompt (byte-identical to the classic form); large ones switch to * progressive mode — the system keeps an identity anchor + skill index, and * details surface per step in the user turn via deterministic top-k recall * (no embeddings, no external services; memory-as-tool was deliberately * rejected — real people don't query a memory database). */ import type { Tool } from "@earendil-works/pi-ai"; import { type Part, type PersonaEpisode, type PersonaSkill, type SessionFrame, type SimRuntime } from "./models.ts"; /** * Planner toolset = control actions + the end-shaped action verb: * · executor attached → first-class `operate` (shell = literal command, * vision = semantic intent); shell additionally gets `write_file`. No use * is ever exposed to the planner (they belong to the execution layer). * · no executor but injected uses → each use becomes a direct planner tool. * · no executor, no uses / no runtime → pure cognition (control only). */ export declare function toolSpecs(runtime: SimRuntime | null | undefined): Tool[]; /** Deterministic tokenizer: latin words + digits + single CJK chars. */ export declare function toks(s: string | null | undefined): Set; /** score = |query ∩ item| / sqrt(|item|); ties keep original order. */ export declare function rank(items: T[], texts: string[], situationText: string, k: number): T[]; export declare function retrieveEpisodes(episodes: PersonaEpisode[], situationText: string, k?: number): PersonaEpisode[]; export declare function retrieveSkills(skills: PersonaSkill[], situationText: string, k?: number): PersonaSkill[]; /** Progressive mode: memories + skill bodies surfacing for THIS step, injected * into the user turn (recomputed and replaced each step; never enters history, * never touches the stable system prefix). Resident mode returns "". */ export declare function situatedRecall(frame: SessionFrame, observation: Part[]): string; /** Slot order (fixed): role declaration → who you are → skills → memory → * situation → in front of you → when to end → anti-bias → monologue rule → * tool rule → anti-hallucination. */ export declare function systemPrompt(frame: SessionFrame): string; export declare function partsText(parts: Part[]): string; /** * The folded user turn: history causal chain + current observation as one * text block (past screenshots become placeholders; real images ride as * separate blocks). Folded steps keep a one-line delegation gist — forget the * details, keep the conclusion — or early findings would evaporate. */ export declare function userText(frame: SessionFrame, observation: Part[]): string; /** * Part.ref → {data, mimeType} for the model API, or null to skip the image * (missing files never block inference). Refs are references by contract — * base64 is only materialized at the API call boundary, never persisted. * Supported: data: URLs and local file paths (the pi-gui world keeps * screenshots as local files); http(s) refs are skipped in P1. */ export declare function imageData(ref: string): { data: string; mimeType: string; } | null;