Vendor OpenClaw source as Adolf fork baseline
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
This commit is contained in:
2026-07-05 09:36:54 +00:00
parent 3216769225
commit bedb527145
21108 changed files with 6010766 additions and 0 deletions

View File

@@ -0,0 +1,260 @@
import Foundation
import Observation
import OpenClawKit
import OpenClawProtocol
import SwiftUI
@MainActor
@Observable
final class WorkActivityStore {
static let shared = WorkActivityStore()
struct Activity: Equatable {
let sessionKey: String
let role: SessionRole
let kind: ActivityKind
let label: String
let startedAt: Date
var lastUpdate: Date
}
private(set) var current: Activity?
private(set) var iconState: IconState = .idle
private(set) var lastToolLabel: String?
private(set) var lastToolUpdatedAt: Date?
private var jobs: [String: Activity] = [:]
private var tools: [String: Activity] = [:]
private var currentSessionKey: String?
private var toolSeqBySession: [String: Int] = [:]
private var mainSessionKeyStorage = "main"
private let toolResultGrace: TimeInterval = 2.0
var mainSessionKey: String {
self.mainSessionKeyStorage
}
func handleJob(sessionKey: String, state: String) {
let isStart = state.lowercased() == "started" || state.lowercased() == "streaming"
if isStart {
let activity = Activity(
sessionKey: sessionKey,
role: self.role(for: sessionKey),
kind: .job,
label: "job",
startedAt: Date(),
lastUpdate: Date())
self.setJobActive(activity)
} else {
// Job ended (done/error/aborted/etc). Clear everything for this session.
self.clearTool(sessionKey: sessionKey)
self.clearJob(sessionKey: sessionKey)
}
}
func handleTool(
sessionKey: String,
phase: String,
name: String?,
meta: String?,
args: [String: OpenClawProtocol.AnyCodable]?)
{
let toolKind = Self.mapToolKind(name)
let label = Self.buildLabel(name: name, meta: meta, args: args)
if phase.lowercased() == "start" {
self.lastToolLabel = label
self.lastToolUpdatedAt = Date()
self.toolSeqBySession[sessionKey, default: 0] += 1
let activity = Activity(
sessionKey: sessionKey,
role: self.role(for: sessionKey),
kind: .tool(toolKind),
label: label,
startedAt: Date(),
lastUpdate: Date())
self.setToolActive(activity)
} else {
// Delay removal slightly to avoid flicker on rapid result/start bursts.
let key = sessionKey
let seq = self.toolSeqBySession[key, default: 0]
Task { [weak self] in
let nsDelay = UInt64((self?.toolResultGrace ?? 0) * 1_000_000_000)
try? await Task.sleep(nanoseconds: nsDelay)
await MainActor.run {
guard let self else { return }
guard self.toolSeqBySession[key, default: 0] == seq else { return }
self.lastToolUpdatedAt = Date()
self.clearTool(sessionKey: key)
}
}
}
}
func resolveIconState(override selection: IconOverrideSelection) {
switch selection {
case .system:
self.iconState = self.deriveIconState()
case .idle:
self.iconState = .idle
default:
let base = selection.toIconState()
switch base {
case let .workingMain(kind),
let .workingOther(kind):
self.iconState = .overridden(kind)
case let .overridden(kind):
self.iconState = .overridden(kind)
case .idle:
self.iconState = .idle
}
}
}
private func setJobActive(_ activity: Activity) {
self.jobs[activity.sessionKey] = activity
self.updateCurrentSession(with: activity)
}
private func setToolActive(_ activity: Activity) {
self.tools[activity.sessionKey] = activity
self.updateCurrentSession(with: activity)
}
private func updateCurrentSession(with activity: Activity) {
// Main session preempts immediately.
if activity.role == .main {
self.currentSessionKey = activity.sessionKey
} else if self.currentSessionKey == nil || !self.isActive(sessionKey: self.currentSessionKey!) {
self.currentSessionKey = activity.sessionKey
}
self.refreshDerivedState()
}
func setMainSessionKey(_ sessionKey: String) {
let trimmed = sessionKey.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty else { return }
guard trimmed != self.mainSessionKeyStorage else { return }
self.mainSessionKeyStorage = trimmed
if let current = self.currentSessionKey, !self.isActive(sessionKey: current) {
self.pickNextSession()
}
self.refreshDerivedState()
}
private func clearJob(sessionKey: String) {
guard self.jobs[sessionKey] != nil else { return }
self.jobs.removeValue(forKey: sessionKey)
if self.currentSessionKey == sessionKey, !self.isActive(sessionKey: sessionKey) {
self.pickNextSession()
}
self.refreshDerivedState()
}
private func clearTool(sessionKey: String) {
guard self.tools[sessionKey] != nil else { return }
self.tools.removeValue(forKey: sessionKey)
if self.currentSessionKey == sessionKey, !self.isActive(sessionKey: sessionKey) {
self.pickNextSession()
}
self.refreshDerivedState()
}
private func pickNextSession() {
// Prefer main if present.
if self.isActive(sessionKey: self.mainSessionKeyStorage) {
self.currentSessionKey = self.mainSessionKeyStorage
return
}
// Otherwise, pick most recent by lastUpdate across job/tool.
let keys = Set(self.jobs.keys).union(self.tools.keys)
let next = keys.max(by: { self.lastUpdate(for: $0) < self.lastUpdate(for: $1) })
self.currentSessionKey = next
}
private func role(for sessionKey: String) -> SessionRole {
sessionKey == self.mainSessionKeyStorage ? .main : .other
}
private func isActive(sessionKey: String) -> Bool {
self.jobs[sessionKey] != nil || self.tools[sessionKey] != nil
}
private func lastUpdate(for sessionKey: String) -> Date {
max(self.jobs[sessionKey]?.lastUpdate ?? .distantPast, self.tools[sessionKey]?.lastUpdate ?? .distantPast)
}
private func currentActivity(for sessionKey: String) -> Activity? {
// Prefer tool overlay if present, otherwise job.
self.tools[sessionKey] ?? self.jobs[sessionKey]
}
private func refreshDerivedState() {
if let key = self.currentSessionKey, !self.isActive(sessionKey: key) {
self.currentSessionKey = nil
}
self.current = self.currentSessionKey.flatMap { self.currentActivity(for: $0) }
self.iconState = self.deriveIconState()
}
private func deriveIconState() -> IconState {
guard let sessionKey = self.currentSessionKey,
let activity = self.currentActivity(for: sessionKey)
else { return .idle }
switch activity.role {
case .main: return .workingMain(activity.kind)
case .other: return .workingOther(activity.kind)
}
}
private static func mapToolKind(_ name: String?) -> ToolKind {
switch name?.lowercased() {
case "bash", "shell": .bash
case "read": .read
case "write": .write
case "edit": .edit
case "attach": .attach
default: .other
}
}
private static func buildLabel(
name: String?,
meta: String?,
args: [String: OpenClawProtocol.AnyCodable]?) -> String
{
let wrappedArgs = self.wrapToolArgs(args)
let display = ToolDisplayRegistry.resolve(name: name ?? "tool", args: wrappedArgs, meta: meta)
if let detail = display.detailLine, !detail.isEmpty {
return "\(display.label): \(detail)"
}
return display.label
}
private static func wrapToolArgs(_ args: [String: OpenClawProtocol.AnyCodable]?) -> OpenClawKit.AnyCodable? {
guard let args else { return nil }
let converted: [String: Any] = args.mapValues { self.unwrapJSONValue($0.value) }
return OpenClawKit.AnyCodable(converted)
}
private static func unwrapJSONValue(_ value: Any) -> Any {
if let dict = value as? [String: OpenClawProtocol.AnyCodable] {
return dict.mapValues { self.unwrapJSONValue($0.value) }
}
if let array = value as? [OpenClawProtocol.AnyCodable] {
return array.map { self.unwrapJSONValue($0.value) }
}
if let dict = value as? [String: Any] {
return dict.mapValues { self.unwrapJSONValue($0) }
}
if let array = value as? [Any] {
return array.map { self.unwrapJSONValue($0) }
}
return value
}
}