Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,27 @@ permissions:
contents: read

jobs:
swiftlint:
name: SwiftLint
runs-on: macos-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Select latest Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest

- name: Install SwiftLint
run: brew install swiftlint

- name: Print SwiftLint version
run: swiftlint version

- name: Lint Swift sources
run: Scripts/lint-swift.sh

swift-validation:
name: Swift Validation
runs-on: ubuntu-latest
Expand Down
60 changes: 60 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
name: Documentation

on:
push:
branches:
- main
pull_request:

concurrency:
group: docs-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true

jobs:
docc-site:
name: Build DocC Site
runs-on: macos-latest
permissions:
contents: read
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Select latest Xcode
uses: maxim-lobanov/setup-xcode@v1
with:
xcode-version: latest

- name: Print Xcode and Swift versions
run: |
xcodebuild -version
xcrun swift --version

- name: Build DocC site
run: Scripts/build-docs-site.sh

- name: Upload GitHub Pages artifact
uses: actions/upload-pages-artifact@v3
with:
path: .build/docc-static-site

deploy:
name: Deploy GitHub Pages
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
needs: docc-site
runs-on: ubuntu-latest
permissions:
pages: write
id-token: write
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Configure GitHub Pages
uses: actions/configure-pages@v5
with:
enablement: true

- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
1 change: 1 addition & 0 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ jobs:
uses: gitleaks/gitleaks-action@v2
env:
GITLEAKS_CONFIG: .github/.gitleaks.toml
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
33 changes: 33 additions & 0 deletions .swiftlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
included:
- Sources
- Tests
- Examples
excluded:
- .build
- .cursor
- .swiftpm
- internal-docs
only_rules:
- duplicate_imports
- empty_count
- explicit_init
- first_where
- line_length
- missing_docs
- modifier_order
- trailing_newline
- trailing_whitespace
- unused_import
line_length:
warning: 160
error: 200
ignores_urls: true
missing_docs:
warning:
- open
- public
excludes_extensions: true
excludes_inherited_types: true
excludes_trivial_init: false
trailing_whitespace:
ignores_empty_lines: true
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ final class OpenClawtvOSUITests: XCTestCase {
// In UI tests it is usually best to stop immediately when a failure occurs.
continueAfterFailure = false

// In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.
// In UI tests it is important to set the initial state, such as interface
// orientation, before the tests run. `setUpWithError()` is a good place.
}

override func tearDownWithError() throws {
Expand Down
12 changes: 7 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# OpenClawKit

[![CI](https://github.com/MarcoDotIO/OpenClawKit/actions/workflows/ci.yml/badge.svg)](https://github.com/MarcoDotIO/OpenClawKit/actions/workflows/ci.yml)
[![Documentation](https://github.com/MarcoDotIO/OpenClawKit/actions/workflows/docs.yml/badge.svg)](https://github.com/MarcoDotIO/OpenClawKit/actions/workflows/docs.yml)
[![Security](https://github.com/MarcoDotIO/OpenClawKit/actions/workflows/security.yml/badge.svg)](https://github.com/MarcoDotIO/OpenClawKit/actions/workflows/security.yml)
[![Release](https://github.com/MarcoDotIO/OpenClawKit/actions/workflows/release.yml/badge.svg)](https://github.com/MarcoDotIO/OpenClawKit/actions/workflows/release.yml)
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
Expand All @@ -13,6 +14,9 @@ OpenClawKit is a Swift-native agent SDK for Apple platforms and Linux services.
It provides a complete runtime surface: protocol contracts, model routing, channels,
skills, memory, observability, security, iOS app integrations, and release-grade tooling.

Public SDK documentation is published as a Swift-DocC site on GitHub Pages, with
stable companion notes in `docs/`.

## 2026.2.4 Highlights

### OpenClaw 2026.3.13 Parity
Expand Down Expand Up @@ -422,19 +426,17 @@ Scripts/validate-apple-matrix.sh --platform ios

CI workflows:

- `ci.yml` - Swift validation, iOS build, and Apple platform matrix checks
- `ci.yml` - Swift validation, linting, iOS build, and Apple platform matrix checks
- `docs.yml` - Swift-DocC build validation and GitHub Pages deployment
- `security.yml` - secret/security scanning
- `release.yml` - changelog-gated tagged releases

## Documentation

- GitHub Pages DocC site: `https://marcodotio.github.io/OpenClawKit/`
- [Architecture](docs/architecture.md)
- [API Surface](docs/api-surface.md)
- [Testing Guide](docs/testing.md)
- [2026.2.4 Parity Manifest](docs/parity-2026.2.4.md)
- [2026.3.11 Parity Manifest](docs/parity-2026.3.11.md)
- [2026.2.1 Parity Manifest](docs/parity-2026.2.1.md)
- [2026.2.1 Roadmap](docs/roadmap-2026.2.1.md)
- [Changelog](CHANGELOG.md)

Protocol generation:
Expand Down
61 changes: 61 additions & 0 deletions Scripts/build-docs-site.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
DERIVED_DATA_PATH="${DERIVED_DATA_PATH:-${ROOT_DIR}/.build/docc-derived-data}"
MERGED_ARCHIVE_PATH="${DOCC_MERGED_ARCHIVE_PATH:-${ROOT_DIR}/.build/OpenClawKit.doccarchive}"
SITE_OUTPUT_PATH="${DOCC_STATIC_SITE_OUTPUT_PATH:-${ROOT_DIR}/.build/docc-static-site}"
HOSTING_BASE_PATH="${DOCC_HOSTING_BASE_PATH:-/OpenClawKit}"
SCHEME="${DOCC_SCHEME:-OpenClawKit-Package}"
FIRST_PARTY_MODULES=(
OpenClawProtocol
OpenClawCore
OpenClawGateway
OpenClawAgents
OpenClawPlugins
OpenClawChannels
OpenClawMemory
OpenClawMedia
OpenClawModels
OpenClawSkills
OpenClawKit
OpenClawChatUI
)

if ! command -v xcodebuild >/dev/null 2>&1; then
echo "xcodebuild is required to generate DocC archives." >&2
exit 1
fi

rm -rf "${DERIVED_DATA_PATH}" "${MERGED_ARCHIVE_PATH}" "${SITE_OUTPUT_PATH}"

xcodebuild docbuild \
-scheme "${SCHEME}" \
-destination 'generic/platform=macOS' \
-derivedDataPath "${DERIVED_DATA_PATH}" \
CODE_SIGNING_ALLOWED=NO

archives=()
for module in "${FIRST_PARTY_MODULES[@]}"; do
archive_path="${DERIVED_DATA_PATH}/Build/Products/Debug/${module}.doccarchive"
if [[ ! -d "${archive_path}" ]]; then
echo "Missing DocC archive for ${module}: ${archive_path}" >&2
exit 1
fi
archives+=("${archive_path}")
done

xcrun docc merge \
"${archives[@]}" \
--output-path "${MERGED_ARCHIVE_PATH}" \
--synthesized-landing-page-name OpenClawKit \
--synthesized-landing-page-kind Package \
--synthesized-landing-page-topics-style detailedGrid

xcrun docc process-archive transform-for-static-hosting \
"${MERGED_ARCHIVE_PATH}" \
--output-path "${SITE_OUTPUT_PATH}" \
--hosting-base-path "${HOSTING_BASE_PATH}"

test -f "${SITE_OUTPUT_PATH}/index.html"
test -d "${SITE_OUTPUT_PATH}/documentation/openclawkit"
22 changes: 22 additions & 0 deletions Scripts/lint-swift.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#!/usr/bin/env bash
set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
CONFIG_PATH="${ROOT_DIR}/.swiftlint.yml"

if ! command -v swiftlint >/dev/null 2>&1; then
echo "swiftlint is required. Install it with Homebrew: brew install swiftlint" >&2
exit 1
fi

swift_files=()
while IFS= read -r -d '' file; do
swift_files+=("${file}")
done < <(find "${ROOT_DIR}/Sources" "${ROOT_DIR}/Tests" "${ROOT_DIR}/Examples" -name '*.swift' -print0)
swift_files+=("${ROOT_DIR}/Package.swift")

swiftlint lint \
--config "${CONFIG_PATH}" \
--force-exclude \
--strict \
"${swift_files[@]}"
1 change: 1 addition & 0 deletions Sources/OpenClawChannels/ChannelAdapter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ public protocol ChannelAdapter: Sendable {
}

public extension ChannelAdapter {
/// Default no-op typing indicator implementation for channels without typing support.
func sendTypingIndicator(accountID _: String?, peerID _: String) async throws {}
}

Expand Down
2 changes: 2 additions & 0 deletions Sources/OpenClawChatUI/ChatModels.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@ import Foundation
#if canImport(AppKit)
import AppKit

/// Platform image type used by shared chat UI attachment previews on AppKit.
public typealias OpenClawPlatformImage = NSImage
#elseif canImport(UIKit)
import UIKit

/// Platform image type used by shared chat UI attachment previews on UIKit.
public typealias OpenClawPlatformImage = UIImage
#endif

Expand Down
7 changes: 7 additions & 0 deletions Sources/OpenClawChatUI/ChatTransport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,43 +31,50 @@ public protocol OpenClawChatTransport: Sendable {
}

extension OpenClawChatTransport {
/// Updates the active session key used for push-event routing.
public func setActiveSessionKey(_: String) async throws {}

/// Resets one session when the transport supports a server-side reset call.
public func resetSession(sessionKey _: String) async throws {
throw NSError(
domain: "OpenClawChatTransport",
code: 0,
userInfo: [NSLocalizedDescriptionKey: "sessions.reset not supported by this transport"])
}

/// Aborts the currently running assistant response for a session when supported.
public func abortRun(sessionKey _: String, runId _: String) async throws {
throw NSError(
domain: "OpenClawChatTransport",
code: 0,
userInfo: [NSLocalizedDescriptionKey: "chat.abort not supported by this transport"])
}

/// Lists recent sessions when the backing transport exposes multi-session history.
public func listSessions(limit _: Int?) async throws -> OpenClawChatSessionsListResponse {
throw NSError(
domain: "OpenClawChatTransport",
code: 0,
userInfo: [NSLocalizedDescriptionKey: "sessions.list not supported by this transport"])
}

/// Lists available model picker choices when the transport supports model discovery.
public func listModels() async throws -> [OpenClawChatModelChoice] {
throw NSError(
domain: "OpenClawChatTransport",
code: 0,
userInfo: [NSLocalizedDescriptionKey: "models.list not supported by this transport"])
}

/// Changes the current session model when the transport supports session patching.
public func setSessionModel(sessionKey _: String, model _: String?) async throws {
throw NSError(
domain: "OpenClawChatTransport",
code: 0,
userInfo: [NSLocalizedDescriptionKey: "sessions.patch(model) not supported by this transport"])
}

/// Changes the current session thinking level when the transport supports session patching.
public func setSessionThinking(sessionKey _: String, thinkingLevel _: String) async throws {
throw NSError(
domain: "OpenClawChatTransport",
Expand Down
Loading
Loading