feat: add tiered channel agent and mobile Codex bridge
This commit is contained in:
parent
950b7e48b3
commit
71db11e7e8
35 changed files with 2242 additions and 76 deletions
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue