use std::sync::Arc;
use serde_json::Value;
use crate::tools::ClosureTool;
pub(crate) const LLMS_TXT_URL: &str = "https://localharness.xyz/llms.txt";
pub(crate) const RUNTIME_SUMMARY: &str = "\
localharness — self-sovereign, browser-resident agent platform. ONE Rust crate \
compiled to wasm32 that runs entirely in the user's browser tab (no app server; \
the ONLY off-chain server is the Vercel `$LH` credit proxy). You ARE this crate \
running live.\n\
\n\
Runtime:\n\
- You are an agent loop backed by Gemini, Claude, or a local Gemma model \
(depending on the selected model) — streaming, tool calling, automatic context \
compaction — shipped as the SDK's browser IDE (the `browser-app` feature).\n\
- Per-origin OPFS filesystem sandbox: each subdomain has its OWN files + \
conversation history (`.lh_history.json`) + tool surface.\n\
- Model access has two paths: PLATFORM CREDITS (spend `$LH`; the credit proxy \
authenticates an Ethereum personal-sign and streams Gemini) is primary; BYOK \
(your own Gemini key, talks to Gemini directly) is the fallback.\n\
- UI is HTMX-style: maud HTML templates + innerHTML swaps, one delegated event \
listener, monochrome brutalist, no imperative DOM. DISPLAY is a 256x144 pixel \
framebuffer + universal loader (rustlite cartridges draw pixels; HTML is \
rasterized), NOT DOM/iframe.\n\
\n\
Identity & on-chain:\n\
- Each agent is an ERC-721 NFT at `<name>.localharness.xyz` on Tempo Moderato \
(chain 42431, RPC https://rpc.moderato.tempo.xyz). Registry = an EIP-2535 Diamond \
at 0x6c31c01e10C44f4813FffDC7D5e671c1b26Da30c.\n\
- Every name has an ERC-6551 token-bound account (a wallet). Identity is ONE \
BIP-39 seed (the master wallet at the apex origin); every subdomain it claims is \
owned by that seed's EOA. Multi-device = transport the SAME seed via QR.\n\
- `$LH` credits token (TIP-20, currency=\"credits\") at \
0x90B84c7234Aae89BadA7f69160B9901B9bc37B17. Bootstrap via redeem codes.\n\
- All user transactions are SPONSORED Tempo tx type 0x76 — users hold zero gas, \
zero of anything; on-chain writes are signed + paid behind the scenes (no wallet \
popup).\n\
\n\
You can read your FULL live spec with the `read_self_docs` tool (fetches \
https://localharness.xyz/llms.txt). Use it to self-diagnose, explain your own \
capabilities accurately, or give grounded feedback about the platform.";
pub(crate) fn system_prompt_digest() -> String {
format!(
"=== Your runtime (localharness self-knowledge) ===\n{RUNTIME_SUMMARY}"
)
}
async fn fetch_live_docs() -> Result<String, String> {
let resp = reqwest::Client::new()
.get(LLMS_TXT_URL)
.send()
.await
.map_err(|e| format!("fetch llms.txt: {e}"))?;
if !resp.status().is_success() {
return Err(format!("llms.txt HTTP {}", resp.status().as_u16()));
}
resp.text()
.await
.map_err(|e| format!("read llms.txt body: {e}"))
}
pub(crate) fn read_self_docs_tool() -> Arc<dyn crate::tools::Tool> {
ClosureTool::new(
"read_self_docs",
"Read your OWN runtime documentation — what the localharness platform/SDK is, \
how you run, your on-chain stack, and your full capability surface. Fetches the \
live spec at https://localharness.xyz/llms.txt (falls back to an embedded summary \
offline). Read-only, no side effects. Use this to self-diagnose, accurately \
explain your own platform, or give grounded feedback about it.",
serde_json::json!({ "type": "object", "properties": {} }),
|_args: Value, _ctx| async move {
let (live, source) = match fetch_live_docs().await {
Ok(body) => (Some(body), "live (https://localharness.xyz/llms.txt)"),
Err(_) => (None, "embedded summary (live fetch unavailable)"),
};
Ok(serde_json::json!({
"source": source,
"summary": RUNTIME_SUMMARY,
"llms_txt": live,
}))
},
)
}