Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11), free to diverge. Tree copied sans upstream .git; upstream remote added for future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19. Preserves docs/ARCHITECTURE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
257 lines
7.7 KiB
Swift
257 lines
7.7 KiB
Swift
import Foundation
|
|
import OpenClawKit
|
|
import SwiftUI
|
|
|
|
private struct OpenClawChatPreviewTransport: OpenClawChatTransport {
|
|
enum Scenario {
|
|
case connected
|
|
case empty
|
|
case loading
|
|
case error
|
|
}
|
|
|
|
let scenario: Scenario
|
|
|
|
init(scenario: Scenario = .connected) {
|
|
self.scenario = scenario
|
|
}
|
|
|
|
func requestHistory(sessionKey: String) async throws -> OpenClawChatHistoryPayload {
|
|
switch self.scenario {
|
|
case .connected:
|
|
break
|
|
case .empty:
|
|
return OpenClawChatHistoryPayload(
|
|
sessionKey: sessionKey,
|
|
sessionId: "preview-empty-session",
|
|
messages: [],
|
|
thinkingLevel: "medium")
|
|
case .loading:
|
|
try await Task.sleep(nanoseconds: 60_000_000_000)
|
|
return OpenClawChatHistoryPayload(
|
|
sessionKey: sessionKey,
|
|
sessionId: "preview-loading-session",
|
|
messages: [],
|
|
thinkingLevel: "medium")
|
|
case .error:
|
|
throw NSError(
|
|
domain: "OpenClawChatPreviewTransport",
|
|
code: 1,
|
|
userInfo: [NSLocalizedDescriptionKey: "Gateway not connected. Check Tailscale and retry."])
|
|
}
|
|
|
|
return OpenClawChatHistoryPayload(
|
|
sessionKey: sessionKey,
|
|
sessionId: "preview-session",
|
|
messages: [
|
|
Self.message(
|
|
role: "user",
|
|
text: "Can you check the gateway status and summarize anything risky?",
|
|
timestamp: 1),
|
|
Self.message(
|
|
role: "assistant",
|
|
text: "Gateway is reachable. The only notable item is that push relay is still using local distribution, so device tests should stay on the local lane.",
|
|
timestamp: 2),
|
|
Self.toolCall(
|
|
id: "tool-preview-1",
|
|
name: "gateway.status",
|
|
arguments: ["deep": AnyCodable(true)],
|
|
timestamp: 3),
|
|
Self.toolResult(
|
|
toolCallId: "tool-preview-1",
|
|
name: "gateway.status",
|
|
text: "status=ok, channels=ios,macos, lastHeartbeat=12s",
|
|
timestamp: 4),
|
|
],
|
|
thinkingLevel: "medium")
|
|
}
|
|
|
|
func listModels() async throws -> [OpenClawChatModelChoice] {
|
|
[
|
|
OpenClawChatModelChoice(
|
|
modelID: "gpt-5.5",
|
|
name: "GPT-5.5",
|
|
provider: "openai",
|
|
contextWindow: 400_000),
|
|
OpenClawChatModelChoice(
|
|
modelID: "sonnet-4.6",
|
|
name: "Claude Sonnet 4.6",
|
|
provider: "anthropic",
|
|
contextWindow: 200_000),
|
|
]
|
|
}
|
|
|
|
func sendMessage(
|
|
sessionKey _: String,
|
|
message _: String,
|
|
thinking _: String,
|
|
idempotencyKey: String,
|
|
attachments _: [OpenClawChatAttachmentPayload]) async throws -> OpenClawChatSendResponse
|
|
{
|
|
OpenClawChatSendResponse(runId: idempotencyKey, status: "ok")
|
|
}
|
|
|
|
func listSessions(limit _: Int?) async throws -> OpenClawChatSessionsListResponse {
|
|
OpenClawChatSessionsListResponse(
|
|
ts: 0,
|
|
path: nil,
|
|
count: 2,
|
|
defaults: OpenClawChatSessionsDefaults(
|
|
modelProvider: "openai",
|
|
model: "gpt-5.5",
|
|
contextTokens: 400_000,
|
|
thinkingLevels: [
|
|
OpenClawChatThinkingLevelOption(id: "off", label: "off"),
|
|
OpenClawChatThinkingLevelOption(id: "medium", label: "medium"),
|
|
OpenClawChatThinkingLevelOption(id: "high", label: "high"),
|
|
],
|
|
thinkingDefault: "medium",
|
|
mainSessionKey: "main"),
|
|
sessions: [
|
|
Self.session(key: "main", displayName: "Main", updatedAt: 2),
|
|
Self.session(key: "ios-preview", displayName: "iOS preview", updatedAt: 1),
|
|
])
|
|
}
|
|
|
|
func requestHealth(timeoutMs _: Int) async throws -> Bool {
|
|
switch self.scenario {
|
|
case .connected, .empty, .loading:
|
|
true
|
|
case .error:
|
|
false
|
|
}
|
|
}
|
|
|
|
func events() -> AsyncStream<OpenClawChatTransportEvent> {
|
|
AsyncStream { continuation in
|
|
continuation.finish()
|
|
}
|
|
}
|
|
|
|
func setActiveSessionKey(_: String) async throws {}
|
|
|
|
private static func message(role: String, text: String, timestamp: Double) -> AnyCodable {
|
|
AnyCodable([
|
|
"role": role,
|
|
"content": [["type": "text", "text": text]],
|
|
"timestamp": timestamp,
|
|
])
|
|
}
|
|
|
|
private static func toolCall(
|
|
id: String,
|
|
name: String,
|
|
arguments: [String: AnyCodable],
|
|
timestamp: Double) -> AnyCodable
|
|
{
|
|
AnyCodable([
|
|
"role": "assistant",
|
|
"content": [
|
|
[
|
|
"type": "toolCall",
|
|
"id": id,
|
|
"name": name,
|
|
"arguments": AnyCodable(arguments),
|
|
],
|
|
],
|
|
"timestamp": timestamp,
|
|
])
|
|
}
|
|
|
|
private static func toolResult(
|
|
toolCallId: String,
|
|
name: String,
|
|
text: String,
|
|
timestamp: Double) -> AnyCodable
|
|
{
|
|
AnyCodable([
|
|
"role": "tool",
|
|
"content": [["type": "text", "text": text]],
|
|
"timestamp": timestamp,
|
|
"toolCallId": toolCallId,
|
|
"toolName": name,
|
|
])
|
|
}
|
|
|
|
private static func session(
|
|
key: String,
|
|
displayName: String,
|
|
updatedAt: Double) -> OpenClawChatSessionEntry
|
|
{
|
|
OpenClawChatSessionEntry(
|
|
key: key,
|
|
kind: nil,
|
|
displayName: displayName,
|
|
surface: "ios",
|
|
subject: nil,
|
|
room: nil,
|
|
space: nil,
|
|
updatedAt: updatedAt,
|
|
sessionId: nil,
|
|
systemSent: nil,
|
|
abortedLastRun: nil,
|
|
thinkingLevel: "medium",
|
|
verboseLevel: nil,
|
|
inputTokens: 2500,
|
|
outputTokens: 900,
|
|
totalTokens: 3400,
|
|
modelProvider: "openai",
|
|
model: "gpt-5.5",
|
|
contextTokens: 400_000)
|
|
}
|
|
}
|
|
|
|
#Preview("Chat") {
|
|
OpenClawChatPreview(scenario: .connected)
|
|
}
|
|
|
|
#Preview("Chat connected") {
|
|
OpenClawChatPreview(scenario: .connected)
|
|
}
|
|
|
|
#Preview("Chat empty") {
|
|
OpenClawChatPreview(
|
|
scenario: .empty,
|
|
sessionKey: "empty-preview")
|
|
}
|
|
|
|
#Preview("Chat loading") {
|
|
OpenClawChatPreview(
|
|
scenario: .loading,
|
|
sessionKey: "loading-preview")
|
|
}
|
|
|
|
#Preview("Chat gateway error") {
|
|
OpenClawChatPreview(
|
|
scenario: .error,
|
|
sessionKey: "error-preview")
|
|
}
|
|
|
|
#Preview("Onboarding chat") {
|
|
OpenClawChatView(
|
|
viewModel: OpenClawChatViewModel(
|
|
sessionKey: "ios-preview",
|
|
transport: OpenClawChatPreviewTransport()),
|
|
showsSessionSwitcher: false,
|
|
style: .onboarding,
|
|
markdownVariant: .standard,
|
|
userAccent: OpenClawChatTheme.accent)
|
|
}
|
|
|
|
private struct OpenClawChatPreview: View {
|
|
let scenario: OpenClawChatPreviewTransport.Scenario
|
|
var sessionKey: String = "main"
|
|
|
|
var body: some View {
|
|
OpenClawChatView(
|
|
viewModel: OpenClawChatViewModel(
|
|
sessionKey: self.sessionKey,
|
|
transport: OpenClawChatPreviewTransport(scenario: self.scenario)),
|
|
showsSessionSwitcher: true,
|
|
style: .standard,
|
|
markdownVariant: .standard,
|
|
userAccent: OpenClawChatTheme.accent,
|
|
showsAssistantTrace: true)
|
|
}
|
|
}
|