feat(hololake): establish clean v1 personal language shell

This commit is contained in:
冰朔 2026-09-03 15:35:33 +08:00
commit c4f662e541
51 changed files with 16233 additions and 1 deletions

View file

@ -0,0 +1,53 @@
import { invoke } from "@tauri-apps/api/core";
import type { Channel, ExternalAiBridge, KnowledgeDocument, MutationReceipt, SystemSnapshot, TimelineEvent } from "./types";
const tauri = () => "__TAURI_INTERNALS__" in window;
const now = () => new Date().toISOString();
const key = "hololake.clean.browser-state.v1";
type BrowserState = { channel: Channel | null; timeline: TimelineEvent[]; documents: KnowledgeDocument[]; bridges: ExternalAiBridge[] };
const empty: BrowserState = { channel: null, timeline: [], documents: [], bridges: [] };
const load = (): BrowserState => JSON.parse(localStorage.getItem(key) ?? JSON.stringify(empty));
const save = (state: BrowserState) => localStorage.setItem(key, JSON.stringify(state));
const event = (sourceKind: TimelineEvent["sourceKind"], title: string, content: string, state: TimelineEvent["state"] = "SUCCEEDED"): TimelineEvent => ({ eventId: crypto.randomUUID(), sourceKind, title, content, occurredAt: now(), state });
export async function snapshot(): Promise<SystemSnapshot> {
if (tauri()) return invoke("system_snapshot");
const s = load();
return { appVersion: "1.0.0-browser", channel: s.channel, timeline: s.timeline, documents: s.documents.map(({ path, title, updatedAt, sha256 }) => ({ path, title, updatedAt, sha256 })), moduleRegistryVersion: "1", publicUpdateEndpoint: "https://guanghulab.com/hololake/releases/latest.json", publicDistributionState: "SIGNED_UPDATE_FEED_READY_NO_RELEASE", externalAiBridges: s.bridges };
}
export async function createChannel(name: string): Promise<Channel> {
if (tauri()) return invoke("create_channel", { name });
const s = load(); const channel: Channel = { channelId: `HL-CH-${crypto.randomUUID().slice(0,8).toUpperCase()}`, name, createdAt: now(), privateGitPath: "浏览器预览不写入磁盘", publicDistributionState: "SIGNED_UPDATE_FEED_READY_NO_RELEASE" };
s.channel = channel; s.timeline.unshift(event("SYSTEM_RECEIPT", "频道已建立", `${channel.channelId} 已登记。`)); save(s); return channel;
}
export async function submitMessage(content: string): Promise<MutationReceipt> {
if (tauri()) return invoke("submit_user_message", { content });
const s = load(); const e = event("USER_MESSAGE", "用户语言", content, "RECORDED"); s.timeline.unshift(e, event("SYSTEM_RECEIPT", "系统回执", "用户语言已分流保存;等待人格体接入,不伪造人格回应。", "WAITING")); save(s);
return { receiptId: crypto.randomUUID(), state: "WAITING_PERSONA", message: "用户语言已记录", gitCommit: null, event: e };
}
export async function readDocument(path: string): Promise<KnowledgeDocument> {
if (tauri()) return invoke("read_knowledge_document", { path });
const doc = load().documents.find(d => d.path === path); if (!doc) throw new Error("文档不存在"); return doc;
}
export async function createDocument(title: string): Promise<MutationReceipt> {
if (tauri()) return invoke("create_knowledge_document", { title });
const s = load(); const path = `${title.trim().replace(/[\\/:*?\"<>|]/g,"-")}.md`; const d = { path, title: title.trim(), body: `# ${title.trim()}\n\n`, updatedAt: now(), sha256: "browser-preview" }; s.documents.unshift(d); const e=event("AGENT_ACTION","Agent 执行",`已创建 ${path}`); s.timeline.unshift(e); save(s); return {receiptId:crypto.randomUUID(),state:"SUCCEEDED",message:"文档已创建",gitCommit:"browser-preview",event:e};
}
export async function saveDocument(path: string, body: string): Promise<MutationReceipt> {
if (tauri()) return invoke("save_knowledge_document", { path, body });
const s=load(); const d=s.documents.find(x=>x.path===path); if(!d) throw new Error("文档不存在"); d.body=body; d.updatedAt=now(); const e=event("SYSTEM_RECEIPT","系统回执",`${path} 已保存到私人 Git 预览层。`); s.timeline.unshift(e); save(s); return {receiptId:crypto.randomUUID(),state:"SUCCEEDED",message:"保存完成",gitCommit:"browser-preview",event:e};
}
export async function deleteDocument(path: string): Promise<MutationReceipt> {
if (tauri()) return invoke("delete_knowledge_document", { path });
const s=load(); s.documents=s.documents.filter(x=>x.path!==path); const e=event("SYSTEM_RECEIPT","系统回执",`${path} 已移入回收站。`); s.timeline.unshift(e); save(s); return {receiptId:crypto.randomUUID(),state:"SUCCEEDED",message:"已移入回收站",gitCommit:"browser-preview",event:e};
}
export async function importFolder(): Promise<MutationReceipt | null> { if (!tauri()) throw new Error("文件夹导入请在已安装的 HoloLake 中使用"); return invoke("import_knowledge_folder"); }
export async function exportDocument(path: string): Promise<string | null> { if (!tauri()) throw new Error("下载请在已安装的 HoloLake 中使用"); return invoke("export_knowledge_document", { path }); }
export async function registerBridge(displayName: string): Promise<ExternalAiBridge> {
if (tauri()) return invoke("register_external_ai_bridge", { displayName });
const s=load(); const b={bridgeId:`HL-AI-${crypto.randomUUID().slice(0,8).toUpperCase()}`,displayName,inboxPath:"浏览器预览",outboxPath:"浏览器预览",state:"LOCAL_EXPRESSION_ONLY"}; s.bridges.push(b); save(s); return b;
}