feat(hololake): expose typed runtime context and modules
This commit is contained in:
parent
03e4338ab8
commit
b433611857
4 changed files with 56 additions and 3 deletions
|
|
@ -4,7 +4,12 @@
|
|||
"protocol": "GLP_LOCAL_REALTIME/1",
|
||||
"transport": {"bind":"127.0.0.1","ports":"39281-39290","framing":"NDJSON","authentication":"LOCAL_0600_TOKEN","authority_from_transport":false},
|
||||
"client_messages": ["hello", "persona_response", "external_ai_message", "tcs_proposal", "ping"],
|
||||
"server_messages": ["welcome", "user_message", "proposal_pending", "proposal_rejected", "agent_receipt", "accepted", "pong", "error"],
|
||||
"server_messages": ["welcome", "system_context", "user_message", "proposal_pending", "proposal_rejected", "agent_receipt", "accepted", "pong", "error"],
|
||||
"system_context": {
|
||||
"schema": "hololake.persona-visible-system-context/v1",
|
||||
"contains": ["CHANNEL_ID_AND_NAME", "PERSONA_STATE", "MODULE_STATES", "ENTERPRISE_ENTRANCE_STATE", "PENDING_AGENT_PROPOSALS", "SOURCE_KINDS", "AUTHORITY_BOUNDARIES"],
|
||||
"forbidden": ["TOKENS", "PRIVATE_KEYS", "RAW_MACHINE_FINGERPRINT", "PRIVATE_FILE_PATHS", "PRIVATE_CONTENT"]
|
||||
},
|
||||
"source_kinds": ["USER_MESSAGE", "PERSONA_RESPONSE", "EXTERNAL_AI_MESSAGE", "SYSTEM_CONTEXT", "PROTOCOL_EVENT", "AGENT_ACTION", "TOOL_RESULT", "SYSTEM_RECEIPT"],
|
||||
"persona_states": ["READY_NO_PERSONA", "LOCAL_TRIAL_UNVERIFIED_EXTERNAL_HOST_REQUIRED", "LOCAL_TRIAL_UNVERIFIED_HOST_CONNECTED"],
|
||||
"registered_gir_operations": ["KNOWLEDGE.CREATE", "KNOWLEDGE.UPDATE", "KNOWLEDGE.DELETE", "KNOWLEDGE.READ", "KNOWLEDGE.LIST"],
|
||||
|
|
|
|||
|
|
@ -49,6 +49,12 @@ if runtime_contract["transport"]["bind"] != "127.0.0.1":
|
|||
errors.append("realtime bridge is not loopback-only")
|
||||
if runtime_contract["mutation_gate"] != "PENDING_HUMAN_APPROVAL_TO_EXPLICIT_UI_APPROVAL_TO_EXECUTION":
|
||||
errors.append("agent human approval gate missing")
|
||||
if "system_context" not in runtime_contract.get("server_messages", []):
|
||||
errors.append("persona-visible system context missing from GLP contract")
|
||||
realtime_source = (ROOT / "src-tauri/src/realtime_bridge.rs").read_text()
|
||||
for required_context in ("sourceKinds", "pendingAgentProposals", "enterpriseEntrance", "proposalIsNotExecution"):
|
||||
if required_context not in realtime_source:
|
||||
errors.append(f"persona-visible system context field missing: {required_context}")
|
||||
baseline = json.loads((ROOT / "contracts/clean-v1-execution-baseline.json").read_text())
|
||||
if baseline.get("anchor_manifest_sha256") != "7e130de78f91a32726e22e4be7d92acf4da966c8968ec359062aa8186c4243c2":
|
||||
errors.append("current direct-language anchor manifest drift")
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use tauri_plugin_dialog::DialogExt;
|
|||
const UPDATE_ENDPOINT: &str = "https://guanghulab.com/hololake/releases/latest.json";
|
||||
const PUBLIC_STATE: &str = "SIGNED_UPDATE_FEED_READY_NO_RELEASE";
|
||||
|
||||
fn bundled_modules() -> Result<Vec<ModuleRecord>, String> {
|
||||
pub(crate) fn bundled_modules() -> Result<Vec<ModuleRecord>, String> {
|
||||
let registry: serde_json::Value =
|
||||
serde_json::from_str(include_str!("../../registries/module-registry.json"))
|
||||
.map_err(|error| format!("MODULE_REGISTRY_INVALID: {error}"))?;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{agent_executor, model::SourceKind, persona_runtime, storage};
|
||||
use crate::{agent_executor, enterprise_entrance, model::SourceKind, persona_runtime, storage};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::{json, Value};
|
||||
#[cfg(unix)]
|
||||
|
|
@ -223,6 +223,47 @@ fn send(writer: &mut TcpStream, value: Value) -> Result<(), String> {
|
|||
writer.flush().map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
fn system_context(app: &AppHandle) -> Result<Value, String> {
|
||||
let channel = storage::channel(app)?;
|
||||
let persona = persona_runtime::snapshot(app)?;
|
||||
let enterprise = enterprise_entrance::snapshot(app)?;
|
||||
let proposals = agent_executor::list(app)?;
|
||||
let modules = crate::bundled_modules()?;
|
||||
Ok(json!({
|
||||
"type": "system_context",
|
||||
"schema": "hololake.persona-visible-system-context/v1",
|
||||
"recordedAt": storage::now(),
|
||||
"channel": channel.map(|value| json!({"channelId":value.channel_id,"name":value.name})),
|
||||
"persona": {
|
||||
"state": persona.state,
|
||||
"activePersonaId": persona.active_persona_id,
|
||||
"verifiedExistingPersonaCount": persona.verified_existing_persona_count
|
||||
},
|
||||
"modules": modules.into_iter().map(|module| json!({
|
||||
"moduleId":module.module_id,
|
||||
"nameZh":module.name_zh,
|
||||
"audience":module.audience,
|
||||
"state":module.state
|
||||
})).collect::<Vec<_>>(),
|
||||
"enterpriseEntrance": {
|
||||
"state": enterprise.state,
|
||||
"serverAuthorized": enterprise.server_authorized,
|
||||
"enterpriseServerEmbedded": enterprise.enterprise_server_embedded
|
||||
},
|
||||
"pendingAgentProposals": proposals.into_iter()
|
||||
.filter(|proposal| proposal.state == "PENDING_HUMAN_APPROVAL")
|
||||
.map(|proposal| json!({"proposalId":proposal.proposal_id,"programId":proposal.gir.program_id,"state":proposal.state}))
|
||||
.collect::<Vec<_>>(),
|
||||
"sourceKinds": ["USER_MESSAGE","PERSONA_RESPONSE","EXTERNAL_AI_MESSAGE","SYSTEM_CONTEXT","PROTOCOL_EVENT","AGENT_ACTION","TOOL_RESULT","SYSTEM_RECEIPT"],
|
||||
"boundaries": {
|
||||
"transportGrantsPersona": false,
|
||||
"transportGrantsExecution": false,
|
||||
"systemReceiptIsNotPersonaSpeech": true,
|
||||
"proposalIsNotExecution": true
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
fn handle_connection(
|
||||
app: AppHandle,
|
||||
state: RealtimeBridgeState,
|
||||
|
|
@ -280,6 +321,7 @@ fn handle_connection(
|
|||
&mut writer,
|
||||
json!({"type":"welcome","protocol":PROTOCOL,"bridgeId":hello.bridge_id,"personaId":hello.persona_id,"personaState":if hello.persona_id.is_some(){"LOCAL_TRIAL_UNVERIFIED_HOST_CONNECTED"}else{"EXTERNAL_AI_CONNECTED_NO_PERSONA"},"executionAuthority":false}),
|
||||
)?;
|
||||
send(&mut writer, system_context(&app)?)?;
|
||||
let (tx, rx) = mpsc::channel::<String>();
|
||||
state
|
||||
.clients
|
||||
|
|
|
|||
Loading…
Reference in a new issue