feat: add tiered channel agent and mobile Codex bridge

This commit is contained in:
冰朔 2026-08-21 08:21:03 +08:00
commit 71db11e7e8
35 changed files with 2242 additions and 76 deletions

View file

@ -6,6 +6,8 @@ struct ContentView: View {
@State private var pairingText = ""
@State private var captureTitle = ""
@State private var captureBody = ""
@State private var agentDraft = ""
@State private var agentDestination = "HOLOLAKE_AGENT"
var body: some View {
NavigationStack {
@ -133,6 +135,89 @@ struct ContentView: View {
}
}
LakeCard {
VStack(alignment: .leading, spacing: 12) {
HStack {
VStack(alignment: .leading, spacing: 3) {
Text("与电脑端 HoloLake 对话").font(.headline)
Text("回复与工具均由已配对的电脑根节点执行")
.font(.caption)
.foregroundStyle(HoloLakeDesign.muted)
}
Spacer()
if let exchange = client.snapshot?.agentExchange {
Text(exchange.personaBindingState == "BOUND_VERIFY_PASS" ? "人格已绑定" : "系统频道")
.font(.caption2.weight(.semibold))
.foregroundStyle(exchange.personaBindingState == "BOUND_VERIFY_PASS" ? HoloLakeDesign.mint : HoloLakeDesign.gold)
}
}
Picker("消息目标", selection: $agentDestination) {
Text("HoloLake Agent").tag("HOLOLAKE_AGENT")
if let target = client.snapshot?.codexTarget {
Text("Codex · \(target.name)").tag("CODEX_SELECTED_THREAD")
}
}
.pickerStyle(.segmented)
if agentDestination == "CODEX_SELECTED_THREAD" {
Text("Codex 任务以只读沙箱运行;需要命令、改文件或额外权限时,必须回到电脑端确认。")
.font(.caption)
.foregroundStyle(HoloLakeDesign.gold)
}
if let exchange = client.snapshot?.agentExchange {
VStack(alignment: .leading, spacing: 8) {
Text(exchange.responderName)
.font(.caption.weight(.semibold))
.foregroundStyle(HoloLakeDesign.mint)
Text(exchange.reply)
.font(.body)
.textSelection(.enabled)
if !exchange.toolReceipts.isEmpty {
Divider().overlay(.white.opacity(0.12))
ForEach(exchange.toolReceipts) { receipt in
Label(receipt.summary, systemImage: "checkmark.seal")
.font(.caption)
.foregroundStyle(HoloLakeDesign.muted)
}
}
}
.padding(13)
.background(.black.opacity(0.18), in: RoundedRectangle(cornerRadius: 14))
}
TextField("给电脑端 HoloLake 发送消息", text: $agentDraft, axis: .vertical)
.lineLimit(3...8)
.padding(12)
.background(.black.opacity(0.2), in: RoundedRectangle(cornerRadius: 14))
Button {
let content = agentDraft
Task {
await client.sendAgentMessage(content, destination: agentDestination)
if client.errorText == nil {
agentDraft = ""
}
}
} label: {
if client.isWorking {
ProgressView()
} else {
Label("发送到电脑端", systemImage: "arrow.up.circle.fill")
}
}
.buttonStyle(.borderedProminent)
.tint(HoloLakeDesign.gold)
.foregroundStyle(HoloLakeDesign.deep)
.disabled(
agentDraft.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|| client.isWorking
|| (agentDestination == "CODEX_SELECTED_THREAD" && client.snapshot?.codexTarget == nil)
)
}
}
LakeCard {
VStack(alignment: .leading, spacing: 12) {
Text("随手记回频道").font(.headline)
@ -200,4 +285,3 @@ struct ContentView: View {
.padding(.horizontal, 4)
}
}