Files
HomeAgent/cmd/ohos/HologramAgent/entry/src/main/ets/common/BridgeProtocol.ets
JianFeeeee f256098c9f refactor: 全面改名为 HologramAgent + 提示词技术内容下沉到 skill/工具描述 + 修 21 处乱码
## ① 全面改名 HomeAgent → HologramAgent

仓库已改名,但代码与文档里仍有大量旧名。本次按"用户能看到的优先"全量替换:

- 用户可见:登录页标题/页脚、默认人格第一句、CLI 状态输出、启动日志、
  plugin_install 的工具描述、AI 图片插件的 User-Agent
- 文档与脚本:README、assets/docs、docs/zh、deploy/*.sh、.github/workflows
- 鸿蒙工程:cmd/ohos/HomeAgent → cmd/ohos/HologramAgent(git mv)
  目录内的 module/app 描述同步;**证书路径原样保留**
  (default_HomeAgent_xxx.cer/p7b/p12 是签名材料的实际文件名,改了会找不到证书)
- 插件元数据:plugin.json 的 author

★ 必须保持原样的两处(改了会坏):
  · legacySeededPromptSignature = "你是 HomeAgent 的看板娘「小宅」…"
    —— 那是识别历史播种人格卡的**原文锚点**,改了就识别不出旧数据
  · 公开 SDK 的 ProxyAuthHomeAgent = "homeagent"
    —— 那是 SDK 契约里的值,属独立仓库,本仓不改

## ② 修 21 处乱码(U+FFFD)

这些是历史编辑留下的编码破坏,全在注释里,例如:
  「赌注重下���遍」→「赌注重下一遍」
  「「不��滤」」  →「「不过滤」」
  「**待��退场**」→「**待退场**」

★ 保留 providers/chineseclip/tokenizer.go 里的 2 处:那是**故意**用
  U+FFFD 演示"非法 UTF-8 字节被归一成 U+FFFD",不是乱码。

## ③ 提示词技术内容下沉(用户:技术性内容应该收敛到 skill 与 -help 中)

实测系统提示词 2309 字,其中两段几乎全是**模型无法据以行动的实现细节**:

  【工具执行顺序】1272 字(ParallelSafe 声明、批内降级、batchRunnable 判据…)
  【三层记忆】   1069 字(L1/L2/L3 编号、消费式删除、向量空间、指纹…)

收敛后 **2309 → 1723 字(-25%)**,保留的全是"模型据此做什么不同的事":

  工具顺序:默认并行 / 不要依赖先后 / 同通道保序 / 写类工具可能串行
  三层记忆:时序里能看最近 / doc_query 把历史事件按原始时间戳插回时序 /
           关系用 memory_recall / 成文知识用 knowledge_search

判断口径写进判据:新加一段提示词前先问"模型会据此做什么不同的事",
答不上来就该进 skill 或工具描述。

## 判据

prompt_memory_test.go 新增 2 条:
- TestSystemPromptHasNoImplementationJargon
  黑名单:ParallelSafe / batchRunnable / 消费式 / DenseCosine / fingerprint /
  向量空间 / 批内降级 / 自激
- TestSystemPromptStaysCompact:上限 2000 字(当前 1723)

变异:把 "ParallelSafe 声明、批内降级" 加回工具顺序段 ⇒ 第一条立刻红。

## 验证

- go build ./... / go vet ./... 干净
- go test ./... -count=1:58 包 0 失败
- make check-client-versions:客户端与内核版本一致
2026-10-22 20:49:44 +08:00

174 lines
4.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* 设备桥协议:消息结构、帧构造与分块切片。
*
* 与 homed 的 remotedevice 插件对齐(internal/plugins/remotedevice)。
* 从 common/DeviceBridge.ets 抽出:这里只有"协议形状"和"帧怎么拼",
* 没有任何 socket、状态机与重连逻辑 —— 那些留在 DeviceBridgeClient 里。
*
* 注意:DeviceBridgeClient 的对外方法名与语义不因本文件而改变,
* 各 send* 方法仍是"拼帧 + 发出去"两步,只是第一步搬到了这里。
*/
import { CapResult } from './BridgeCaps';
import { appVersion } from './AppVersion';
// ===== 协议消息(与 remotedevice 插件对齐)=====
export interface HelloDeviceInfo {
hostname: string;
platform: string;
arch: string;
os_release: string;
version: string;
cpus: number;
}
export interface HelloDevice {
device_id: string;
name: string;
kind: string;
authorized: boolean;
caps: string[];
info: HelloDeviceInfo;
}
export interface HelloMessage {
op: string;
device: HelloDevice;
}
export interface BindMessage {
op: string;
device_id: string;
token: string;
}
export interface CmdReply {
op: string; // 'cmd_result'
req_id: string;
status: string;
output: string;
error: string;
}
export interface DataStartMessage {
op: string;
req_id: string;
kind: string;
mime: string;
total: number;
chunk_size: number;
}
export interface DataEndMessage {
op: string;
req_id: string;
status: string;
total?: number;
error?: string;
}
export const CHUNK_SIZE: number = 8192;
// ===== 命令处理器回调 =====
// 返回 CapResult;二进制大结果通过 dataHandler 分块回传。
export type BridgeCmdHandler = (reqId: string, command: string) => Promise<CapResult>;
// ===== 帧构造 =====
export function bridgeHelloFrame(deviceId: string, name: string, kind: string,
caps: string[], hostname: string,
authorized: boolean): string {
const info: HelloDeviceInfo = {
hostname: hostname,
platform: 'OpenHarmony',
arch: '',
os_release: '',
version: appVersion(),
cpus: 0,
};
const device: HelloDevice = {
device_id: deviceId,
name: name,
kind: kind,
authorized: authorized,
caps: caps,
info: info,
};
const hello: HelloMessage = { op: 'hello', device: device };
return JSON.stringify(hello);
}
export function bridgeBindFrame(deviceId: string, token: string): string {
const bind: BindMessage = {
op: 'bind',
device_id: deviceId,
token: token,
};
return JSON.stringify(bind);
}
export function bridgeResultFrame(reqId: string, status: string,
output: string, errMsg: string): string {
const result: CmdReply = {
op: 'cmd_result',
req_id: reqId,
status: status,
output: output,
error: errMsg,
};
return JSON.stringify(result);
}
export function bridgeDataStartFrame(reqId: string, kind: string, mime: string,
total: number): string {
const startMsg: DataStartMessage = {
op: 'cmd_data_start',
req_id: reqId,
kind: kind,
mime: mime,
total: total,
chunk_size: CHUNK_SIZE,
};
return JSON.stringify(startMsg);
}
export function bridgeDataEndFrame(reqId: string): string {
const endMsg: DataEndMessage = {
op: 'cmd_data_end',
req_id: reqId,
status: 'ok',
};
return JSON.stringify(endMsg);
}
export function bridgeEventFrame(deviceId: string, eventType: string, detail: string): string {
const payload: Record<string, string> = { 'detail': detail };
const msg: Record<string, Object> = {
'op': 'event',
'device_id': deviceId,
'type': eventType,
'payload': payload,
};
return JSON.stringify(msg);
}
export function bridgeStatusFrame(deviceId: string, status: string): string {
const msg: Record<string, Object> = {
'op': 'status',
'device_id': deviceId,
'status': status,
};
return JSON.stringify(msg);
}
/** 按 CHUNK_SIZE 切二进制;切片顺序即发送顺序。 */
export function bridgeChunkSlices(bytes: Uint8Array): Uint8Array[] {
const out: Uint8Array[] = [];
for (let off: number = 0; off < bytes.byteLength; off += CHUNK_SIZE) {
const end: number = Math.min(off + CHUNK_SIZE, bytes.byteLength);
out.push(bytes.slice(off, end));
}
return out;
}