Compare commits
8 Commits
master
...
feat/hardw
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e6f0d1198 | ||
|
|
7e40186bd7 | ||
|
|
f94c10024b | ||
|
|
46262136f6 | ||
|
|
bd08a1bc94 | ||
|
|
2fbf4cd15c | ||
|
|
eb518adb38 | ||
|
|
83f1d474bd |
@ -1,44 +1,3 @@
|
||||
# EditorConfig is awesome: https://EditorConfig.org
|
||||
|
||||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# All files
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
# Rust files - match rustfmt.toml
|
||||
[*.rs]
|
||||
indent_size = 4
|
||||
max_line_length = 100
|
||||
|
||||
# Markdown files
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
max_line_length = 80
|
||||
|
||||
# TOML files
|
||||
[*.toml]
|
||||
indent_size = 2
|
||||
|
||||
# YAML files
|
||||
[*.{yml,yaml}]
|
||||
indent_size = 2
|
||||
|
||||
# Python files
|
||||
[*.py]
|
||||
indent_size = 4
|
||||
max_line_length = 100
|
||||
|
||||
# Shell scripts
|
||||
[*.{sh,bash}]
|
||||
indent_size = 2
|
||||
|
||||
# JSON files
|
||||
[*.json]
|
||||
indent_size = 2
|
||||
|
||||
@ -118,7 +118,3 @@ PROVIDER=openrouter
|
||||
# Optional: Brave Search (requires API key from https://brave.com/search/api)
|
||||
# WEB_SEARCH_PROVIDER=brave
|
||||
# BRAVE_API_KEY=your-brave-search-api-key
|
||||
#
|
||||
# Optional: SearXNG (self-hosted, requires instance URL)
|
||||
# WEB_SEARCH_PROVIDER=searxng
|
||||
# SEARXNG_INSTANCE_URL=https://searx.example.com
|
||||
|
||||
301
.github/labeler.yml
vendored
@ -36,145 +36,6 @@
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/**"
|
||||
|
||||
"channel:bluesky":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/bluesky.rs"
|
||||
|
||||
"channel:clawdtalk":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/clawdtalk.rs"
|
||||
|
||||
"channel:cli":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/cli.rs"
|
||||
|
||||
"channel:dingtalk":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/dingtalk.rs"
|
||||
|
||||
"channel:discord":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/discord.rs"
|
||||
- "src/channels/discord_history.rs"
|
||||
|
||||
"channel:email":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/email_channel.rs"
|
||||
- "src/channels/gmail_push.rs"
|
||||
|
||||
"channel:imessage":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/imessage.rs"
|
||||
|
||||
"channel:irc":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/irc.rs"
|
||||
|
||||
"channel:lark":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/lark.rs"
|
||||
|
||||
"channel:linq":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/linq.rs"
|
||||
|
||||
"channel:matrix":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/matrix.rs"
|
||||
|
||||
"channel:mattermost":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/mattermost.rs"
|
||||
|
||||
"channel:mochat":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/mochat.rs"
|
||||
|
||||
"channel:mqtt":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/mqtt.rs"
|
||||
|
||||
"channel:nextcloud-talk":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/nextcloud_talk.rs"
|
||||
|
||||
"channel:nostr":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/nostr.rs"
|
||||
|
||||
"channel:notion":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/notion.rs"
|
||||
|
||||
"channel:qq":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/qq.rs"
|
||||
|
||||
"channel:reddit":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/reddit.rs"
|
||||
|
||||
"channel:signal":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/signal.rs"
|
||||
|
||||
"channel:slack":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/slack.rs"
|
||||
|
||||
"channel:telegram":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/telegram.rs"
|
||||
|
||||
"channel:twitter":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/twitter.rs"
|
||||
|
||||
"channel:wati":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/wati.rs"
|
||||
|
||||
"channel:webhook":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/webhook.rs"
|
||||
|
||||
"channel:wecom":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/wecom.rs"
|
||||
|
||||
"channel:whatsapp":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/channels/whatsapp.rs"
|
||||
- "src/channels/whatsapp_storage.rs"
|
||||
- "src/channels/whatsapp_web.rs"
|
||||
|
||||
"gateway":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
@ -240,73 +101,6 @@
|
||||
- any-glob-to-any-file:
|
||||
- "src/providers/**"
|
||||
|
||||
"provider:anthropic":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/providers/anthropic.rs"
|
||||
|
||||
"provider:azure-openai":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/providers/azure_openai.rs"
|
||||
|
||||
"provider:bedrock":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/providers/bedrock.rs"
|
||||
|
||||
"provider:claude-code":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/providers/claude_code.rs"
|
||||
|
||||
"provider:compatible":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/providers/compatible.rs"
|
||||
|
||||
"provider:copilot":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/providers/copilot.rs"
|
||||
|
||||
"provider:gemini":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/providers/gemini.rs"
|
||||
- "src/providers/gemini_cli.rs"
|
||||
|
||||
"provider:glm":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/providers/glm.rs"
|
||||
|
||||
"provider:kilocli":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/providers/kilocli.rs"
|
||||
|
||||
"provider:ollama":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/providers/ollama.rs"
|
||||
|
||||
"provider:openai":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/providers/openai.rs"
|
||||
- "src/providers/openai_codex.rs"
|
||||
|
||||
"provider:openrouter":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/providers/openrouter.rs"
|
||||
|
||||
"provider:telnyx":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/providers/telnyx.rs"
|
||||
|
||||
"service":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
@ -327,101 +121,6 @@
|
||||
- any-glob-to-any-file:
|
||||
- "src/tools/**"
|
||||
|
||||
"tool:browser":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/tools/browser.rs"
|
||||
- "src/tools/browser_delegate.rs"
|
||||
- "src/tools/browser_open.rs"
|
||||
- "src/tools/text_browser.rs"
|
||||
- "src/tools/screenshot.rs"
|
||||
|
||||
"tool:composio":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/tools/composio.rs"
|
||||
|
||||
"tool:cron":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/tools/cron_add.rs"
|
||||
- "src/tools/cron_list.rs"
|
||||
- "src/tools/cron_remove.rs"
|
||||
- "src/tools/cron_run.rs"
|
||||
- "src/tools/cron_runs.rs"
|
||||
- "src/tools/cron_update.rs"
|
||||
|
||||
"tool:file":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/tools/file_edit.rs"
|
||||
- "src/tools/file_read.rs"
|
||||
- "src/tools/file_write.rs"
|
||||
- "src/tools/glob_search.rs"
|
||||
- "src/tools/content_search.rs"
|
||||
|
||||
"tool:google-workspace":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/tools/google_workspace.rs"
|
||||
|
||||
"tool:mcp":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/tools/mcp_client.rs"
|
||||
- "src/tools/mcp_deferred.rs"
|
||||
- "src/tools/mcp_protocol.rs"
|
||||
- "src/tools/mcp_tool.rs"
|
||||
- "src/tools/mcp_transport.rs"
|
||||
|
||||
"tool:memory":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/tools/memory_forget.rs"
|
||||
- "src/tools/memory_recall.rs"
|
||||
- "src/tools/memory_store.rs"
|
||||
|
||||
"tool:microsoft365":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/tools/microsoft365/**"
|
||||
|
||||
"tool:shell":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/tools/shell.rs"
|
||||
- "src/tools/node_tool.rs"
|
||||
- "src/tools/cli_discovery.rs"
|
||||
|
||||
"tool:sop":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/tools/sop_advance.rs"
|
||||
- "src/tools/sop_approve.rs"
|
||||
- "src/tools/sop_execute.rs"
|
||||
- "src/tools/sop_list.rs"
|
||||
- "src/tools/sop_status.rs"
|
||||
|
||||
"tool:web":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/tools/web_fetch.rs"
|
||||
- "src/tools/web_search_tool.rs"
|
||||
- "src/tools/web_search_provider_routing.rs"
|
||||
- "src/tools/http_request.rs"
|
||||
|
||||
"tool:security":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/tools/security_ops.rs"
|
||||
- "src/tools/verifiable_intent.rs"
|
||||
|
||||
"tool:cloud":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- "src/tools/cloud_ops.rs"
|
||||
- "src/tools/cloud_patterns.rs"
|
||||
|
||||
"tunnel":
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
|
||||
4
.github/workflows/ci-run.yml
vendored
@ -7,7 +7,7 @@ on:
|
||||
branches: [master]
|
||||
|
||||
concurrency:
|
||||
group: ci-${{ github.event.pull_request.number || 'push-master' }}
|
||||
group: ci-${{ github.event.pull_request.number || github.sha }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
@ -154,7 +154,7 @@ jobs:
|
||||
run: mkdir -p web/dist && touch web/dist/.gitkeep
|
||||
|
||||
- name: Check all features
|
||||
run: cargo check --features ci-all --locked
|
||||
run: cargo check --all-features --locked
|
||||
|
||||
docs-quality:
|
||||
name: Docs Quality
|
||||
|
||||
19
.github/workflows/pr-path-labeler.yml
vendored
@ -1,19 +0,0 @@
|
||||
name: PR Path Labeler
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [opened, synchronize, reopened]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
label:
|
||||
name: Apply path labels
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5
|
||||
with:
|
||||
sync-labels: true
|
||||
16
.github/workflows/pub-homebrew-core.yml
vendored
@ -1,22 +1,6 @@
|
||||
name: Pub Homebrew Core
|
||||
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
release_tag:
|
||||
description: "Existing release tag to publish (vX.Y.Z)"
|
||||
required: true
|
||||
type: string
|
||||
dry_run:
|
||||
description: "Patch formula only (no push/PR)"
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
secrets:
|
||||
HOMEBREW_UPSTREAM_PR_TOKEN:
|
||||
required: false
|
||||
HOMEBREW_CORE_BOT_TOKEN:
|
||||
required: false
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
release_tag:
|
||||
|
||||
25
.github/workflows/publish-crates-auto.yml
vendored
@ -19,7 +19,6 @@ env:
|
||||
jobs:
|
||||
detect-version-change:
|
||||
name: Detect Version Bump
|
||||
if: github.repository == 'zeroclaw-labs/zeroclaw'
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
changed: ${{ steps.check.outputs.changed }}
|
||||
@ -41,14 +40,6 @@ jobs:
|
||||
echo "Current version: ${current}"
|
||||
echo "Previous version: ${previous}"
|
||||
|
||||
# Skip if stable release workflow will handle this version
|
||||
# (indicated by an existing or imminent stable tag)
|
||||
if git ls-remote --exit-code --tags origin "refs/tags/v${current}" >/dev/null 2>&1; then
|
||||
echo "Stable tag v${current} exists — stable release workflow handles crates.io"
|
||||
echo "changed=false" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "$current" != "$previous" && -n "$current" ]]; then
|
||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
echo "version=${current}" >> "$GITHUB_OUTPUT"
|
||||
@ -111,22 +102,6 @@ jobs:
|
||||
- name: Clean web build artifacts
|
||||
run: rm -rf web/node_modules web/src web/package.json web/package-lock.json web/tsconfig*.json web/vite.config.ts web/index.html
|
||||
|
||||
- name: Publish aardvark-sys to crates.io
|
||||
shell: bash
|
||||
env:
|
||||
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||
run: |
|
||||
OUTPUT=$(cargo publish --locked --allow-dirty --no-verify -p aardvark-sys 2>&1) && exit 0
|
||||
echo "$OUTPUT"
|
||||
if echo "$OUTPUT" | grep -q 'already exists'; then
|
||||
echo "::notice::aardvark-sys already on crates.io — skipping"
|
||||
exit 0
|
||||
fi
|
||||
exit 1
|
||||
|
||||
- name: Wait for aardvark-sys to index
|
||||
run: sleep 15
|
||||
|
||||
- name: Publish to crates.io
|
||||
shell: bash
|
||||
env:
|
||||
|
||||
18
.github/workflows/publish-crates.yml
vendored
@ -67,24 +67,6 @@ jobs:
|
||||
- name: Clean web build artifacts
|
||||
run: rm -rf web/node_modules web/src web/package.json web/package-lock.json web/tsconfig*.json web/vite.config.ts web/index.html
|
||||
|
||||
- name: Publish aardvark-sys to crates.io
|
||||
if: "!inputs.dry_run"
|
||||
shell: bash
|
||||
env:
|
||||
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||
run: |
|
||||
OUTPUT=$(cargo publish --locked --allow-dirty --no-verify -p aardvark-sys 2>&1) && exit 0
|
||||
echo "$OUTPUT"
|
||||
if echo "$OUTPUT" | grep -q 'already exists'; then
|
||||
echo "::notice::aardvark-sys already on crates.io — skipping"
|
||||
exit 0
|
||||
fi
|
||||
exit 1
|
||||
|
||||
- name: Wait for aardvark-sys to index
|
||||
if: "!inputs.dry_run"
|
||||
run: sleep 15
|
||||
|
||||
- name: Publish (dry run)
|
||||
if: inputs.dry_run
|
||||
run: cargo publish --dry-run --locked --allow-dirty --no-verify
|
||||
|
||||
92
.github/workflows/release-beta-on-push.yml
vendored
@ -21,48 +21,25 @@ env:
|
||||
jobs:
|
||||
version:
|
||||
name: Resolve Version
|
||||
if: github.repository == 'zeroclaw-labs/zeroclaw'
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
version: ${{ steps.ver.outputs.version }}
|
||||
tag: ${{ steps.ver.outputs.tag }}
|
||||
skip: ${{ steps.ver.outputs.skip }}
|
||||
steps:
|
||||
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
with:
|
||||
fetch-depth: 2
|
||||
- name: Compute beta version
|
||||
id: ver
|
||||
shell: bash
|
||||
run: |
|
||||
set -euo pipefail
|
||||
base_version=$(sed -n 's/^version = "\([^"]*\)"/\1/p' Cargo.toml | head -1)
|
||||
|
||||
# Skip beta if this is a version bump commit (stable release handles it)
|
||||
commit_msg=$(git log -1 --pretty=format:"%s")
|
||||
if [[ "$commit_msg" =~ ^chore:\ bump\ version ]]; then
|
||||
echo "Version bump commit detected — skipping beta release"
|
||||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Skip beta if a stable tag already exists for this version
|
||||
if git ls-remote --exit-code --tags origin "refs/tags/v${base_version}" >/dev/null 2>&1; then
|
||||
echo "Stable tag v${base_version} exists — skipping beta release"
|
||||
echo "skip=true" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
beta_tag="v${base_version}-beta.${GITHUB_RUN_NUMBER}"
|
||||
echo "version=${base_version}" >> "$GITHUB_OUTPUT"
|
||||
echo "tag=${beta_tag}" >> "$GITHUB_OUTPUT"
|
||||
echo "skip=false" >> "$GITHUB_OUTPUT"
|
||||
echo "Beta release: ${beta_tag}"
|
||||
|
||||
release-notes:
|
||||
name: Generate Release Notes
|
||||
needs: [version]
|
||||
if: github.repository == 'zeroclaw-labs/zeroclaw' && needs.version.outputs.skip != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
notes: ${{ steps.notes.outputs.body }}
|
||||
@ -153,8 +130,6 @@ jobs:
|
||||
|
||||
web:
|
||||
name: Build Web Dashboard
|
||||
needs: [version]
|
||||
if: github.repository == 'zeroclaw-labs/zeroclaw' && needs.version.outputs.skip != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 10
|
||||
steps:
|
||||
@ -266,65 +241,9 @@ jobs:
|
||||
path: zeroclaw-${{ matrix.target }}.${{ matrix.ext }}
|
||||
retention-days: 7
|
||||
|
||||
build-desktop:
|
||||
name: Build Desktop App (macOS Universal)
|
||||
needs: [version]
|
||||
if: needs.version.outputs.skip != 'true'
|
||||
runs-on: macos-14
|
||||
timeout-minutes: 40
|
||||
steps:
|
||||
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
|
||||
- uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
|
||||
with:
|
||||
toolchain: 1.92.0
|
||||
targets: aarch64-apple-darwin,x86_64-apple-darwin
|
||||
|
||||
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
|
||||
with:
|
||||
prefix-key: macos-tauri
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
- name: Install Tauri CLI
|
||||
run: cargo install tauri-cli --locked
|
||||
|
||||
- name: Sync Tauri version with Cargo.toml
|
||||
shell: bash
|
||||
run: |
|
||||
VERSION=$(sed -n 's/^version = "\([^"]*\)"/\1/p' Cargo.toml | head -1)
|
||||
cd apps/tauri
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
jq --arg v "$VERSION" '.version = $v' tauri.conf.json > tmp.json && mv tmp.json tauri.conf.json
|
||||
else
|
||||
sed -i '' "s/\"version\": \"[^\"]*\"/\"version\": \"$VERSION\"/" tauri.conf.json
|
||||
fi
|
||||
echo "Tauri version set to: $VERSION"
|
||||
|
||||
- name: Build Tauri app (universal binary)
|
||||
working-directory: apps/tauri
|
||||
run: cargo tauri build --target universal-apple-darwin
|
||||
|
||||
- name: Prepare desktop release assets
|
||||
run: |
|
||||
mkdir -p desktop-assets
|
||||
find target -name '*.dmg' -exec cp {} desktop-assets/ZeroClaw.dmg \; 2>/dev/null || true
|
||||
find target -name '*.app.tar.gz' -exec cp {} desktop-assets/ZeroClaw-macos.app.tar.gz \; 2>/dev/null || true
|
||||
find target -name '*.app.tar.gz.sig' -exec cp {} desktop-assets/ZeroClaw-macos.app.tar.gz.sig \; 2>/dev/null || true
|
||||
echo "--- Desktop assets ---"
|
||||
ls -lh desktop-assets/
|
||||
|
||||
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: desktop-macos
|
||||
path: desktop-assets/*
|
||||
retention-days: 7
|
||||
|
||||
publish:
|
||||
name: Publish Beta Release
|
||||
needs: [version, release-notes, build, build-desktop]
|
||||
needs: [version, release-notes, build]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
@ -334,21 +253,16 @@ jobs:
|
||||
pattern: zeroclaw-*
|
||||
path: artifacts
|
||||
|
||||
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
||||
with:
|
||||
name: desktop-macos
|
||||
path: artifacts/desktop-macos
|
||||
|
||||
- name: Generate checksums
|
||||
run: |
|
||||
cd artifacts
|
||||
find . -type f \( -name '*.tar.gz' -o -name '*.zip' -o -name '*.dmg' \) -exec sha256sum {} + | sed 's| \./[^/]*/| |' > SHA256SUMS
|
||||
find . -type f \( -name '*.tar.gz' -o -name '*.zip' \) -exec sha256sum {} + | sed 's| \./[^/]*/| |' > SHA256SUMS
|
||||
cat SHA256SUMS
|
||||
|
||||
- name: Collect release assets
|
||||
run: |
|
||||
mkdir -p release-assets
|
||||
find artifacts -type f \( -name '*.tar.gz' -o -name '*.zip' -o -name '*.dmg' -o -name 'SHA256SUMS' \) -exec cp {} release-assets/ \;
|
||||
find artifacts -type f \( -name '*.tar.gz' -o -name '*.zip' -o -name 'SHA256SUMS' \) -exec cp {} release-assets/ \;
|
||||
cp install.sh release-assets/
|
||||
echo "--- Assets ---"
|
||||
ls -lh release-assets/
|
||||
|
||||
125
.github/workflows/release-stable-manual.yml
vendored
@ -1,9 +1,6 @@
|
||||
name: Release Stable
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v[0-9]+.[0-9]+.[0-9]+" # stable tags only (no -beta suffix)
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
version:
|
||||
@ -36,22 +33,11 @@ jobs:
|
||||
- name: Validate semver and Cargo.toml match
|
||||
id: check
|
||||
shell: bash
|
||||
env:
|
||||
INPUT_VERSION: ${{ inputs.version || '' }}
|
||||
REF_NAME: ${{ github.ref_name }}
|
||||
EVENT_NAME: ${{ github.event_name }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
input_version="${{ inputs.version }}"
|
||||
cargo_version=$(sed -n 's/^version = "\([^"]*\)"/\1/p' Cargo.toml | head -1)
|
||||
|
||||
# Resolve version from tag push or manual input
|
||||
if [[ "$EVENT_NAME" == "push" ]]; then
|
||||
# Tag push: extract version from tag name (v0.5.9 -> 0.5.9)
|
||||
input_version="${REF_NAME#v}"
|
||||
else
|
||||
input_version="$INPUT_VERSION"
|
||||
fi
|
||||
|
||||
if [[ ! "$input_version" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "::error::Version must be semver (X.Y.Z). Got: ${input_version}"
|
||||
exit 1
|
||||
@ -63,13 +49,9 @@ jobs:
|
||||
fi
|
||||
|
||||
tag="v${input_version}"
|
||||
|
||||
# Only check tag existence for manual dispatch (tag push means it already exists)
|
||||
if [[ "$EVENT_NAME" != "push" ]]; then
|
||||
if git ls-remote --exit-code --tags origin "refs/tags/${tag}" >/dev/null 2>&1; then
|
||||
echo "::error::Tag ${tag} already exists."
|
||||
exit 1
|
||||
fi
|
||||
if git ls-remote --exit-code --tags origin "refs/tags/${tag}" >/dev/null 2>&1; then
|
||||
echo "::error::Tag ${tag} already exists."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "tag=${tag}" >> "$GITHUB_OUTPUT"
|
||||
@ -273,64 +255,9 @@ jobs:
|
||||
path: zeroclaw-${{ matrix.target }}.${{ matrix.ext }}
|
||||
retention-days: 14
|
||||
|
||||
build-desktop:
|
||||
name: Build Desktop App (macOS Universal)
|
||||
needs: [validate]
|
||||
runs-on: macos-14
|
||||
timeout-minutes: 40
|
||||
steps:
|
||||
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
|
||||
- uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable
|
||||
with:
|
||||
toolchain: 1.92.0
|
||||
targets: aarch64-apple-darwin,x86_64-apple-darwin
|
||||
|
||||
- uses: Swatinem/rust-cache@779680da715d629ac1d338a641029a2f4372abb5 # v2
|
||||
with:
|
||||
prefix-key: macos-tauri
|
||||
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
- name: Install Tauri CLI
|
||||
run: cargo install tauri-cli --locked
|
||||
|
||||
- name: Sync Tauri version with Cargo.toml
|
||||
shell: bash
|
||||
run: |
|
||||
VERSION=$(sed -n 's/^version = "\([^"]*\)"/\1/p' Cargo.toml | head -1)
|
||||
cd apps/tauri
|
||||
if command -v jq >/dev/null 2>&1; then
|
||||
jq --arg v "$VERSION" '.version = $v' tauri.conf.json > tmp.json && mv tmp.json tauri.conf.json
|
||||
else
|
||||
sed -i '' "s/\"version\": \"[^\"]*\"/\"version\": \"$VERSION\"/" tauri.conf.json
|
||||
fi
|
||||
echo "Tauri version set to: $VERSION"
|
||||
|
||||
- name: Build Tauri app (universal binary)
|
||||
working-directory: apps/tauri
|
||||
run: cargo tauri build --target universal-apple-darwin
|
||||
|
||||
- name: Prepare desktop release assets
|
||||
run: |
|
||||
mkdir -p desktop-assets
|
||||
find target -name '*.dmg' -exec cp {} desktop-assets/ZeroClaw.dmg \; 2>/dev/null || true
|
||||
find target -name '*.app.tar.gz' -exec cp {} desktop-assets/ZeroClaw-macos.app.tar.gz \; 2>/dev/null || true
|
||||
find target -name '*.app.tar.gz.sig' -exec cp {} desktop-assets/ZeroClaw-macos.app.tar.gz.sig \; 2>/dev/null || true
|
||||
echo "--- Desktop assets ---"
|
||||
ls -lh desktop-assets/
|
||||
|
||||
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: desktop-macos
|
||||
path: desktop-assets/*
|
||||
retention-days: 14
|
||||
|
||||
publish:
|
||||
name: Publish Stable Release
|
||||
needs: [validate, release-notes, build, build-desktop]
|
||||
needs: [validate, release-notes, build]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
@ -340,21 +267,16 @@ jobs:
|
||||
pattern: zeroclaw-*
|
||||
path: artifacts
|
||||
|
||||
- uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
||||
with:
|
||||
name: desktop-macos
|
||||
path: artifacts/desktop-macos
|
||||
|
||||
- name: Generate checksums
|
||||
run: |
|
||||
cd artifacts
|
||||
find . -type f \( -name '*.tar.gz' -o -name '*.zip' -o -name '*.dmg' \) -exec sha256sum {} + | sed 's| \./[^/]*/| |' > SHA256SUMS
|
||||
find . -type f \( -name '*.tar.gz' -o -name '*.zip' \) -exec sha256sum {} + | sed 's| \./[^/]*/| |' > SHA256SUMS
|
||||
cat SHA256SUMS
|
||||
|
||||
- name: Collect release assets
|
||||
run: |
|
||||
mkdir -p release-assets
|
||||
find artifacts -type f \( -name '*.tar.gz' -o -name '*.zip' -o -name '*.dmg' -o -name 'SHA256SUMS' \) -exec cp {} release-assets/ \;
|
||||
find artifacts -type f \( -name '*.tar.gz' -o -name '*.zip' -o -name 'SHA256SUMS' \) -exec cp {} release-assets/ \;
|
||||
cp install.sh release-assets/
|
||||
echo "--- Assets ---"
|
||||
ls -lh release-assets/
|
||||
@ -364,14 +286,6 @@ jobs:
|
||||
NOTES: ${{ needs.release-notes.outputs.notes }}
|
||||
run: printf '%s\n' "$NOTES" > release-notes.md
|
||||
|
||||
- name: Create tag if manual dispatch
|
||||
if: github.event_name == 'workflow_dispatch'
|
||||
env:
|
||||
TAG: ${{ needs.validate.outputs.tag }}
|
||||
run: |
|
||||
git tag -a "$TAG" -m "zeroclaw $TAG"
|
||||
git push origin "$TAG"
|
||||
|
||||
- name: Create GitHub Release
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.RELEASE_TOKEN }}
|
||||
@ -409,21 +323,6 @@ jobs:
|
||||
- name: Clean web build artifacts
|
||||
run: rm -rf web/node_modules web/src web/package.json web/package-lock.json web/tsconfig*.json web/vite.config.ts web/index.html
|
||||
|
||||
- name: Publish aardvark-sys to crates.io
|
||||
env:
|
||||
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||
run: |
|
||||
OUTPUT=$(cargo publish --locked --allow-dirty --no-verify -p aardvark-sys 2>&1) && exit 0
|
||||
echo "$OUTPUT"
|
||||
if echo "$OUTPUT" | grep -q 'already exists'; then
|
||||
echo "::notice::aardvark-sys already on crates.io — skipping"
|
||||
exit 0
|
||||
fi
|
||||
exit 1
|
||||
|
||||
- name: Wait for aardvark-sys to index
|
||||
run: sleep 15
|
||||
|
||||
- name: Publish to crates.io
|
||||
env:
|
||||
CARGO_REGISTRY_TOKEN: ${{ secrets.CARGO_REGISTRY_TOKEN }}
|
||||
@ -547,16 +446,6 @@ jobs:
|
||||
dry_run: false
|
||||
secrets: inherit
|
||||
|
||||
homebrew:
|
||||
name: Update Homebrew Core
|
||||
needs: [validate, publish]
|
||||
if: ${{ !cancelled() && needs.publish.result == 'success' }}
|
||||
uses: ./.github/workflows/pub-homebrew-core.yml
|
||||
with:
|
||||
release_tag: ${{ needs.validate.outputs.tag }}
|
||||
dry_run: false
|
||||
secrets: inherit
|
||||
|
||||
# ── Post-publish: tweet after release + website are live ──────────────
|
||||
# Docker push can be slow; don't let it block the tweet.
|
||||
tweet:
|
||||
|
||||
92
AGENTS.md
@ -1,92 +0,0 @@
|
||||
# AGENTS.md — ZeroClaw
|
||||
|
||||
Cross-tool agent instructions for any AI coding assistant working on this repository.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
cargo fmt --all -- --check
|
||||
cargo clippy --all-targets -- -D warnings
|
||||
cargo test
|
||||
```
|
||||
|
||||
Full pre-PR validation (recommended):
|
||||
|
||||
```bash
|
||||
./dev/ci.sh all
|
||||
```
|
||||
|
||||
Docs-only changes: run markdown lint and link-integrity checks. If touching bootstrap scripts: `bash -n install.sh`.
|
||||
|
||||
## Project Snapshot
|
||||
|
||||
ZeroClaw is a Rust-first autonomous agent runtime optimized for performance, efficiency, stability, extensibility, sustainability, and security.
|
||||
|
||||
Core architecture is trait-driven and modular. Extend by implementing traits and registering in factory modules.
|
||||
|
||||
Key extension points:
|
||||
|
||||
- `src/providers/traits.rs` (`Provider`)
|
||||
- `src/channels/traits.rs` (`Channel`)
|
||||
- `src/tools/traits.rs` (`Tool`)
|
||||
- `src/memory/traits.rs` (`Memory`)
|
||||
- `src/observability/traits.rs` (`Observer`)
|
||||
- `src/runtime/traits.rs` (`RuntimeAdapter`)
|
||||
- `src/peripherals/traits.rs` (`Peripheral`) — hardware boards (STM32, RPi GPIO)
|
||||
|
||||
## Repository Map
|
||||
|
||||
- `src/main.rs` — CLI entrypoint and command routing
|
||||
- `src/lib.rs` — module exports and shared command enums
|
||||
- `src/config/` — schema + config loading/merging
|
||||
- `src/agent/` — orchestration loop
|
||||
- `src/gateway/` — webhook/gateway server
|
||||
- `src/security/` — policy, pairing, secret store
|
||||
- `src/memory/` — markdown/sqlite memory backends + embeddings/vector merge
|
||||
- `src/providers/` — model providers and resilient wrapper
|
||||
- `src/channels/` — Telegram/Discord/Slack/etc channels
|
||||
- `src/tools/` — tool execution surface (shell, file, memory, browser)
|
||||
- `src/peripherals/` — hardware peripherals (STM32, RPi GPIO)
|
||||
- `src/runtime/` — runtime adapters (currently native)
|
||||
- `docs/` — topic-based documentation (setup-guides, reference, ops, security, hardware, contributing, maintainers)
|
||||
- `.github/` — CI, templates, automation workflows
|
||||
|
||||
## Risk Tiers
|
||||
|
||||
- **Low risk**: docs/chore/tests-only changes
|
||||
- **Medium risk**: most `src/**` behavior changes without boundary/security impact
|
||||
- **High risk**: `src/security/**`, `src/runtime/**`, `src/gateway/**`, `src/tools/**`, `.github/workflows/**`, access-control boundaries
|
||||
|
||||
When uncertain, classify as higher risk.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Read before write** — inspect existing module, factory wiring, and adjacent tests before editing.
|
||||
2. **One concern per PR** — avoid mixed feature+refactor+infra patches.
|
||||
3. **Implement minimal patch** — no speculative abstractions, no config keys without a concrete use case.
|
||||
4. **Validate by risk tier** — docs-only: lightweight checks. Code changes: full relevant checks.
|
||||
5. **Document impact** — update PR notes for behavior, risk, side effects, and rollback.
|
||||
6. **Queue hygiene** — stacked PR: declare `Depends on #...`. Replacing old PR: declare `Supersedes #...`.
|
||||
|
||||
Branch/commit/PR rules:
|
||||
- Work from a non-`master` branch. Open a PR to `master`; do not push directly.
|
||||
- Use conventional commit titles. Prefer small PRs (`size: XS/S/M`).
|
||||
- Follow `.github/pull_request_template.md` fully.
|
||||
- Never commit secrets, personal data, or real identity information (see `@docs/contributing/pr-discipline.md`).
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
- Do not add heavy dependencies for minor convenience.
|
||||
- Do not silently weaken security policy or access constraints.
|
||||
- Do not add speculative config/feature flags "just in case".
|
||||
- Do not mix massive formatting-only changes with functional changes.
|
||||
- Do not modify unrelated modules "while here".
|
||||
- Do not bypass failing checks without explicit explanation.
|
||||
- Do not hide behavior-changing side effects in refactor commits.
|
||||
- Do not include personal identity or sensitive information in test data, examples, docs, or commits.
|
||||
|
||||
## Linked References
|
||||
|
||||
- `@docs/contributing/change-playbooks.md` — adding providers, channels, tools, peripherals; security/gateway changes; architecture boundaries
|
||||
- `@docs/contributing/pr-discipline.md` — privacy rules, superseded-PR attribution/templates, handoff template
|
||||
- `@docs/contributing/docs-contract.md` — docs system contract, i18n rules, locale parity
|
||||
92
CLAUDE.md
@ -1,16 +1,90 @@
|
||||
# CLAUDE.md — ZeroClaw (Claude Code)
|
||||
# CLAUDE.md — ZeroClaw
|
||||
|
||||
> **Shared instructions live in [`AGENTS.md`](./AGENTS.md).**
|
||||
> This file contains only Claude Code-specific directives.
|
||||
## Commands
|
||||
|
||||
## Claude Code Settings
|
||||
```bash
|
||||
cargo fmt --all -- --check
|
||||
cargo clippy --all-targets -- -D warnings
|
||||
cargo test
|
||||
```
|
||||
|
||||
Claude Code should read and follow all instructions in `AGENTS.md` at the repository root for project conventions, commands, risk tiers, workflow rules, and anti-patterns.
|
||||
Full pre-PR validation (recommended):
|
||||
|
||||
## Hooks
|
||||
```bash
|
||||
./dev/ci.sh all
|
||||
```
|
||||
|
||||
_No custom hooks defined yet._
|
||||
Docs-only changes: run markdown lint and link-integrity checks. If touching bootstrap scripts: `bash -n install.sh`.
|
||||
|
||||
## Slash Commands
|
||||
## Project Snapshot
|
||||
|
||||
_No custom slash commands defined yet._
|
||||
ZeroClaw is a Rust-first autonomous agent runtime optimized for performance, efficiency, stability, extensibility, sustainability, and security.
|
||||
|
||||
Core architecture is trait-driven and modular. Extend by implementing traits and registering in factory modules.
|
||||
|
||||
Key extension points:
|
||||
|
||||
- `src/providers/traits.rs` (`Provider`)
|
||||
- `src/channels/traits.rs` (`Channel`)
|
||||
- `src/tools/traits.rs` (`Tool`)
|
||||
- `src/memory/traits.rs` (`Memory`)
|
||||
- `src/observability/traits.rs` (`Observer`)
|
||||
- `src/runtime/traits.rs` (`RuntimeAdapter`)
|
||||
- `src/peripherals/traits.rs` (`Peripheral`) — hardware boards (STM32, RPi GPIO)
|
||||
|
||||
## Repository Map
|
||||
|
||||
- `src/main.rs` — CLI entrypoint and command routing
|
||||
- `src/lib.rs` — module exports and shared command enums
|
||||
- `src/config/` — schema + config loading/merging
|
||||
- `src/agent/` — orchestration loop
|
||||
- `src/gateway/` — webhook/gateway server
|
||||
- `src/security/` — policy, pairing, secret store
|
||||
- `src/memory/` — markdown/sqlite memory backends + embeddings/vector merge
|
||||
- `src/providers/` — model providers and resilient wrapper
|
||||
- `src/channels/` — Telegram/Discord/Slack/etc channels
|
||||
- `src/tools/` — tool execution surface (shell, file, memory, browser)
|
||||
- `src/peripherals/` — hardware peripherals (STM32, RPi GPIO)
|
||||
- `src/runtime/` — runtime adapters (currently native)
|
||||
- `docs/` — topic-based documentation (setup-guides, reference, ops, security, hardware, contributing, maintainers)
|
||||
- `.github/` — CI, templates, automation workflows
|
||||
|
||||
## Risk Tiers
|
||||
|
||||
- **Low risk**: docs/chore/tests-only changes
|
||||
- **Medium risk**: most `src/**` behavior changes without boundary/security impact
|
||||
- **High risk**: `src/security/**`, `src/runtime/**`, `src/gateway/**`, `src/tools/**`, `.github/workflows/**`, access-control boundaries
|
||||
|
||||
When uncertain, classify as higher risk.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Read before write** — inspect existing module, factory wiring, and adjacent tests before editing.
|
||||
2. **One concern per PR** — avoid mixed feature+refactor+infra patches.
|
||||
3. **Implement minimal patch** — no speculative abstractions, no config keys without a concrete use case.
|
||||
4. **Validate by risk tier** — docs-only: lightweight checks. Code changes: full relevant checks.
|
||||
5. **Document impact** — update PR notes for behavior, risk, side effects, and rollback.
|
||||
6. **Queue hygiene** — stacked PR: declare `Depends on #...`. Replacing old PR: declare `Supersedes #...`.
|
||||
|
||||
Branch/commit/PR rules:
|
||||
- Work from a non-`master` branch. Open a PR to `master`; do not push directly.
|
||||
- Use conventional commit titles. Prefer small PRs (`size: XS/S/M`).
|
||||
- Follow `.github/pull_request_template.md` fully.
|
||||
- Never commit secrets, personal data, or real identity information (see `@docs/contributing/pr-discipline.md`).
|
||||
|
||||
## Anti-Patterns
|
||||
|
||||
- Do not add heavy dependencies for minor convenience.
|
||||
- Do not silently weaken security policy or access constraints.
|
||||
- Do not add speculative config/feature flags "just in case".
|
||||
- Do not mix massive formatting-only changes with functional changes.
|
||||
- Do not modify unrelated modules "while here".
|
||||
- Do not bypass failing checks without explicit explanation.
|
||||
- Do not hide behavior-changing side effects in refactor commits.
|
||||
- Do not include personal identity or sensitive information in test data, examples, docs, or commits.
|
||||
|
||||
## Linked References
|
||||
|
||||
- `@docs/contributing/change-playbooks.md` — adding providers, channels, tools, peripherals; security/gateway changes; architecture boundaries
|
||||
- `@docs/contributing/pr-discipline.md` — privacy rules, superseded-PR attribution/templates, handoff template
|
||||
- `@docs/contributing/docs-contract.md` — docs system contract, i18n rules, locale parity
|
||||
|
||||
3547
Cargo.lock
generated
34
Cargo.toml
@ -1,10 +1,10 @@
|
||||
[workspace]
|
||||
members = [".", "crates/robot-kit", "crates/aardvark-sys", "apps/tauri"]
|
||||
members = [".", "crates/robot-kit", "crates/aardvark-sys"]
|
||||
resolver = "2"
|
||||
|
||||
[package]
|
||||
name = "zeroclawlabs"
|
||||
version = "0.6.1"
|
||||
version = "0.5.3"
|
||||
edition = "2021"
|
||||
authors = ["theonlyhennygod"]
|
||||
license = "MIT OR Apache-2.0"
|
||||
@ -97,7 +97,7 @@ anyhow = "1.0"
|
||||
thiserror = "2.0"
|
||||
|
||||
# Aardvark I2C/SPI/GPIO USB adapter (Total Phase) — stub when SDK absent
|
||||
aardvark-sys = { path = "crates/aardvark-sys", version = "0.1.0" }
|
||||
aardvark-sys = { path = "crates/aardvark-sys" }
|
||||
|
||||
# UUID generation
|
||||
uuid = { version = "1.22", default-features = false, features = ["v4", "std"] }
|
||||
@ -150,7 +150,6 @@ which = "8.0"
|
||||
|
||||
# WebSocket client channels (Discord/Lark/DingTalk/Nostr)
|
||||
tokio-tungstenite = { version = "0.29", features = ["rustls-tls-webpki-roots"] }
|
||||
tokio-socks = "0.5"
|
||||
futures-util = { version = "0.3", default-features = false, features = ["sink"] }
|
||||
nostr-sdk = { version = "0.44", default-features = false, features = ["nip04", "nip59"], optional = true }
|
||||
regex = "1.10"
|
||||
@ -200,9 +199,6 @@ pdf-extract = { version = "0.10", optional = true }
|
||||
# WASM plugin runtime (extism)
|
||||
extism = { version = "1.20", optional = true }
|
||||
|
||||
# Cross-platform audio capture for voice wake word detection (optional, enable with --features voice-wake)
|
||||
cpal = { version = "0.15", optional = true }
|
||||
|
||||
# Terminal QR rendering for WhatsApp Web pairing flow.
|
||||
qrcode = { version = "0.14", optional = true }
|
||||
|
||||
@ -225,7 +221,7 @@ landlock = { version = "0.4", optional = true }
|
||||
libc = "0.2"
|
||||
|
||||
[features]
|
||||
default = ["observability-prometheus", "channel-nostr", "channel-lark", "skill-creation"]
|
||||
default = ["observability-prometheus", "channel-nostr", "skill-creation"]
|
||||
channel-nostr = ["dep:nostr-sdk"]
|
||||
hardware = ["nusb", "tokio-serial"]
|
||||
channel-matrix = ["dep:matrix-sdk"]
|
||||
@ -254,30 +250,8 @@ rag-pdf = ["dep:pdf-extract"]
|
||||
skill-creation = []
|
||||
# whatsapp-web = Native WhatsApp Web client with custom rusqlite storage backend
|
||||
whatsapp-web = ["dep:wa-rs", "dep:wa-rs-core", "dep:wa-rs-binary", "dep:wa-rs-proto", "dep:wa-rs-ureq-http", "dep:wa-rs-tokio-transport", "dep:serde-big-array", "dep:prost", "dep:qrcode"]
|
||||
# voice-wake = Voice wake word detection via microphone (cpal)
|
||||
voice-wake = ["dep:cpal"]
|
||||
# WASM plugin system (extism-based)
|
||||
plugins-wasm = ["dep:extism"]
|
||||
# Meta-feature for CI: all features except those requiring system C libraries
|
||||
# not available on standard CI runners (e.g., voice-wake needs libasound2-dev).
|
||||
ci-all = [
|
||||
"channel-nostr",
|
||||
"hardware",
|
||||
"channel-matrix",
|
||||
"channel-lark",
|
||||
"memory-postgres",
|
||||
"observability-prometheus",
|
||||
"observability-otel",
|
||||
"peripheral-rpi",
|
||||
"browser-native",
|
||||
"sandbox-landlock",
|
||||
"sandbox-bubblewrap",
|
||||
"probe",
|
||||
"rag-pdf",
|
||||
"skill-creation",
|
||||
"whatsapp-web",
|
||||
"plugins-wasm",
|
||||
]
|
||||
|
||||
[profile.release]
|
||||
opt-level = "z" # Optimize for size
|
||||
|
||||
14
Dockerfile
@ -12,7 +12,7 @@ RUN npm run build
|
||||
FROM rust:1.94-slim@sha256:da9dab7a6b8dd428e71718402e97207bb3e54167d37b5708616050b1e8f60ed6 AS builder
|
||||
|
||||
WORKDIR /app
|
||||
ARG ZEROCLAW_CARGO_FEATURES="memory-postgres,channel-lark"
|
||||
ARG ZEROCLAW_CARGO_FEATURES="memory-postgres"
|
||||
|
||||
# Install build dependencies
|
||||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
@ -23,11 +23,9 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
|
||||
# 1. Copy manifests to cache dependencies
|
||||
COPY Cargo.toml Cargo.lock ./
|
||||
# Include every workspace member: Cargo.lock is generated for the full workspace.
|
||||
# Previously we used sed to drop `crates/robot-kit`, which made the manifest disagree
|
||||
# with the lockfile and caused `cargo --locked` to fail (Cargo refused to rewrite the lock).
|
||||
COPY crates/robot-kit/ crates/robot-kit/
|
||||
COPY crates/aardvark-sys/ crates/aardvark-sys/
|
||||
# Remove robot-kit from workspace members — it is excluded by .dockerignore
|
||||
# and is not needed for the Docker build (hardware-only crate).
|
||||
RUN sed -i 's/members = \[".", "crates\/robot-kit"\]/members = ["."]/' Cargo.toml
|
||||
# Create dummy targets declared in Cargo.toml so manifest parsing succeeds.
|
||||
RUN mkdir -p src benches \
|
||||
&& echo "fn main() {}" > src/main.rs \
|
||||
@ -79,10 +77,6 @@ RUN mkdir -p /zeroclaw-data/.zeroclaw /zeroclaw-data/workspace && \
|
||||
'port = 42617' \
|
||||
'host = "[::]"' \
|
||||
'allow_public_bind = true' \
|
||||
'' \
|
||||
'[autonomy]' \
|
||||
'level = "supervised"' \
|
||||
'auto_approve = ["file_read", "file_write", "file_edit", "memory_recall", "memory_store", "web_search_tool", "web_fetch", "calculator", "glob_search", "content_search", "image_info", "weather", "git_operations"]' \
|
||||
> /zeroclaw-data/.zeroclaw/config.toml && \
|
||||
chown -R 65534:65534 /zeroclaw-data
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ RUN npm run build
|
||||
FROM rust:1.94-bookworm AS builder
|
||||
|
||||
WORKDIR /app
|
||||
ARG ZEROCLAW_CARGO_FEATURES="memory-postgres,channel-lark"
|
||||
ARG ZEROCLAW_CARGO_FEATURES="memory-postgres"
|
||||
|
||||
# Install build dependencies
|
||||
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
@ -38,10 +38,9 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
||||
|
||||
# 1. Copy manifests to cache dependencies
|
||||
COPY Cargo.toml Cargo.lock ./
|
||||
# Include every workspace member: Cargo.lock is generated for the full workspace.
|
||||
# Previously we used sed to drop `crates/robot-kit`, which made the manifest disagree
|
||||
# with the lockfile and caused `cargo --locked` to fail (Cargo refused to rewrite the lock).
|
||||
COPY crates/robot-kit/ crates/robot-kit/
|
||||
# Remove robot-kit from workspace members — it is excluded by .dockerignore
|
||||
# and is not needed for the Docker build (hardware-only crate).
|
||||
RUN sed -i 's/members = \[".", "crates\/robot-kit"\]/members = ["."]/' Cargo.toml
|
||||
# Create dummy targets declared in Cargo.toml so manifest parsing succeeds.
|
||||
RUN mkdir -p src benches \
|
||||
&& echo "fn main() {}" > src/main.rs \
|
||||
@ -89,10 +88,6 @@ RUN mkdir -p /zeroclaw-data/.zeroclaw /zeroclaw-data/workspace && \
|
||||
'port = 42617' \
|
||||
'host = "[::]"' \
|
||||
'allow_public_bind = true' \
|
||||
'' \
|
||||
'[autonomy]' \
|
||||
'level = "supervised"' \
|
||||
'auto_approve = ["file_read", "file_write", "file_edit", "memory_recall", "memory_store", "web_search_tool", "web_fetch", "calculator", "glob_search", "content_search", "image_info", "weather", "git_operations"]' \
|
||||
> /zeroclaw-data/.zeroclaw/config.toml && \
|
||||
chown -R 65534:65534 /zeroclaw-data
|
||||
|
||||
|
||||
15
NOTICE
@ -41,18 +41,3 @@ This project uses third-party libraries and components,
|
||||
each licensed under their respective terms.
|
||||
|
||||
See Cargo.lock for a complete dependency list.
|
||||
|
||||
Verifiable Intent Specification
|
||||
================================
|
||||
|
||||
The src/verifiable_intent/ module is a Rust-native reimplementation based on
|
||||
the Verifiable Intent open specification and reference implementation:
|
||||
|
||||
Project: Verifiable Intent (VI)
|
||||
Author: agent-intent
|
||||
Source: https://github.com/agent-intent/verifiable-intent
|
||||
License: Apache License, Version 2.0
|
||||
|
||||
This implementation follows the VI specification design (SD-JWT layered
|
||||
credentials, constraint model, three-layer chain). No source code was copied
|
||||
from the reference implementation.
|
||||
|
||||
41
README.ar.md
@ -324,6 +324,47 @@ ls -lh target/release/zeroclaw
|
||||
- CI/CD: تجريبي (تلقائي عند الدفع) → مستقر (إرسال يدوي) → Docker، crates.io، Scoop، AUR، Homebrew، تغريدة.
|
||||
- ملفات ثنائية مُعدة مسبقًا لـ Linux (x86_64، aarch64، armv7)، macOS (x86_64، aarch64)، Windows (x86_64).
|
||||
|
||||
## كيف يعمل (باختصار)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## التكوين
|
||||
|
||||
|
||||
41
README.bn.md
@ -324,6 +324,47 @@ React 19 + Vite 6 + Tailwind CSS 4 ওয়েব ড্যাশবোর্
|
||||
- CI/CD: বেটা (পুশে অটো) → স্টেবল (ম্যানুয়াল ডিসপ্যাচ) → Docker, crates.io, Scoop, AUR, Homebrew, টুইট।
|
||||
- Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64) এর জন্য প্রি-বিল্ট বাইনারি।
|
||||
|
||||
## এটি কিভাবে কাজ করে (সংক্ষিপ্ত)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## কনফিগারেশন
|
||||
|
||||
|
||||
41
README.cs.md
@ -324,6 +324,47 @@ Webový panel React 19 + Vite 6 + Tailwind CSS 4 servírovaný přímo z Gateway
|
||||
- CI/CD: beta (auto na push) → stable (ruční dispatch) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Předpřipravené binárky pro Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## Jak to funguje (krátce)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Konfigurace
|
||||
|
||||
|
||||
41
README.da.md
@ -324,6 +324,47 @@ React 19 + Vite 6 + Tailwind CSS 4 web-dashboard serveret direkte fra Gateway'en
|
||||
- CI/CD: beta (auto on push) → stable (manual dispatch) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Forhaandsbyggede binaerer til Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## Saadan virker det (kort)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Konfiguration
|
||||
|
||||
|
||||
41
README.de.md
@ -324,6 +324,47 @@ React 19 + Vite 6 + Tailwind CSS 4 Web-Dashboard, direkt vom Gateway bereitgeste
|
||||
- CI/CD: beta (automatisch bei Push) → stable (manueller Dispatch) → Docker, crates.io, Scoop, AUR, Homebrew, Tweet.
|
||||
- Vorgefertigte Binaries für Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## Wie es funktioniert (kurz)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (Steuerungsebene) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web-Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Ratenbegrenzung │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Konfiguration
|
||||
|
||||
|
||||
41
README.el.md
@ -324,6 +324,47 @@ ls -lh target/release/zeroclaw
|
||||
- CI/CD: beta (auto on push) → stable (manual dispatch) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Προκατασκευασμένα δυαδικά για Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## Πώς λειτουργεί (σύντομα)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Ρύθμιση παραμέτρων
|
||||
|
||||
|
||||
41
README.es.md
@ -324,6 +324,47 @@ Panel web React 19 + Vite 6 + Tailwind CSS 4 servido directamente desde el Gatew
|
||||
- CI/CD: beta (automático al hacer push) → stable (dispatch manual) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Binarios preconstruidos para Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## Cómo funciona (resumen)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (plano de control) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Panel Web (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Emparejamiento + Limitación │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Configuración
|
||||
|
||||
|
||||
41
README.fi.md
@ -324,6 +324,47 @@ React 19 + Vite 6 + Tailwind CSS 4 web-hallintapaneeli, jota tarjoillaan suoraan
|
||||
- CI/CD: beta (auto on push) → stable (manual dispatch) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Valmiit binaarit Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## Miten se toimii (lyhyesti)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Maaritykset
|
||||
|
||||
|
||||
41
README.fr.md
@ -324,6 +324,47 @@ Tableau de bord web React 19 + Vite 6 + Tailwind CSS 4 servi directement depuis
|
||||
- CI/CD : beta (automatique au push) → stable (dispatch manuel) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Binaires précompilés pour Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## Comment ça fonctionne (résumé)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (plan de contrôle) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Tableau de bord (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Appairage + Limitation │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
|
||||
41
README.he.md
@ -324,6 +324,47 @@ ls -lh target/release/zeroclaw
|
||||
- CI/CD: בטא (אוטומטי בדחיפה) → יציב (שליחה ידנית) → Docker, crates.io, Scoop, AUR, Homebrew, ציוץ.
|
||||
- בינאריים מוכנים מראש ל-Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## איך זה עובד (בקצרה)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## הגדרות
|
||||
|
||||
|
||||
41
README.hi.md
@ -324,6 +324,47 @@ React 19 + Vite 6 + Tailwind CSS 4 वेब डैशबोर्ड सीध
|
||||
- CI/CD: बीटा (पुश पर ऑटो) → स्टेबल (मैनुअल डिस्पैच) → Docker, crates.io, Scoop, AUR, Homebrew, ट्वीट।
|
||||
- Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64) के लिए प्री-बिल्ट बाइनरी।
|
||||
|
||||
## यह कैसे काम करता है (संक्षिप्त)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## कॉन्फ़िगरेशन
|
||||
|
||||
|
||||
41
README.hu.md
@ -324,6 +324,47 @@ React 19 + Vite 6 + Tailwind CSS 4 webes vezerlopult, amelyet kozvetlenul a Gate
|
||||
- CI/CD: beta (auto on push) → stable (manual dispatch) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Elore elkeszitett binarisok Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64) rendszerekhez.
|
||||
|
||||
## Hogyan mukodik (roviden)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Konfiguracio
|
||||
|
||||
|
||||
41
README.id.md
@ -324,6 +324,47 @@ Dasbor web React 19 + Vite 6 + Tailwind CSS 4 yang disajikan langsung dari Gatew
|
||||
- CI/CD: beta (otomatis saat push) → stable (dispatch manual) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Biner pre-built untuk Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## Cara kerjanya (singkat)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Konfigurasi
|
||||
|
||||
|
||||
41
README.it.md
@ -324,6 +324,47 @@ Dashboard web React 19 + Vite 6 + Tailwind CSS 4 servita direttamente dal Gatewa
|
||||
- CI/CD: beta (automatico al push) → stable (dispatch manuale) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Binari precompilati per Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## Come funziona (sintesi)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (piano di controllo) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Dashboard Web (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Accoppiamento + Limitazione │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Configurazione
|
||||
|
||||
|
||||
41
README.ja.md
@ -324,6 +324,47 @@ React 19 + Vite 6 + Tailwind CSS 4 ウェブダッシュボード、Gatewayか
|
||||
- CI/CD:beta(プッシュ時自動)→ stable(手動ディスパッチ)→ Docker、crates.io、Scoop、AUR、Homebrew、tweet。
|
||||
- プリビルドバイナリ:Linux(x86_64、aarch64、armv7)、macOS(x86_64、aarch64)、Windows(x86_64)。
|
||||
|
||||
## 仕組み(概要)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## 設定
|
||||
|
||||
|
||||
41
README.ko.md
@ -324,6 +324,47 @@ Gateway에서 직접 제공하는 React 19 + Vite 6 + Tailwind CSS 4 웹 대시
|
||||
- CI/CD: beta (push 시 자동) → stable (수동 디스패치) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64)용 사전 빌드 바이너리.
|
||||
|
||||
## 작동 방식 (요약)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## 구성
|
||||
|
||||
|
||||
43
README.md
@ -300,7 +300,7 @@ React 19 + Vite 6 + Tailwind CSS 4 web dashboard served directly from the Gatewa
|
||||
|
||||
- **Core:** shell, file read/write/edit, git operations, glob search, content search
|
||||
- **Web:** browser control, web fetch, web search, screenshot, image info, PDF read
|
||||
- **Integrations:** Jira, Notion, Google Workspace, Microsoft 365, LinkedIn, Composio, Pushover, Weather (wttr.in)
|
||||
- **Integrations:** Jira, Notion, Google Workspace, Microsoft 365, LinkedIn, Composio, Pushover
|
||||
- **MCP:** Model Context Protocol tool wrapper + deferred tool sets
|
||||
- **Scheduling:** cron add/remove/update/run, schedule tool
|
||||
- **Memory:** recall, store, forget, knowledge, project intel
|
||||
@ -324,6 +324,47 @@ React 19 + Vite 6 + Tailwind CSS 4 web dashboard served directly from the Gatewa
|
||||
- CI/CD: beta (auto on push) → stable (manual dispatch) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Pre-built binaries for Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## How it works (short)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
|
||||
41
README.nb.md
@ -324,6 +324,47 @@ React 19 + Vite 6 + Tailwind CSS 4 nettbasert dashbord servert direkte fra Gatew
|
||||
- CI/CD: beta (auto pa push) -> stabil (manuell utsendelse) -> Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Forhandsbygde binarfiler for Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## Slik fungerer det (kort)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (kontrollplan) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Nettbasert dashbord (React 19)│
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Paring + Hastighetsbegrensning│
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Sloyfe │ │Planleg.│ │ Sverm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Leveran.│ │Verktoy │ │ Minne │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Sikker- │ │Periferiutst│
|
||||
│ het │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Konfigurasjon
|
||||
|
||||
|
||||
41
README.nl.md
@ -324,6 +324,47 @@ React 19 + Vite 6 + Tailwind CSS 4 webdashboard geserveerd direct vanuit de Gate
|
||||
- CI/CD: beta (auto bij push) → stable (handmatige dispatch) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Voorgebouwde binaries voor Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## Hoe het werkt (kort)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Configuratie
|
||||
|
||||
|
||||
41
README.pl.md
@ -324,6 +324,47 @@ Panel webowy React 19 + Vite 6 + Tailwind CSS 4 serwowany bezpośrednio z Gatewa
|
||||
- CI/CD: beta (auto na push) → stable (ręczny dispatch) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Gotowe pliki binarne dla Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## Jak to działa (w skrócie)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Konfiguracja
|
||||
|
||||
|
||||
41
README.pt.md
@ -324,6 +324,47 @@ Painel web React 19 + Vite 6 + Tailwind CSS 4 servido diretamente pelo Gateway:
|
||||
- CI/CD: beta (automático no push) → stable (dispatch manual) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Binários pré-construídos para Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## Como funciona (resumo)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (plano de controle) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Painel Web (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pareamento + Limitação │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Configuração
|
||||
|
||||
|
||||
41
README.ro.md
@ -324,6 +324,47 @@ Panou web React 19 + Vite 6 + Tailwind CSS 4 servit direct din Gateway:
|
||||
- CI/CD: beta (automat la push) → stable (dispatch manual) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Binare pre-construite pentru Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## Cum funcționează (pe scurt)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Configurare
|
||||
|
||||
|
||||
41
README.ru.md
@ -324,6 +324,47 @@ ls -lh target/release/zeroclaw
|
||||
- CI/CD: бета (авто при push) → стабильный (ручной запуск) → Docker, crates.io, Scoop, AUR, Homebrew, твит.
|
||||
- Предсобранные бинарные файлы для Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## Как это работает (кратко)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Конфигурация
|
||||
|
||||
|
||||
41
README.sv.md
@ -324,6 +324,47 @@ React 19 + Vite 6 + Tailwind CSS 4 webbpanel serverad direkt från Gateway:
|
||||
- CI/CD: beta (automatiskt vid push) → stable (manuell dispatch) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Förbyggda binärer för Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## Hur det fungerar (kort)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (kontrollplan) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Webbpanel (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Parkoppling + Hastighetsbegränsning │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Konfiguration
|
||||
|
||||
|
||||
41
README.th.md
@ -324,6 +324,47 @@ Feature-gated: Matrix (`channel-matrix`), Lark (`channel-lark`), Nostr (`channel
|
||||
- CI/CD: beta (อัตโนมัติเมื่อ push) → stable (dispatch แบบ manual) → Docker, crates.io, Scoop, AUR, Homebrew, tweet
|
||||
- ไบนารี pre-built สำหรับ Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64)
|
||||
|
||||
## วิธีการทำงาน (สั้น)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## การกำหนดค่า
|
||||
|
||||
|
||||
41
README.tl.md
@ -324,6 +324,47 @@ React 19 + Vite 6 + Tailwind CSS 4 web dashboard na direktang inihahatid mula sa
|
||||
- CI/CD: beta (auto sa push) → stable (manual dispatch) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Pre-built binaries para sa Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## Paano gumagana (maikli)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
|
||||
41
README.tr.md
@ -324,6 +324,47 @@ Gateway'den doğrudan sunulan React 19 + Vite 6 + Tailwind CSS 4 web paneli:
|
||||
- CI/CD: beta (push'ta otomatik) → stable (manuel dispatch) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64) için önceden derlenmiş ikili dosyalar.
|
||||
|
||||
## Nasıl çalışır (kısaca)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Yapılandırma
|
||||
|
||||
|
||||
41
README.uk.md
@ -324,6 +324,47 @@ ls -lh target/release/zeroclaw
|
||||
- CI/CD: beta (автоматично при push) → stable (ручний запуск) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Попередньо зібрані бінарні файли для Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## Як це працює (коротко)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Конфігурація
|
||||
|
||||
|
||||
41
README.ur.md
@ -324,6 +324,47 @@ Gateway سے براہ راست فراہم کردہ React 19 + Vite 6 + Tailwind
|
||||
- CI/CD: beta (push پر خودکار) → stable (دستی dispatch) → Docker، crates.io، Scoop، AUR، Homebrew، tweet۔
|
||||
- Linux (x86_64، aarch64، armv7)، macOS (x86_64، aarch64)، Windows (x86_64) کے لیے پری بلٹ بائنریز۔
|
||||
|
||||
## یہ کیسے کام کرتا ہے (مختصر)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## کنفیگریشن
|
||||
|
||||
|
||||
41
README.vi.md
@ -324,6 +324,47 @@ Bảng điều khiển web React 19 + Vite 6 + Tailwind CSS 4 được phục v
|
||||
- CI/CD: beta (tự động khi push) → stable (dispatch thủ công) → Docker, crates.io, Scoop, AUR, Homebrew, tweet.
|
||||
- Binary dựng sẵn cho Linux (x86_64, aarch64, armv7), macOS (x86_64, aarch64), Windows (x86_64).
|
||||
|
||||
## Cách hoạt động (tóm tắt)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## Cấu hình
|
||||
|
||||
|
||||
@ -324,6 +324,47 @@ React 19 + Vite 6 + Tailwind CSS 4 网页仪表板直接从 Gateway 提供:
|
||||
- CI/CD:beta(推送时自动)→ stable(手动触发)→ Docker、crates.io、Scoop、AUR、Homebrew、tweet。
|
||||
- 预构建二进制文件支持 Linux(x86_64、aarch64、armv7)、macOS(x86_64、aarch64)、Windows(x86_64)。
|
||||
|
||||
## 工作原理(简述)
|
||||
|
||||
```
|
||||
WhatsApp / Telegram / Slack / Discord / Signal / iMessage / Matrix / IRC / Email
|
||||
Bluesky / Nostr / Mattermost / DingTalk / Lark / QQ / Reddit / MQTT / WebSocket
|
||||
│
|
||||
▼
|
||||
┌───────────────────────────────┐
|
||||
│ Gateway │
|
||||
│ (control plane) │
|
||||
│ http://127.0.0.1:42617 │
|
||||
├───────────────────────────────┤
|
||||
│ Web Dashboard (React 19) │
|
||||
│ REST API + WebSocket + SSE │
|
||||
│ Pairing + Rate Limiting │
|
||||
└──────────────┬────────────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│ Agent │ │ Cron │ │ Hands │
|
||||
│ Loop │ │Scheduler│ │ Swarm │
|
||||
└───┬────┘ └───┬────┘ └───┬────┘
|
||||
│ │ │
|
||||
└──────────┼──────────┘
|
||||
│
|
||||
┌──────────┼──────────┐
|
||||
│ │ │
|
||||
▼ ▼ ▼
|
||||
┌────────┐ ┌────────┐ ┌────────┐
|
||||
│Provider│ │ Tools │ │ Memory │
|
||||
│ (LLM) │ │ (70+) │ │(md/sql)│
|
||||
└────────┘ └────────┘ └────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌────────┐ ┌────────────┐
|
||||
│Security│ │ Peripherals│
|
||||
│ Policy │ │(ESP32/STM32)│
|
||||
└────────┘ └────────────┘
|
||||
```
|
||||
|
||||
## 配置
|
||||
|
||||
|
||||
@ -1,29 +0,0 @@
|
||||
[package]
|
||||
name = "zeroclaw-desktop"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
description = "ZeroClaw Desktop — Tauri-powered system tray app"
|
||||
publish = false
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.0", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "2.0", features = ["tray-icon", "image-png"] }
|
||||
tauri-plugin-shell = "2.0"
|
||||
tauri-plugin-store = "2.0"
|
||||
tauri-plugin-single-instance = "2.0"
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
|
||||
tokio = { version = "1.50", features = ["rt-multi-thread", "macros", "sync", "time"] }
|
||||
anyhow = "1.0"
|
||||
|
||||
[target.'cfg(target_os = "macos")'.dependencies]
|
||||
objc2 = "0.6"
|
||||
objc2-app-kit = { version = "0.3", features = ["NSApplication", "NSImage", "NSRunningApplication"] }
|
||||
objc2-foundation = { version = "0.3", features = ["NSData"] }
|
||||
|
||||
[features]
|
||||
default = ["custom-protocol"]
|
||||
custom-protocol = ["tauri/custom-protocol"]
|
||||
@ -1,3 +0,0 @@
|
||||
fn main() {
|
||||
tauri_build::build();
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "default",
|
||||
"description": "Default capability set for ZeroClaw Desktop",
|
||||
"windows": ["main"],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"shell:allow-open",
|
||||
"store:allow-get",
|
||||
"store:allow-set",
|
||||
"store:allow-save",
|
||||
"store:allow-load"
|
||||
]
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
{
|
||||
"identifier": "desktop",
|
||||
"description": "Desktop-specific permissions for ZeroClaw",
|
||||
"windows": ["main"],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"shell:allow-open",
|
||||
"shell:allow-execute",
|
||||
"store:allow-get",
|
||||
"store:allow-set",
|
||||
"store:allow-save",
|
||||
"store:allow-load"
|
||||
]
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
{
|
||||
"identifier": "mobile",
|
||||
"description": "Mobile-specific permissions for ZeroClaw",
|
||||
"windows": ["main"],
|
||||
"permissions": [
|
||||
"core:default"
|
||||
]
|
||||
}
|
||||
|
Before Width: | Height: | Size: 1002 B |
|
Before Width: | Height: | Size: 243 B |
|
Before Width: | Height: | Size: 243 B |
@ -1,4 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 128 128">
|
||||
<rect width="128" height="128" rx="16" fill="#DC322F"/>
|
||||
<text x="64" y="80" font-size="64" font-family="monospace" font-weight="bold" fill="white" text-anchor="middle">Z</text>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 251 B |
|
Before Width: | Height: | Size: 199 B |
|
Before Width: | Height: | Size: 208 B |
|
Before Width: | Height: | Size: 168 B |
|
Before Width: | Height: | Size: 201 B |
@ -1,17 +0,0 @@
|
||||
use crate::gateway_client::GatewayClient;
|
||||
use crate::state::SharedState;
|
||||
use tauri::State;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn send_message(
|
||||
state: State<'_, SharedState>,
|
||||
message: String,
|
||||
) -> Result<serde_json::Value, String> {
|
||||
let s = state.read().await;
|
||||
let client = GatewayClient::new(&s.gateway_url, s.token.as_deref());
|
||||
drop(s);
|
||||
client
|
||||
.send_webhook_message(&message)
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
@ -1,11 +0,0 @@
|
||||
use crate::gateway_client::GatewayClient;
|
||||
use crate::state::SharedState;
|
||||
use tauri::State;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn list_channels(state: State<'_, SharedState>) -> Result<serde_json::Value, String> {
|
||||
let s = state.read().await;
|
||||
let client = GatewayClient::new(&s.gateway_url, s.token.as_deref());
|
||||
drop(s);
|
||||
client.get_status().await.map_err(|e| e.to_string())
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
use crate::gateway_client::GatewayClient;
|
||||
use crate::state::SharedState;
|
||||
use tauri::State;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_status(state: State<'_, SharedState>) -> Result<serde_json::Value, String> {
|
||||
let s = state.read().await;
|
||||
let client = GatewayClient::new(&s.gateway_url, s.token.as_deref());
|
||||
drop(s);
|
||||
client.get_status().await.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_health(state: State<'_, SharedState>) -> Result<bool, String> {
|
||||
let s = state.read().await;
|
||||
let client = GatewayClient::new(&s.gateway_url, s.token.as_deref());
|
||||
drop(s);
|
||||
client.get_health().await.map_err(|e| e.to_string())
|
||||
}
|
||||
@ -1,4 +0,0 @@
|
||||
pub mod agent;
|
||||
pub mod channels;
|
||||
pub mod gateway;
|
||||
pub mod pairing;
|
||||
@ -1,19 +0,0 @@
|
||||
use crate::gateway_client::GatewayClient;
|
||||
use crate::state::SharedState;
|
||||
use tauri::State;
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn initiate_pairing(state: State<'_, SharedState>) -> Result<serde_json::Value, String> {
|
||||
let s = state.read().await;
|
||||
let client = GatewayClient::new(&s.gateway_url, s.token.as_deref());
|
||||
drop(s);
|
||||
client.initiate_pairing().await.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_devices(state: State<'_, SharedState>) -> Result<serde_json::Value, String> {
|
||||
let s = state.read().await;
|
||||
let client = GatewayClient::new(&s.gateway_url, s.token.as_deref());
|
||||
drop(s);
|
||||
client.get_devices().await.map_err(|e| e.to_string())
|
||||
}
|
||||
@ -1,213 +0,0 @@
|
||||
//! HTTP client for communicating with the ZeroClaw gateway.
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
|
||||
pub struct GatewayClient {
|
||||
pub(crate) base_url: String,
|
||||
pub(crate) token: Option<String>,
|
||||
client: reqwest::Client,
|
||||
}
|
||||
|
||||
impl GatewayClient {
|
||||
pub fn new(base_url: &str, token: Option<&str>) -> Self {
|
||||
let client = reqwest::Client::builder()
|
||||
.timeout(std::time::Duration::from_secs(10))
|
||||
.build()
|
||||
.unwrap_or_default();
|
||||
Self {
|
||||
base_url: base_url.to_string(),
|
||||
token: token.map(String::from),
|
||||
client,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn auth_header(&self) -> Option<String> {
|
||||
self.token.as_ref().map(|t| format!("Bearer {t}"))
|
||||
}
|
||||
|
||||
pub async fn get_status(&self) -> Result<serde_json::Value> {
|
||||
let mut req = self.client.get(format!("{}/api/status", self.base_url));
|
||||
if let Some(auth) = self.auth_header() {
|
||||
req = req.header("Authorization", auth);
|
||||
}
|
||||
let resp = req.send().await.context("status request failed")?;
|
||||
Ok(resp.json().await?)
|
||||
}
|
||||
|
||||
pub async fn get_health(&self) -> Result<bool> {
|
||||
match self
|
||||
.client
|
||||
.get(format!("{}/health", self.base_url))
|
||||
.send()
|
||||
.await
|
||||
{
|
||||
Ok(resp) => Ok(resp.status().is_success()),
|
||||
Err(_) => Ok(false),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_devices(&self) -> Result<serde_json::Value> {
|
||||
let mut req = self.client.get(format!("{}/api/devices", self.base_url));
|
||||
if let Some(auth) = self.auth_header() {
|
||||
req = req.header("Authorization", auth);
|
||||
}
|
||||
let resp = req.send().await.context("devices request failed")?;
|
||||
Ok(resp.json().await?)
|
||||
}
|
||||
|
||||
pub async fn initiate_pairing(&self) -> Result<serde_json::Value> {
|
||||
let mut req = self
|
||||
.client
|
||||
.post(format!("{}/api/pairing/initiate", self.base_url));
|
||||
if let Some(auth) = self.auth_header() {
|
||||
req = req.header("Authorization", auth);
|
||||
}
|
||||
let resp = req.send().await.context("pairing request failed")?;
|
||||
Ok(resp.json().await?)
|
||||
}
|
||||
|
||||
/// Check whether the gateway requires pairing.
|
||||
pub async fn requires_pairing(&self) -> Result<bool> {
|
||||
let resp = self
|
||||
.client
|
||||
.get(format!("{}/health", self.base_url))
|
||||
.send()
|
||||
.await
|
||||
.context("health request failed")?;
|
||||
let body: serde_json::Value = resp.json().await?;
|
||||
Ok(body["require_pairing"].as_bool().unwrap_or(false))
|
||||
}
|
||||
|
||||
/// Request a new pairing code from the gateway (localhost-only admin endpoint).
|
||||
pub async fn request_new_paircode(&self) -> Result<String> {
|
||||
let resp = self
|
||||
.client
|
||||
.post(format!("{}/admin/paircode/new", self.base_url))
|
||||
.send()
|
||||
.await
|
||||
.context("paircode request failed")?;
|
||||
let body: serde_json::Value = resp.json().await?;
|
||||
body["pairing_code"]
|
||||
.as_str()
|
||||
.map(String::from)
|
||||
.context("no pairing_code in response")
|
||||
}
|
||||
|
||||
/// Exchange a pairing code for a bearer token.
|
||||
pub async fn pair_with_code(&self, code: &str) -> Result<String> {
|
||||
let resp = self
|
||||
.client
|
||||
.post(format!("{}/pair", self.base_url))
|
||||
.header("X-Pairing-Code", code)
|
||||
.send()
|
||||
.await
|
||||
.context("pair request failed")?;
|
||||
if !resp.status().is_success() {
|
||||
anyhow::bail!("pair request returned {}", resp.status());
|
||||
}
|
||||
let body: serde_json::Value = resp.json().await?;
|
||||
body["token"]
|
||||
.as_str()
|
||||
.map(String::from)
|
||||
.context("no token in pair response")
|
||||
}
|
||||
|
||||
/// Validate an existing token by calling a protected endpoint.
|
||||
pub async fn validate_token(&self) -> Result<bool> {
|
||||
let mut req = self.client.get(format!("{}/api/status", self.base_url));
|
||||
if let Some(auth) = self.auth_header() {
|
||||
req = req.header("Authorization", auth);
|
||||
}
|
||||
match req.send().await {
|
||||
Ok(resp) => Ok(resp.status().is_success()),
|
||||
Err(_) => Ok(false),
|
||||
}
|
||||
}
|
||||
|
||||
/// Auto-pair with the gateway: request a new code and exchange it for a token.
|
||||
pub async fn auto_pair(&self) -> Result<String> {
|
||||
let code = self.request_new_paircode().await?;
|
||||
self.pair_with_code(&code).await
|
||||
}
|
||||
|
||||
pub async fn send_webhook_message(&self, message: &str) -> Result<serde_json::Value> {
|
||||
let mut req = self
|
||||
.client
|
||||
.post(format!("{}/webhook", self.base_url))
|
||||
.json(&serde_json::json!({ "message": message }));
|
||||
if let Some(auth) = self.auth_header() {
|
||||
req = req.header("Authorization", auth);
|
||||
}
|
||||
let resp = req.send().await.context("webhook request failed")?;
|
||||
Ok(resp.json().await?)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn client_creation_no_token() {
|
||||
let client = GatewayClient::new("http://127.0.0.1:42617", None);
|
||||
assert_eq!(client.base_url, "http://127.0.0.1:42617");
|
||||
assert!(client.token.is_none());
|
||||
assert!(client.auth_header().is_none());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn client_creation_with_token() {
|
||||
let client = GatewayClient::new("http://localhost:8080", Some("test-token"));
|
||||
assert_eq!(client.base_url, "http://localhost:8080");
|
||||
assert_eq!(client.token.as_deref(), Some("test-token"));
|
||||
assert_eq!(client.auth_header().unwrap(), "Bearer test-token");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn client_custom_url() {
|
||||
let client = GatewayClient::new("https://zeroclaw.example.com:9999", None);
|
||||
assert_eq!(client.base_url, "https://zeroclaw.example.com:9999");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn auth_header_format() {
|
||||
let client = GatewayClient::new("http://localhost", Some("zc_abc123"));
|
||||
assert_eq!(client.auth_header().unwrap(), "Bearer zc_abc123");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn health_returns_false_for_unreachable_host() {
|
||||
// Connect to a port that should not be listening.
|
||||
let client = GatewayClient::new("http://127.0.0.1:1", None);
|
||||
let result = client.get_health().await.unwrap();
|
||||
assert!(!result, "health should be false for unreachable host");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn status_fails_for_unreachable_host() {
|
||||
let client = GatewayClient::new("http://127.0.0.1:1", None);
|
||||
let result = client.get_status().await;
|
||||
assert!(result.is_err(), "status should fail for unreachable host");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn devices_fails_for_unreachable_host() {
|
||||
let client = GatewayClient::new("http://127.0.0.1:1", None);
|
||||
let result = client.get_devices().await;
|
||||
assert!(result.is_err(), "devices should fail for unreachable host");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn pairing_fails_for_unreachable_host() {
|
||||
let client = GatewayClient::new("http://127.0.0.1:1", None);
|
||||
let result = client.initiate_pairing().await;
|
||||
assert!(result.is_err(), "pairing should fail for unreachable host");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn webhook_fails_for_unreachable_host() {
|
||||
let client = GatewayClient::new("http://127.0.0.1:1", None);
|
||||
let result = client.send_webhook_message("hello").await;
|
||||
assert!(result.is_err(), "webhook should fail for unreachable host");
|
||||
}
|
||||
}
|
||||
@ -1,40 +0,0 @@
|
||||
//! Background health polling for the ZeroClaw gateway.
|
||||
|
||||
use crate::gateway_client::GatewayClient;
|
||||
use crate::state::SharedState;
|
||||
use crate::tray::icon;
|
||||
use std::time::Duration;
|
||||
use tauri::{AppHandle, Emitter, Runtime};
|
||||
|
||||
const POLL_INTERVAL: Duration = Duration::from_secs(5);
|
||||
|
||||
/// Spawn a background task that polls gateway health and updates state + tray.
|
||||
pub fn spawn_health_poller<R: Runtime>(app: AppHandle<R>, state: SharedState) {
|
||||
tauri::async_runtime::spawn(async move {
|
||||
loop {
|
||||
let (url, token) = {
|
||||
let s = state.read().await;
|
||||
(s.gateway_url.clone(), s.token.clone())
|
||||
};
|
||||
|
||||
let client = GatewayClient::new(&url, token.as_deref());
|
||||
let healthy = client.get_health().await.unwrap_or(false);
|
||||
|
||||
let (connected, agent_status) = {
|
||||
let mut s = state.write().await;
|
||||
s.connected = healthy;
|
||||
(s.connected, s.agent_status)
|
||||
};
|
||||
|
||||
// Update the tray icon and tooltip to reflect current state.
|
||||
if let Some(tray) = app.tray_by_id("main") {
|
||||
let _ = tray.set_icon(Some(icon::icon_for_state(connected, agent_status)));
|
||||
let _ = tray.set_tooltip(Some(icon::tooltip_for_state(connected, agent_status)));
|
||||
}
|
||||
|
||||
let _ = app.emit("zeroclaw://status-changed", healthy);
|
||||
|
||||
tokio::time::sleep(POLL_INTERVAL).await;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -1,136 +0,0 @@
|
||||
//! ZeroClaw Desktop — Tauri application library.
|
||||
|
||||
pub mod commands;
|
||||
pub mod gateway_client;
|
||||
pub mod health;
|
||||
pub mod state;
|
||||
pub mod tray;
|
||||
|
||||
use gateway_client::GatewayClient;
|
||||
use state::shared_state;
|
||||
use tauri::{Manager, RunEvent};
|
||||
|
||||
/// Attempt to auto-pair with the gateway so the WebView has a valid token
|
||||
/// before the React frontend mounts. Runs on localhost so the admin endpoints
|
||||
/// are accessible without auth.
|
||||
async fn auto_pair(state: &state::SharedState) -> Option<String> {
|
||||
let url = {
|
||||
let s = state.read().await;
|
||||
s.gateway_url.clone()
|
||||
};
|
||||
|
||||
let client = GatewayClient::new(&url, None);
|
||||
|
||||
// Check if gateway is reachable and requires pairing.
|
||||
if !client.requires_pairing().await.unwrap_or(false) {
|
||||
return None; // Pairing disabled — no token needed.
|
||||
}
|
||||
|
||||
// Check if we already have a valid token in state.
|
||||
{
|
||||
let s = state.read().await;
|
||||
if let Some(ref token) = s.token {
|
||||
let authed = GatewayClient::new(&url, Some(token));
|
||||
if authed.validate_token().await.unwrap_or(false) {
|
||||
return Some(token.clone()); // Existing token is valid.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No valid token — auto-pair by requesting a new code and exchanging it.
|
||||
let client = GatewayClient::new(&url, None);
|
||||
match client.auto_pair().await {
|
||||
Ok(token) => {
|
||||
let mut s = state.write().await;
|
||||
s.token = Some(token.clone());
|
||||
Some(token)
|
||||
}
|
||||
Err(_) => None, // Gateway may not be ready yet; health poller will retry.
|
||||
}
|
||||
}
|
||||
|
||||
/// Inject a bearer token into the WebView's localStorage so the React app
|
||||
/// skips the pairing dialog. Uses Tauri's WebviewWindow scripting API.
|
||||
fn inject_token_into_webview<R: tauri::Runtime>(window: &tauri::WebviewWindow<R>, token: &str) {
|
||||
let escaped = token.replace('\\', "\\\\").replace('\'', "\\'");
|
||||
let script = format!("localStorage.setItem('zeroclaw_token', '{escaped}')");
|
||||
// WebviewWindow scripting is the standard Tauri API for running JS in the WebView.
|
||||
let _ = window.eval(&script);
|
||||
}
|
||||
|
||||
/// Set the macOS dock icon programmatically so it shows even in dev builds
|
||||
/// (which don't have a proper .app bundle).
|
||||
#[cfg(target_os = "macos")]
|
||||
fn set_dock_icon() {
|
||||
use objc2::{AnyThread, MainThreadMarker};
|
||||
use objc2_app_kit::NSApplication;
|
||||
use objc2_app_kit::NSImage;
|
||||
use objc2_foundation::NSData;
|
||||
|
||||
let icon_bytes = include_bytes!("../icons/128x128.png");
|
||||
// Safety: setup() runs on the main thread in Tauri.
|
||||
let mtm = unsafe { MainThreadMarker::new_unchecked() };
|
||||
let data = NSData::with_bytes(icon_bytes);
|
||||
if let Some(image) = NSImage::initWithData(NSImage::alloc(), &data) {
|
||||
let app = NSApplication::sharedApplication(mtm);
|
||||
unsafe { app.setApplicationIconImage(Some(&image)) };
|
||||
}
|
||||
}
|
||||
|
||||
/// Configure and run the Tauri application.
|
||||
pub fn run() {
|
||||
let shared = shared_state();
|
||||
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.plugin(tauri_plugin_store::Builder::default().build())
|
||||
.plugin(tauri_plugin_single_instance::init(|app, _args, _cwd| {
|
||||
// When a second instance launches, focus the existing window.
|
||||
if let Some(window) = app.get_webview_window("main") {
|
||||
let _ = window.show();
|
||||
let _ = window.set_focus();
|
||||
}
|
||||
}))
|
||||
.manage(shared.clone())
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
commands::gateway::get_status,
|
||||
commands::gateway::get_health,
|
||||
commands::channels::list_channels,
|
||||
commands::pairing::initiate_pairing,
|
||||
commands::pairing::get_devices,
|
||||
commands::agent::send_message,
|
||||
])
|
||||
.setup(move |app| {
|
||||
// Set macOS dock icon (needed for dev builds without .app bundle).
|
||||
#[cfg(target_os = "macos")]
|
||||
set_dock_icon();
|
||||
|
||||
// Set up the system tray.
|
||||
let _ = tray::setup_tray(app);
|
||||
|
||||
// Auto-pair with gateway and inject token into the WebView.
|
||||
let app_handle = app.handle().clone();
|
||||
let pair_state = shared.clone();
|
||||
tauri::async_runtime::spawn(async move {
|
||||
if let Some(token) = auto_pair(&pair_state).await {
|
||||
if let Some(window) = app_handle.get_webview_window("main") {
|
||||
inject_token_into_webview(&window, &token);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Start background health polling.
|
||||
health::spawn_health_poller(app.handle().clone(), shared.clone());
|
||||
|
||||
Ok(())
|
||||
})
|
||||
.build(tauri::generate_context!())
|
||||
.expect("error while building tauri application")
|
||||
.run(|_app, event| {
|
||||
// Keep the app running in the background when all windows are closed.
|
||||
// This is the standard pattern for menu bar / tray apps.
|
||||
if let RunEvent::ExitRequested { api, .. } = event {
|
||||
api.prevent_exit();
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -1,8 +0,0 @@
|
||||
//! ZeroClaw Desktop — main entry point.
|
||||
//!
|
||||
//! Prevents an additional console window on Windows in release.
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
fn main() {
|
||||
zeroclaw_desktop::run();
|
||||
}
|
||||
@ -1,6 +0,0 @@
|
||||
//! Mobile entry point for ZeroClaw Desktop (iOS/Android).
|
||||
|
||||
#[tauri::mobile_entry_point]
|
||||
fn main() {
|
||||
zeroclaw_desktop::run();
|
||||
}
|
||||
@ -1,99 +0,0 @@
|
||||
//! Shared application state for Tauri.
|
||||
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
/// Agent status as reported by the gateway.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
pub enum AgentStatus {
|
||||
Idle,
|
||||
Working,
|
||||
Error,
|
||||
}
|
||||
|
||||
/// Shared application state behind an `Arc<RwLock<_>>`.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct AppState {
|
||||
pub gateway_url: String,
|
||||
pub token: Option<String>,
|
||||
pub connected: bool,
|
||||
pub agent_status: AgentStatus,
|
||||
}
|
||||
|
||||
impl Default for AppState {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
gateway_url: "http://127.0.0.1:42617".to_string(),
|
||||
token: None,
|
||||
connected: false,
|
||||
agent_status: AgentStatus::Idle,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Thread-safe wrapper around `AppState`.
|
||||
pub type SharedState = Arc<RwLock<AppState>>;
|
||||
|
||||
/// Create the default shared state.
|
||||
pub fn shared_state() -> SharedState {
|
||||
Arc::new(RwLock::new(AppState::default()))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn default_state() {
|
||||
let state = AppState::default();
|
||||
assert_eq!(state.gateway_url, "http://127.0.0.1:42617");
|
||||
assert!(state.token.is_none());
|
||||
assert!(!state.connected);
|
||||
assert_eq!(state.agent_status, AgentStatus::Idle);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn shared_state_is_cloneable() {
|
||||
let s1 = shared_state();
|
||||
let s2 = s1.clone();
|
||||
// Both references point to the same allocation.
|
||||
assert!(Arc::ptr_eq(&s1, &s2));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn shared_state_concurrent_read_write() {
|
||||
let state = shared_state();
|
||||
|
||||
// Write from one handle.
|
||||
{
|
||||
let mut s = state.write().await;
|
||||
s.connected = true;
|
||||
s.agent_status = AgentStatus::Working;
|
||||
s.token = Some("zc_test".to_string());
|
||||
}
|
||||
|
||||
// Read from cloned handle.
|
||||
let state2 = state.clone();
|
||||
let s = state2.read().await;
|
||||
assert!(s.connected);
|
||||
assert_eq!(s.agent_status, AgentStatus::Working);
|
||||
assert_eq!(s.token.as_deref(), Some("zc_test"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn agent_status_serialization() {
|
||||
assert_eq!(
|
||||
serde_json::to_string(&AgentStatus::Idle).unwrap(),
|
||||
"\"idle\""
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_string(&AgentStatus::Working).unwrap(),
|
||||
"\"working\""
|
||||
);
|
||||
assert_eq!(
|
||||
serde_json::to_string(&AgentStatus::Error).unwrap(),
|
||||
"\"error\""
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,25 +0,0 @@
|
||||
//! Tray menu event handling.
|
||||
|
||||
use tauri::{menu::MenuEvent, AppHandle, Manager, Runtime};
|
||||
|
||||
pub fn handle_menu_event<R: Runtime>(app: &AppHandle<R>, event: MenuEvent) {
|
||||
match event.id().as_ref() {
|
||||
"show" => show_main_window(app, None),
|
||||
"chat" => show_main_window(app, Some("/agent")),
|
||||
"quit" => {
|
||||
app.exit(0);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn show_main_window<R: Runtime>(app: &AppHandle<R>, navigate_to: Option<&str>) {
|
||||
if let Some(window) = app.get_webview_window("main") {
|
||||
let _ = window.show();
|
||||
let _ = window.set_focus();
|
||||
if let Some(path) = navigate_to {
|
||||
let script = format!("window.location.hash = '{path}'");
|
||||
let _ = window.eval(&script);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,105 +0,0 @@
|
||||
//! Tray icon management — swap icon based on connection/agent status.
|
||||
|
||||
use crate::state::AgentStatus;
|
||||
use tauri::image::Image;
|
||||
|
||||
/// Embedded tray icon PNGs (22x22, RGBA).
|
||||
const ICON_IDLE: &[u8] = include_bytes!("../../icons/tray-idle.png");
|
||||
const ICON_WORKING: &[u8] = include_bytes!("../../icons/tray-working.png");
|
||||
const ICON_ERROR: &[u8] = include_bytes!("../../icons/tray-error.png");
|
||||
const ICON_DISCONNECTED: &[u8] = include_bytes!("../../icons/tray-disconnected.png");
|
||||
|
||||
/// Select the appropriate tray icon for the current state.
|
||||
pub fn icon_for_state(connected: bool, status: AgentStatus) -> Image<'static> {
|
||||
let bytes: &[u8] = if !connected {
|
||||
ICON_DISCONNECTED
|
||||
} else {
|
||||
match status {
|
||||
AgentStatus::Idle => ICON_IDLE,
|
||||
AgentStatus::Working => ICON_WORKING,
|
||||
AgentStatus::Error => ICON_ERROR,
|
||||
}
|
||||
};
|
||||
Image::from_bytes(bytes).expect("embedded tray icon is a valid PNG")
|
||||
}
|
||||
|
||||
/// Tooltip text for the current state.
|
||||
pub fn tooltip_for_state(connected: bool, status: AgentStatus) -> &'static str {
|
||||
if !connected {
|
||||
return "ZeroClaw — Disconnected";
|
||||
}
|
||||
match status {
|
||||
AgentStatus::Idle => "ZeroClaw — Idle",
|
||||
AgentStatus::Working => "ZeroClaw — Working",
|
||||
AgentStatus::Error => "ZeroClaw — Error",
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn icon_disconnected_when_not_connected() {
|
||||
// Should not panic — icon bytes are valid PNGs.
|
||||
let _img = icon_for_state(false, AgentStatus::Idle);
|
||||
let _img = icon_for_state(false, AgentStatus::Working);
|
||||
let _img = icon_for_state(false, AgentStatus::Error);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn icon_connected_variants() {
|
||||
let _idle = icon_for_state(true, AgentStatus::Idle);
|
||||
let _working = icon_for_state(true, AgentStatus::Working);
|
||||
let _error = icon_for_state(true, AgentStatus::Error);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tooltip_disconnected() {
|
||||
assert_eq!(
|
||||
tooltip_for_state(false, AgentStatus::Idle),
|
||||
"ZeroClaw — Disconnected"
|
||||
);
|
||||
// Agent status is irrelevant when disconnected.
|
||||
assert_eq!(
|
||||
tooltip_for_state(false, AgentStatus::Working),
|
||||
"ZeroClaw — Disconnected"
|
||||
);
|
||||
assert_eq!(
|
||||
tooltip_for_state(false, AgentStatus::Error),
|
||||
"ZeroClaw — Disconnected"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tooltip_connected_variants() {
|
||||
assert_eq!(
|
||||
tooltip_for_state(true, AgentStatus::Idle),
|
||||
"ZeroClaw — Idle"
|
||||
);
|
||||
assert_eq!(
|
||||
tooltip_for_state(true, AgentStatus::Working),
|
||||
"ZeroClaw — Working"
|
||||
);
|
||||
assert_eq!(
|
||||
tooltip_for_state(true, AgentStatus::Error),
|
||||
"ZeroClaw — Error"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn embedded_icons_are_valid_png() {
|
||||
// Verify the PNG signature (first 8 bytes) of each embedded icon.
|
||||
let png_sig: &[u8] = &[0x89, b'P', b'N', b'G', 0x0D, 0x0A, 0x1A, 0x0A];
|
||||
assert!(ICON_IDLE.starts_with(png_sig), "idle icon not valid PNG");
|
||||
assert!(
|
||||
ICON_WORKING.starts_with(png_sig),
|
||||
"working icon not valid PNG"
|
||||
);
|
||||
assert!(ICON_ERROR.starts_with(png_sig), "error icon not valid PNG");
|
||||
assert!(
|
||||
ICON_DISCONNECTED.starts_with(png_sig),
|
||||
"disconnected icon not valid PNG"
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -1,19 +0,0 @@
|
||||
//! Tray menu construction.
|
||||
|
||||
use tauri::{
|
||||
menu::{Menu, MenuItemBuilder, PredefinedMenuItem},
|
||||
App, Runtime,
|
||||
};
|
||||
|
||||
pub fn create_tray_menu<R: Runtime>(app: &App<R>) -> Result<Menu<R>, tauri::Error> {
|
||||
let show = MenuItemBuilder::with_id("show", "Show Dashboard").build(app)?;
|
||||
let chat = MenuItemBuilder::with_id("chat", "Agent Chat").build(app)?;
|
||||
let sep1 = PredefinedMenuItem::separator(app)?;
|
||||
let status = MenuItemBuilder::with_id("status", "Status: Checking...")
|
||||
.enabled(false)
|
||||
.build(app)?;
|
||||
let sep2 = PredefinedMenuItem::separator(app)?;
|
||||
let quit = MenuItemBuilder::with_id("quit", "Quit ZeroClaw").build(app)?;
|
||||
|
||||
Menu::with_items(app, &[&show, &chat, &sep1, &status, &sep2, &quit])
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
//! System tray integration for ZeroClaw Desktop.
|
||||
|
||||
pub mod events;
|
||||
pub mod icon;
|
||||
pub mod menu;
|
||||
|
||||
use tauri::{
|
||||
tray::{TrayIcon, TrayIconBuilder, TrayIconEvent},
|
||||
App, Manager, Runtime,
|
||||
};
|
||||
|
||||
/// Set up the system tray icon and menu.
|
||||
pub fn setup_tray<R: Runtime>(app: &App<R>) -> Result<TrayIcon<R>, tauri::Error> {
|
||||
let menu = menu::create_tray_menu(app)?;
|
||||
|
||||
TrayIconBuilder::with_id("main")
|
||||
.tooltip("ZeroClaw — Disconnected")
|
||||
.icon(icon::icon_for_state(false, crate::state::AgentStatus::Idle))
|
||||
.menu(&menu)
|
||||
.show_menu_on_left_click(false)
|
||||
.on_menu_event(events::handle_menu_event)
|
||||
.on_tray_icon_event(|tray, event| {
|
||||
if let TrayIconEvent::Click { button, .. } = event {
|
||||
if button == tauri::tray::MouseButton::Left {
|
||||
let app = tray.app_handle();
|
||||
if let Some(window) = app.get_webview_window("main") {
|
||||
let _ = window.show();
|
||||
let _ = window.set_focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.build(app)
|
||||
}
|
||||
@ -1,35 +0,0 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/tauri-apps/tauri/dev/crates/tauri-cli/config.schema.json",
|
||||
"productName": "ZeroClaw",
|
||||
"version": "0.6.1",
|
||||
"identifier": "ai.zeroclawlabs.desktop",
|
||||
"build": {
|
||||
"devUrl": "http://127.0.0.1:42617/_app/",
|
||||
"frontendDist": "http://127.0.0.1:42617/_app/"
|
||||
},
|
||||
"app": {
|
||||
"windows": [
|
||||
{
|
||||
"title": "ZeroClaw",
|
||||
"width": 1200,
|
||||
"height": 800,
|
||||
"resizable": true,
|
||||
"fullscreen": false,
|
||||
"visible": false
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
"csp": "default-src 'self' http://127.0.0.1:* ws://127.0.0.1:*; connect-src 'self' http://127.0.0.1:* ws://127.0.0.1:*; script-src 'self' 'unsafe-inline' http://127.0.0.1:*; style-src 'self' 'unsafe-inline' http://127.0.0.1:*; img-src 'self' http://127.0.0.1:* data:"
|
||||
}
|
||||
},
|
||||
"bundle": {
|
||||
"active": true,
|
||||
"targets": "all",
|
||||
"icon": [
|
||||
"icons/32x32.png",
|
||||
"icons/128x128.png",
|
||||
"icons/icon.icns",
|
||||
"icons/icon.ico"
|
||||
]
|
||||
}
|
||||
}
|
||||
@ -263,7 +263,7 @@ fn bench_memory_operations(c: &mut Criterion) {
|
||||
c.bench_function("memory_recall_top10", |b| {
|
||||
b.iter(|| {
|
||||
rt.block_on(async {
|
||||
mem.recall(black_box("zeroclaw agent"), 10, None, None, None)
|
||||
mem.recall(black_box("zeroclaw agent"), 10, None)
|
||||
.await
|
||||
.unwrap()
|
||||
})
|
||||
|
||||
@ -10,22 +10,3 @@ default_temperature = 0.7
|
||||
port = 42617
|
||||
host = "[::]"
|
||||
allow_public_bind = true
|
||||
|
||||
# Cost tracking and budget enforcement configuration
|
||||
# Enable to track API usage costs and enforce spending limits
|
||||
[cost]
|
||||
enabled = false
|
||||
daily_limit_usd = 10.0
|
||||
monthly_limit_usd = 100.0
|
||||
warn_at_percent = 80
|
||||
allow_override = false
|
||||
|
||||
# Per-model pricing (USD per 1M tokens)
|
||||
# Uncomment and customize to override default pricing
|
||||
# [cost.prices."anthropic/claude-sonnet-4-20250514"]
|
||||
# input = 3.0
|
||||
# output = 15.0
|
||||
#
|
||||
# [cost.prices."openai/gpt-4o"]
|
||||
# input = 5.0
|
||||
# output = 15.0
|
||||
|
||||
4
dist/aur/.SRCINFO
vendored
@ -1,6 +1,6 @@
|
||||
pkgbase = zeroclaw
|
||||
pkgdesc = Zero overhead. Zero compromise. 100% Rust. The fastest, smallest AI assistant.
|
||||
pkgver = 0.5.9
|
||||
pkgver = 0.5.3
|
||||
pkgrel = 1
|
||||
url = https://github.com/zeroclaw-labs/zeroclaw
|
||||
arch = x86_64
|
||||
@ -10,7 +10,7 @@ pkgbase = zeroclaw
|
||||
makedepends = git
|
||||
depends = gcc-libs
|
||||
depends = openssl
|
||||
source = zeroclaw-0.5.9.tar.gz::https://github.com/zeroclaw-labs/zeroclaw/archive/refs/tags/v0.5.9.tar.gz
|
||||
source = zeroclaw-0.5.3.tar.gz::https://github.com/zeroclaw-labs/zeroclaw/archive/refs/tags/v0.5.3.tar.gz
|
||||
sha256sums = SKIP
|
||||
|
||||
pkgname = zeroclaw
|
||||
|
||||
2
dist/aur/PKGBUILD
vendored
@ -1,6 +1,6 @@
|
||||
# Maintainer: zeroclaw-labs <bot@zeroclaw.dev>
|
||||
pkgname=zeroclaw
|
||||
pkgver=0.5.9
|
||||
pkgver=0.5.3
|
||||
pkgrel=1
|
||||
pkgdesc="Zero overhead. Zero compromise. 100% Rust. The fastest, smallest AI assistant."
|
||||
arch=('x86_64')
|
||||
|
||||
4
dist/scoop/zeroclaw.json
vendored
@ -1,11 +1,11 @@
|
||||
{
|
||||
"version": "0.5.9",
|
||||
"version": "0.5.3",
|
||||
"description": "Zero overhead. Zero compromise. 100% Rust. The fastest, smallest AI assistant.",
|
||||
"homepage": "https://github.com/zeroclaw-labs/zeroclaw",
|
||||
"license": "MIT|Apache-2.0",
|
||||
"architecture": {
|
||||
"64bit": {
|
||||
"url": "https://github.com/zeroclaw-labs/zeroclaw/releases/download/v0.5.9/zeroclaw-x86_64-pc-windows-msvc.zip",
|
||||
"url": "https://github.com/zeroclaw-labs/zeroclaw/releases/download/v0.5.3/zeroclaw-x86_64-pc-windows-msvc.zip",
|
||||
"hash": "",
|
||||
"bin": "zeroclaw.exe"
|
||||
}
|
||||
|
||||
@ -1,202 +0,0 @@
|
||||
# ADR-004: Tool Shared State Ownership Contract
|
||||
|
||||
**Status:** Accepted
|
||||
|
||||
**Date:** 2026-03-22
|
||||
|
||||
**Issue:** [#4057](https://github.com/zeroclaw/zeroclaw/issues/4057)
|
||||
|
||||
## Context
|
||||
|
||||
ZeroClaw tools execute in a multi-client environment where a single daemon
|
||||
process serves requests from multiple connected clients simultaneously. Several
|
||||
tools already maintain long-lived shared state:
|
||||
|
||||
- **`DelegateParentToolsHandle`** (`src/tools/mod.rs`):
|
||||
`Arc<RwLock<Vec<Arc<dyn Tool>>>>` — holds parent tools for delegate agents
|
||||
with no per-client isolation.
|
||||
- **`ChannelMapHandle`** (`src/tools/reaction.rs`):
|
||||
`Arc<RwLock<HashMap<String, Arc<dyn Channel>>>>` — global channel map shared
|
||||
across all clients.
|
||||
- **`CanvasStore`** (`src/tools/canvas.rs`):
|
||||
`Arc<RwLock<HashMap<String, CanvasEntry>>>` — canvas IDs are plain strings
|
||||
with no client namespace.
|
||||
|
||||
These patterns emerged organically. As the tool surface grows and more clients
|
||||
connect concurrently, we need a clear contract governing ownership, identity,
|
||||
isolation, lifecycle, and reload behavior for tool-held shared state. Without
|
||||
this contract, new tools risk introducing data leaks between clients, stale
|
||||
state after config reloads, or inconsistent initialization timing.
|
||||
|
||||
Additional context:
|
||||
|
||||
- The tool registry is immutable after startup, built once in
|
||||
`all_tools_with_runtime()`.
|
||||
- Client identity is currently derived from IP address only
|
||||
(`src/gateway/mod.rs`), which is insufficient for reliable namespacing.
|
||||
- `SecurityPolicy` is scoped per agent, not per client.
|
||||
- `WorkspaceManager` provides some isolation but workspace switching is global.
|
||||
|
||||
## Decision
|
||||
|
||||
### 1. Ownership: May tools own long-lived shared state?
|
||||
|
||||
**Yes.** Tools MAY own long-lived shared state, provided they follow the
|
||||
established **handle pattern**: wrap the state in `Arc<RwLock<T>>` (or
|
||||
`Arc<parking_lot::RwLock<T>>`) and expose a cloneable handle type.
|
||||
|
||||
This pattern is already proven by three independent implementations:
|
||||
|
||||
| Handle | Location | Inner type |
|
||||
|--------|----------|-----------|
|
||||
| `DelegateParentToolsHandle` | `src/tools/mod.rs` | `Vec<Arc<dyn Tool>>` |
|
||||
| `ChannelMapHandle` | `src/tools/reaction.rs` | `HashMap<String, Arc<dyn Channel>>` |
|
||||
| `CanvasStore` | `src/tools/canvas.rs` | `HashMap<String, CanvasEntry>` |
|
||||
|
||||
Tools that need shared state MUST:
|
||||
|
||||
- Define a named handle type alias (e.g., `pub type FooHandle = Arc<RwLock<T>>`).
|
||||
- Accept the handle at construction time rather than creating global state.
|
||||
- Document the concurrency contract in the handle type's doc comment.
|
||||
|
||||
Tools MUST NOT use static mutable state (`lazy_static!`, `OnceCell` with
|
||||
interior mutability) for per-request or per-client data.
|
||||
|
||||
### 2. Identity assignment: Who constructs identity keys?
|
||||
|
||||
**The daemon SHOULD provide identity.** Tools MUST NOT construct their own
|
||||
client identity keys.
|
||||
|
||||
A new `ClientId` type should be introduced (opaque, `Clone + Eq + Hash + Send + Sync`)
|
||||
that the daemon assigns at connection time. This replaces the current approach
|
||||
of using raw IP addresses (`src/gateway/mod.rs:259-306`), which breaks when
|
||||
multiple clients share a NAT address or when proxied connections arrive.
|
||||
|
||||
`ClientId` is passed to tools that require per-client state namespacing as part
|
||||
of the tool execution context. Tools that do not need per-client isolation
|
||||
(e.g., the immutable tool registry) may ignore it.
|
||||
|
||||
The `ClientId` contract:
|
||||
|
||||
- Generated by the gateway layer at connection establishment.
|
||||
- Opaque to tools — tools must not parse or derive meaning from the value.
|
||||
- Stable for the lifetime of a single client session.
|
||||
- Passed through the execution context, not stored globally.
|
||||
|
||||
### 3. Lifecycle: When may tools run startup-style validation?
|
||||
|
||||
**Validation runs once at first registration, and again when config changes
|
||||
are detected.**
|
||||
|
||||
The lifecycle phases are:
|
||||
|
||||
1. **Construction** — tool is instantiated with handles and config. No I/O or
|
||||
validation occurs here.
|
||||
2. **Registration** — tool is registered in the tool registry via
|
||||
`all_tools_with_runtime()`. At this point the tool MAY perform one-time
|
||||
startup validation (e.g., checking that required credentials exist, verifying
|
||||
external service connectivity).
|
||||
3. **Execution** — tool handles individual requests. No re-validation unless
|
||||
the config-change signal fires (see Reload Semantics below).
|
||||
4. **Shutdown** — daemon is stopping. Tools with open resources SHOULD clean up
|
||||
gracefully via `Drop` or an explicit shutdown method.
|
||||
|
||||
Tools MUST NOT perform blocking validation during execution-phase calls.
|
||||
Validation results SHOULD be cached in the tool's handle state and checked
|
||||
via a fast path during execution.
|
||||
|
||||
### 4. Isolation: What must be isolated per client?
|
||||
|
||||
State falls into two categories with different isolation requirements:
|
||||
|
||||
**MUST be isolated per client:**
|
||||
|
||||
- Security-sensitive state: credentials, API keys, quotas, rate-limit counters,
|
||||
per-client authorization decisions.
|
||||
- User-specific session data: conversation context, user preferences,
|
||||
workspace-scoped file paths.
|
||||
|
||||
Isolation mechanism: tools holding per-client state MUST key their internal
|
||||
maps by `ClientId`. The handle pattern naturally supports this by using
|
||||
`HashMap<ClientId, T>` inside the `RwLock`.
|
||||
|
||||
**MAY be shared across clients (with namespace prefixing):**
|
||||
|
||||
- Broadcast/display state: canvas frames (`CanvasStore`), notification channels
|
||||
(`ChannelMapHandle`).
|
||||
- Read-only reference data: tool registry, static configuration, model
|
||||
metadata.
|
||||
|
||||
When shared state uses string keys (e.g., canvas IDs, channel names), tools
|
||||
SHOULD support optional namespace prefixing (e.g., `{client_id}:{canvas_name}`)
|
||||
to allow per-client isolation when needed without mandating it for broadcast
|
||||
use cases.
|
||||
|
||||
Tools MUST NOT store per-client secrets in shared (non-isolated) state
|
||||
structures.
|
||||
|
||||
### 5. Reload semantics: What invalidates prior shared state on config change?
|
||||
|
||||
**Config changes detected via hash comparison MUST invalidate cached
|
||||
validation state.**
|
||||
|
||||
The reload contract:
|
||||
|
||||
- The daemon computes a hash of the tool-relevant config section at startup and
|
||||
after each config reload event.
|
||||
- When the hash changes, the daemon signals affected tools to re-run their
|
||||
registration-phase validation.
|
||||
- Tools MUST treat their cached validation result as stale when signaled and
|
||||
re-validate before the next execution.
|
||||
|
||||
Specific invalidation rules:
|
||||
|
||||
| Config change | Invalidation scope |
|
||||
|--------------|-------------------|
|
||||
| Credential/secret rotation | Per-tool validation cache; per-client credential state |
|
||||
| Tool enable/disable | Full tool registry rebuild via `all_tools_with_runtime()` |
|
||||
| Security policy change | `SecurityPolicy` re-derivation; per-agent policy state |
|
||||
| Workspace directory change | `WorkspaceManager` state; file-path-dependent tool state |
|
||||
| Provider config change | Provider-dependent tools re-validate connectivity |
|
||||
|
||||
Tools MAY retain non-security shared state (e.g., canvas content, channel
|
||||
subscriptions) across config reloads unless the reload explicitly affects that
|
||||
state's validity.
|
||||
|
||||
## Consequences
|
||||
|
||||
### Positive
|
||||
|
||||
- **Consistency:** All new tools follow the same handle pattern, making shared
|
||||
state discoverable and auditable.
|
||||
- **Safety:** Per-client isolation of security-sensitive state prevents data
|
||||
leaks in multi-tenant scenarios.
|
||||
- **Clarity:** Explicit lifecycle phases eliminate ambiguity about when
|
||||
validation runs.
|
||||
- **Evolvability:** The `ClientId` abstraction decouples tools from transport
|
||||
details, supporting future identity mechanisms (tokens, certificates).
|
||||
|
||||
### Negative
|
||||
|
||||
- **Migration cost:** Existing tools (`CanvasStore`, `ReactionTool`) may need
|
||||
refactoring to accept `ClientId` and namespace their state.
|
||||
- **Complexity:** Tools that were simple singletons now need to consider
|
||||
multi-client semantics even if they currently have one client.
|
||||
- **Performance:** Per-client keying adds a hash lookup on each access, though
|
||||
this is negligible compared to I/O costs.
|
||||
|
||||
### Neutral
|
||||
|
||||
- The tool registry remains immutable after startup; this ADR does not change
|
||||
that invariant.
|
||||
- `SecurityPolicy` remains per-agent; this ADR documents that client isolation
|
||||
is orthogonal to agent-level policy.
|
||||
|
||||
## References
|
||||
|
||||
- `src/tools/mod.rs` — `DelegateParentToolsHandle`, `all_tools_with_runtime()`
|
||||
- `src/tools/reaction.rs` — `ChannelMapHandle`, `ReactionTool`
|
||||
- `src/tools/canvas.rs` — `CanvasStore`, `CanvasEntry`
|
||||
- `src/tools/traits.rs` — `Tool` trait
|
||||
- `src/gateway/mod.rs` — client IP extraction (`forwarded_client_ip`, `resolve_client_ip`)
|
||||
- `src/security/` — `SecurityPolicy`
|
||||
@ -1,215 +0,0 @@
|
||||
# Browser Automation Setup Guide
|
||||
|
||||
This guide covers setting up browser automation capabilities in ZeroClaw, including both headless automation and GUI access via VNC.
|
||||
|
||||
## Overview
|
||||
|
||||
ZeroClaw supports multiple browser access methods:
|
||||
|
||||
| Method | Use Case | Requirements |
|
||||
|--------|----------|--------------|
|
||||
| **agent-browser CLI** | Headless automation, AI agents | npm, Chrome |
|
||||
| **VNC + noVNC** | GUI access, debugging | Xvfb, x11vnc, noVNC |
|
||||
| **Chrome Remote Desktop** | Remote GUI via Google | XFCE, Google account |
|
||||
|
||||
## Quick Start: Headless Automation
|
||||
|
||||
### 1. Install agent-browser
|
||||
|
||||
```bash
|
||||
# Install CLI
|
||||
npm install -g agent-browser
|
||||
|
||||
# Download Chrome for Testing
|
||||
agent-browser install --with-deps # Linux (includes system deps)
|
||||
agent-browser install # macOS/Windows
|
||||
```
|
||||
|
||||
### 2. Verify ZeroClaw Config
|
||||
|
||||
The browser tool is enabled by default. To verify or customize, edit
|
||||
`~/.zeroclaw/config.toml`:
|
||||
|
||||
```toml
|
||||
[browser]
|
||||
enabled = true # default: true
|
||||
allowed_domains = ["*"] # default: ["*"] (all public hosts)
|
||||
backend = "agent_browser" # default: "agent_browser"
|
||||
native_headless = true # default: true
|
||||
```
|
||||
|
||||
To restrict domains or disable the browser tool:
|
||||
|
||||
```toml
|
||||
[browser]
|
||||
enabled = false # disable entirely
|
||||
# or restrict to specific domains:
|
||||
allowed_domains = ["example.com", "docs.example.com"]
|
||||
```
|
||||
|
||||
### 3. Test
|
||||
|
||||
```bash
|
||||
echo "Open https://example.com and tell me what it says" | zeroclaw agent
|
||||
```
|
||||
|
||||
## VNC Setup (GUI Access)
|
||||
|
||||
For debugging or when you need visual browser access:
|
||||
|
||||
### Install Dependencies
|
||||
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
apt-get install -y xvfb x11vnc fluxbox novnc websockify
|
||||
|
||||
# Optional: Desktop environment for Chrome Remote Desktop
|
||||
apt-get install -y xfce4 xfce4-goodies
|
||||
```
|
||||
|
||||
### Start VNC Server
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# Start virtual display with VNC access
|
||||
|
||||
DISPLAY_NUM=99
|
||||
VNC_PORT=5900
|
||||
NOVNC_PORT=6080
|
||||
RESOLUTION=1920x1080x24
|
||||
|
||||
# Start Xvfb
|
||||
Xvfb :$DISPLAY_NUM -screen 0 $RESOLUTION -ac &
|
||||
sleep 1
|
||||
|
||||
# Start window manager
|
||||
fluxbox -display :$DISPLAY_NUM &
|
||||
sleep 1
|
||||
|
||||
# Start x11vnc
|
||||
x11vnc -display :$DISPLAY_NUM -rfbport $VNC_PORT -forever -shared -nopw -bg
|
||||
sleep 1
|
||||
|
||||
# Start noVNC (web-based VNC)
|
||||
websockify --web=/usr/share/novnc $NOVNC_PORT localhost:$VNC_PORT &
|
||||
|
||||
echo "VNC available at:"
|
||||
echo " VNC Client: localhost:$VNC_PORT"
|
||||
echo " Web Browser: http://localhost:$NOVNC_PORT/vnc.html"
|
||||
```
|
||||
|
||||
### VNC Access
|
||||
|
||||
- **VNC Client**: Connect to `localhost:5900`
|
||||
- **Web Browser**: Open `http://localhost:6080/vnc.html`
|
||||
|
||||
### Start Browser on VNC Display
|
||||
|
||||
```bash
|
||||
DISPLAY=:99 google-chrome --no-sandbox https://example.com &
|
||||
```
|
||||
|
||||
## Chrome Remote Desktop
|
||||
|
||||
### Install
|
||||
|
||||
```bash
|
||||
# Download and install
|
||||
wget https://dl.google.com/linux/direct/chrome-remote-desktop_current_amd64.deb
|
||||
apt-get install -y ./chrome-remote-desktop_current_amd64.deb
|
||||
|
||||
# Configure session
|
||||
echo "xfce4-session" > ~/.chrome-remote-desktop-session
|
||||
chmod +x ~/.chrome-remote-desktop-session
|
||||
```
|
||||
|
||||
### Setup
|
||||
|
||||
1. Visit <https://remotedesktop.google.com/headless>
|
||||
2. Copy the "Debian Linux" setup command
|
||||
3. Run it on your server
|
||||
4. Start the service: `systemctl --user start chrome-remote-desktop`
|
||||
|
||||
### Remote Access
|
||||
|
||||
Go to <https://remotedesktop.google.com/access> from any device.
|
||||
|
||||
## Testing
|
||||
|
||||
### CLI Tests
|
||||
|
||||
```bash
|
||||
# Basic open and close
|
||||
agent-browser open https://example.com
|
||||
agent-browser get title
|
||||
agent-browser close
|
||||
|
||||
# Snapshot with refs
|
||||
agent-browser open https://example.com
|
||||
agent-browser snapshot -i
|
||||
agent-browser close
|
||||
|
||||
# Screenshot
|
||||
agent-browser open https://example.com
|
||||
agent-browser screenshot /tmp/test.png
|
||||
agent-browser close
|
||||
```
|
||||
|
||||
### ZeroClaw Integration Tests
|
||||
|
||||
```bash
|
||||
# Content extraction
|
||||
echo "Open https://example.com and summarize it" | zeroclaw agent
|
||||
|
||||
# Navigation
|
||||
echo "Go to https://github.com/trending and list the top 3 repos" | zeroclaw agent
|
||||
|
||||
# Form interaction
|
||||
echo "Go to Wikipedia, search for 'Rust programming language', and summarize" | zeroclaw agent
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "Element not found"
|
||||
|
||||
The page may not be fully loaded. Add a wait:
|
||||
|
||||
```bash
|
||||
agent-browser open https://slow-site.com
|
||||
agent-browser wait --load networkidle
|
||||
agent-browser snapshot -i
|
||||
```
|
||||
|
||||
### Cookie dialogs blocking access
|
||||
|
||||
Handle cookie consent first:
|
||||
|
||||
```bash
|
||||
agent-browser open https://site-with-cookies.com
|
||||
agent-browser snapshot -i
|
||||
agent-browser click @accept_cookies # Click the accept button
|
||||
agent-browser snapshot -i # Now get the actual content
|
||||
```
|
||||
|
||||
### Docker sandbox network restrictions
|
||||
|
||||
If `web_fetch` fails inside Docker sandbox, use agent-browser instead:
|
||||
|
||||
```bash
|
||||
# Instead of web_fetch, use:
|
||||
agent-browser open https://example.com
|
||||
agent-browser get text body
|
||||
```
|
||||
|
||||
## Security Notes
|
||||
|
||||
- `agent-browser` runs Chrome in headless mode with sandboxing
|
||||
- For sensitive sites, use `--session-name` to persist auth state
|
||||
- The `--allowed-domains` config restricts navigation to specific domains
|
||||
- VNC ports (5900, 6080) should be behind a firewall or Tailscale
|
||||
|
||||
## Related
|
||||
|
||||
- [agent-browser Documentation](https://github.com/vercel-labs/agent-browser)
|
||||
- [ZeroClaw Configuration Reference](./config-reference.md)
|
||||
- [Skills Documentation](../skills/)
|
||||
@ -20,7 +20,6 @@ Selected allowlist (all actions currently used across Quality Gate, Release Beta
|
||||
| `docker/setup-buildx-action@v3` | release, promote-release | Docker Buildx setup |
|
||||
| `docker/login-action@v3` | release, promote-release | GHCR authentication |
|
||||
| `docker/build-push-action@v6` | release, promote-release | Multi-platform Docker image build and push |
|
||||
| `actions/labeler@v5` | pr-path-labeler | Apply path/scope labels from `labeler.yml` |
|
||||
|
||||
Equivalent allowlist patterns:
|
||||
|
||||
@ -37,7 +36,6 @@ Equivalent allowlist patterns:
|
||||
| Quality Gate | `.github/workflows/checks-on-pr.yml` | Pull requests to `master` |
|
||||
| Release Beta | `.github/workflows/release-beta-on-push.yml` | Push to `master` |
|
||||
| Release Stable | `.github/workflows/release-stable-manual.yml` | Manual `workflow_dispatch` |
|
||||
| PR Path Labeler | `.github/workflows/pr-path-labeler.yml` | `pull_request_target` (opened, synchronize, reopened) |
|
||||
|
||||
## Change Control
|
||||
|
||||
@ -64,7 +62,6 @@ gh api repos/zeroclaw-labs/zeroclaw/actions/permissions/selected-actions
|
||||
|
||||
## Change Log
|
||||
|
||||
- 2026-03-23: Added PR Path Labeler (`pr-path-labeler.yml`) using `actions/labeler@v5`. No allowlist change needed — covered by existing `actions/*` pattern.
|
||||
- 2026-03-10: Renamed workflows — CI → Quality Gate (`checks-on-pr.yml`), Beta Release → Release Beta (`release-beta-on-push.yml`), Promote Release → Release Stable (`release-stable-manual.yml`). Added `lint` and `security` jobs to Quality Gate. Added Cross-Platform Build (`cross-platform-build-manual.yml`).
|
||||
- 2026-03-05: Complete workflow overhaul — replaced 22 workflows with 3 (CI, Beta Release, Promote Release)
|
||||
- Removed patterns no longer in use: `DavidAnson/markdownlint-cli2-action@*`, `lycheeverse/lychee-action@*`, `EmbarkStudios/cargo-deny-action@*`, `rustsec/audit-check@*`, `rhysd/actionlint@*`, `sigstore/cosign-installer@*`, `Checkmarx/vorpal-reviewdog-github-action@*`, `useblacksmith/*`
|
||||
|
||||
@ -45,15 +45,6 @@ For complete code examples of each extension trait, see [extension-examples.md](
|
||||
- Keep multilingual entry-point parity for all supported locales (`en`, `zh-CN`, `ja`, `ru`, `fr`, `vi`) when nav or key wording changes.
|
||||
- When shared docs wording changes, sync corresponding localized docs in the same PR (or explicitly document deferral and follow-up PR).
|
||||
|
||||
## Tool Shared State
|
||||
|
||||
- Follow the `Arc<RwLock<T>>` handle pattern for any tool that owns long-lived shared state.
|
||||
- Accept handles at construction; do not create global/static mutable state.
|
||||
- Use `ClientId` (provided by the daemon) to namespace per-client state — never construct identity keys inside the tool.
|
||||
- Isolate security-sensitive state (credentials, quotas) per client; broadcast/display state may be shared with optional namespace prefixing.
|
||||
- Cached validation is invalidated on config change — tools must re-validate before the next execution when signaled.
|
||||
- See [ADR-004: Tool Shared State Ownership](../architecture/adr-004-tool-shared-state-ownership.md) for the full contract.
|
||||
|
||||
## Architecture Boundary Rules
|
||||
|
||||
- Extend capabilities by adding trait implementations + factory wiring first; avoid cross-module rewrites for isolated features.
|
||||
|
||||
@ -1,213 +0,0 @@
|
||||
# Label Registry
|
||||
|
||||
Single reference for every label used on PRs and issues. Labels are grouped by category. Each entry lists the label name, definition, and how it is applied.
|
||||
|
||||
Sources consolidated here:
|
||||
|
||||
- `.github/labeler.yml` (path-label config for `actions/labeler`)
|
||||
- `.github/label-policy.json` (contributor tier thresholds)
|
||||
- `docs/contributing/pr-workflow.md` (size, risk, and triage label definitions)
|
||||
- `docs/contributing/ci-map.md` (automation behavior and high-risk path heuristics)
|
||||
|
||||
Note: The CI was simplified to 4 workflows (`ci.yml`, `release.yml`, `ci-full.yml`, `promote-release.yml`). Workflows that previously automated size, risk, contributor tier, and triage labels (`pr-labeler.yml`, `pr-auto-response.yml`, `pr-check-stale.yml`, and supporting scripts) were removed. Only path labels via `pr-path-labeler.yml` are currently automated.
|
||||
|
||||
---
|
||||
|
||||
## Path labels
|
||||
|
||||
Applied automatically by `pr-path-labeler.yml` using `actions/labeler`. Matches changed files against glob patterns in `.github/labeler.yml`.
|
||||
|
||||
### Base scope labels
|
||||
|
||||
| Label | Matches |
|
||||
|---|---|
|
||||
| `docs` | `docs/**`, `**/*.md`, `**/*.mdx`, `LICENSE`, `.markdownlint-cli2.yaml` |
|
||||
| `dependencies` | `Cargo.toml`, `Cargo.lock`, `deny.toml`, `.github/dependabot.yml` |
|
||||
| `ci` | `.github/**`, `.githooks/**` |
|
||||
| `core` | `src/*.rs` |
|
||||
| `agent` | `src/agent/**` |
|
||||
| `channel` | `src/channels/**` |
|
||||
| `gateway` | `src/gateway/**` |
|
||||
| `config` | `src/config/**` |
|
||||
| `cron` | `src/cron/**` |
|
||||
| `daemon` | `src/daemon/**` |
|
||||
| `doctor` | `src/doctor/**` |
|
||||
| `health` | `src/health/**` |
|
||||
| `heartbeat` | `src/heartbeat/**` |
|
||||
| `integration` | `src/integrations/**` |
|
||||
| `memory` | `src/memory/**` |
|
||||
| `security` | `src/security/**` |
|
||||
| `runtime` | `src/runtime/**` |
|
||||
| `onboard` | `src/onboard/**` |
|
||||
| `provider` | `src/providers/**` |
|
||||
| `service` | `src/service/**` |
|
||||
| `skillforge` | `src/skillforge/**` |
|
||||
| `skills` | `src/skills/**` |
|
||||
| `tool` | `src/tools/**` |
|
||||
| `tunnel` | `src/tunnel/**` |
|
||||
| `observability` | `src/observability/**` |
|
||||
| `tests` | `tests/**` |
|
||||
| `scripts` | `scripts/**` |
|
||||
| `dev` | `dev/**` |
|
||||
|
||||
### Per-component channel labels
|
||||
|
||||
Each channel gets a specific label in addition to the base `channel` label.
|
||||
|
||||
| Label | Matches |
|
||||
|---|---|
|
||||
| `channel:bluesky` | `bluesky.rs` |
|
||||
| `channel:clawdtalk` | `clawdtalk.rs` |
|
||||
| `channel:cli` | `cli.rs` |
|
||||
| `channel:dingtalk` | `dingtalk.rs` |
|
||||
| `channel:discord` | `discord.rs`, `discord_history.rs` |
|
||||
| `channel:email` | `email_channel.rs`, `gmail_push.rs` |
|
||||
| `channel:imessage` | `imessage.rs` |
|
||||
| `channel:irc` | `irc.rs` |
|
||||
| `channel:lark` | `lark.rs` |
|
||||
| `channel:linq` | `linq.rs` |
|
||||
| `channel:matrix` | `matrix.rs` |
|
||||
| `channel:mattermost` | `mattermost.rs` |
|
||||
| `channel:mochat` | `mochat.rs` |
|
||||
| `channel:mqtt` | `mqtt.rs` |
|
||||
| `channel:nextcloud-talk` | `nextcloud_talk.rs` |
|
||||
| `channel:nostr` | `nostr.rs` |
|
||||
| `channel:notion` | `notion.rs` |
|
||||
| `channel:qq` | `qq.rs` |
|
||||
| `channel:reddit` | `reddit.rs` |
|
||||
| `channel:signal` | `signal.rs` |
|
||||
| `channel:slack` | `slack.rs` |
|
||||
| `channel:telegram` | `telegram.rs` |
|
||||
| `channel:twitter` | `twitter.rs` |
|
||||
| `channel:wati` | `wati.rs` |
|
||||
| `channel:webhook` | `webhook.rs` |
|
||||
| `channel:wecom` | `wecom.rs` |
|
||||
| `channel:whatsapp` | `whatsapp.rs`, `whatsapp_storage.rs`, `whatsapp_web.rs` |
|
||||
|
||||
### Per-component provider labels
|
||||
|
||||
| Label | Matches |
|
||||
|---|---|
|
||||
| `provider:anthropic` | `anthropic.rs` |
|
||||
| `provider:azure-openai` | `azure_openai.rs` |
|
||||
| `provider:bedrock` | `bedrock.rs` |
|
||||
| `provider:claude-code` | `claude_code.rs` |
|
||||
| `provider:compatible` | `compatible.rs` |
|
||||
| `provider:copilot` | `copilot.rs` |
|
||||
| `provider:gemini` | `gemini.rs`, `gemini_cli.rs` |
|
||||
| `provider:glm` | `glm.rs` |
|
||||
| `provider:kilocli` | `kilocli.rs` |
|
||||
| `provider:ollama` | `ollama.rs` |
|
||||
| `provider:openai` | `openai.rs`, `openai_codex.rs` |
|
||||
| `provider:openrouter` | `openrouter.rs` |
|
||||
| `provider:telnyx` | `telnyx.rs` |
|
||||
|
||||
### Per-group tool labels
|
||||
|
||||
Tools are grouped by logical function rather than one label per file.
|
||||
|
||||
| Label | Matches |
|
||||
|---|---|
|
||||
| `tool:browser` | `browser.rs`, `browser_delegate.rs`, `browser_open.rs`, `text_browser.rs`, `screenshot.rs` |
|
||||
| `tool:cloud` | `cloud_ops.rs`, `cloud_patterns.rs` |
|
||||
| `tool:composio` | `composio.rs` |
|
||||
| `tool:cron` | `cron_add.rs`, `cron_list.rs`, `cron_remove.rs`, `cron_run.rs`, `cron_runs.rs`, `cron_update.rs` |
|
||||
| `tool:file` | `file_edit.rs`, `file_read.rs`, `file_write.rs`, `glob_search.rs`, `content_search.rs` |
|
||||
| `tool:google-workspace` | `google_workspace.rs` |
|
||||
| `tool:mcp` | `mcp_client.rs`, `mcp_deferred.rs`, `mcp_protocol.rs`, `mcp_tool.rs`, `mcp_transport.rs` |
|
||||
| `tool:memory` | `memory_forget.rs`, `memory_recall.rs`, `memory_store.rs` |
|
||||
| `tool:microsoft365` | `microsoft365/**` |
|
||||
| `tool:security` | `security_ops.rs`, `verifiable_intent.rs` |
|
||||
| `tool:shell` | `shell.rs`, `node_tool.rs`, `cli_discovery.rs` |
|
||||
| `tool:sop` | `sop_advance.rs`, `sop_approve.rs`, `sop_execute.rs`, `sop_list.rs`, `sop_status.rs` |
|
||||
| `tool:web` | `web_fetch.rs`, `web_search_tool.rs`, `web_search_provider_routing.rs`, `http_request.rs` |
|
||||
|
||||
---
|
||||
|
||||
## Size labels
|
||||
|
||||
Defined in `pr-workflow.md` §6.1. Based on effective changed line count, normalized for docs-only and lockfile-heavy PRs.
|
||||
|
||||
| Label | Threshold |
|
||||
|---|---|
|
||||
| `size: XS` | <= 80 lines |
|
||||
| `size: S` | <= 250 lines |
|
||||
| `size: M` | <= 500 lines |
|
||||
| `size: L` | <= 1000 lines |
|
||||
| `size: XL` | > 1000 lines |
|
||||
|
||||
**Applied by:** manual. The workflows that previously computed size labels (`pr-labeler.yml` and supporting scripts) were removed during CI simplification.
|
||||
|
||||
---
|
||||
|
||||
## Risk labels
|
||||
|
||||
Defined in `pr-workflow.md` §13.2 and `ci-map.md`. Based on a heuristic combining touched paths and change size.
|
||||
|
||||
| Label | Meaning |
|
||||
|---|---|
|
||||
| `risk: low` | No high-risk paths touched, small change |
|
||||
| `risk: medium` | Behavioral `src/**` changes without boundary/security impact |
|
||||
| `risk: high` | Touches high-risk paths (see below) or large security-adjacent change |
|
||||
| `risk: manual` | Maintainer override that freezes automated risk recalculation |
|
||||
|
||||
High-risk paths: `src/security/**`, `src/runtime/**`, `src/gateway/**`, `src/tools/**`, `.github/workflows/**`.
|
||||
|
||||
The boundary between low and medium is not formally defined beyond "no high-risk paths."
|
||||
|
||||
**Applied by:** manual. Previously automated via `pr-labeler.yml`; removed during CI simplification.
|
||||
|
||||
---
|
||||
|
||||
## Contributor tier labels
|
||||
|
||||
Defined in `.github/label-policy.json`. Based on the author's merged PR count queried from the GitHub API.
|
||||
|
||||
| Label | Minimum merged PRs |
|
||||
|---|---|
|
||||
| `trusted contributor` | 5 |
|
||||
| `experienced contributor` | 10 |
|
||||
| `principal contributor` | 20 |
|
||||
| `distinguished contributor` | 50 |
|
||||
|
||||
**Applied by:** manual. Previously automated via `pr-labeler.yml` and `pr-auto-response.yml`; removed during CI simplification.
|
||||
|
||||
---
|
||||
|
||||
## Response and triage labels
|
||||
|
||||
Defined in `pr-workflow.md` §8. Applied manually.
|
||||
|
||||
| Label | Purpose | Applied by |
|
||||
|---|---|---|
|
||||
| `r:needs-repro` | Incomplete bug report; request deterministic repro | Manual |
|
||||
| `r:support` | Usage/help item better handled outside bug backlog | Manual |
|
||||
| `invalid` | Not a valid bug/feature request | Manual |
|
||||
| `duplicate` | Duplicate of existing issue | Manual |
|
||||
| `stale-candidate` | Dormant PR/issue; candidate for closing | Manual |
|
||||
| `superseded` | Replaced by a newer PR | Manual |
|
||||
| `no-stale` | Exempt from stale automation; accepted but blocked work | Manual |
|
||||
|
||||
**Automation:** none currently. The workflows that handled label-driven issue closing (`pr-auto-response.yml`) and stale detection (`pr-check-stale.yml`) were removed during CI simplification.
|
||||
|
||||
---
|
||||
|
||||
## Implementation status
|
||||
|
||||
| Category | Count | Automated | Workflow |
|
||||
|---|---|---|---|
|
||||
| Path (base scope) | 27 | Yes | `pr-path-labeler.yml` |
|
||||
| Path (per-component) | 52 | Yes | `pr-path-labeler.yml` |
|
||||
| Size | 5 | No | Manual |
|
||||
| Risk | 4 | No | Manual |
|
||||
| Contributor tier | 4 | No | Manual |
|
||||
| Response/triage | 7 | No | Manual |
|
||||
| **Total** | **99** | | |
|
||||
|
||||
---
|
||||
|
||||
## Maintenance
|
||||
|
||||
- **Owner:** maintainers responsible for label policy and PR triage automation.
|
||||
- **Update trigger:** new channels, providers, or tools added to the source tree; label policy changes; triage workflow changes.
|
||||
- **Source of truth:** this document consolidates definitions from the four source files listed at the top. When definitions conflict, update the source file first, then sync this registry.
|
||||
@ -4,22 +4,8 @@ Localized documentation trees live here and under `docs/`.
|
||||
|
||||
## Locales
|
||||
|
||||
- العربية (Arabic): [ar/README.md](ar/README.md)
|
||||
- বাংলা (Bengali): [bn/README.md](bn/README.md)
|
||||
- Deutsch (German): [de/README.md](de/README.md)
|
||||
- Ελληνικά (Greek): [el/README.md](el/README.md)
|
||||
- Español (Spanish): [es/README.md](es/README.md)
|
||||
- Français (French): [fr/README.md](fr/README.md)
|
||||
- हिन्दी (Hindi): [hi/README.md](hi/README.md)
|
||||
- Italiano (Italian): [it/README.md](it/README.md)
|
||||
- 日本語 (Japanese): [ja/README.md](ja/README.md)
|
||||
- 한국어 (Korean): [ko/README.md](ko/README.md)
|
||||
- Português (Portuguese): [pt/README.md](pt/README.md)
|
||||
- Русский (Russian): [ru/README.md](ru/README.md)
|
||||
- Tagalog: [tl/README.md](tl/README.md)
|
||||
- Tiếng Việt (Vietnamese): [vi/README.md](vi/README.md)
|
||||
- Vietnamese (canonical): [`docs/vi/`](../vi/)
|
||||
- 简体中文 (Chinese): [zh-CN/README.md](zh-CN/README.md)
|
||||
- Chinese (Simplified): [`docs/i18n/zh-CN/`](zh-CN/)
|
||||
|
||||
## Structure
|
||||
|
||||
|
||||
@ -1,35 +0,0 @@
|
||||
# ZeroClaw Documentation Hub (Arabic)
|
||||
|
||||
This locale hub is enabled for Arabic community support.
|
||||
|
||||
Last synchronized: **March 6, 2026**.
|
||||
|
||||
## Quick Links
|
||||
|
||||
- Arabic docs hub: [README.md](README.md)
|
||||
- Arabic summary: [SUMMARY.md](SUMMARY.md)
|
||||
- English docs hub: [../../README.md](../../README.md)
|
||||
- English summary: [../../SUMMARY.md](../../SUMMARY.md)
|
||||
|
||||
## Coverage Status
|
||||
|
||||
Current status: **hub-level support enabled**. Full document translation is in progress.
|
||||
|
||||
## Other Languages
|
||||
|
||||
- English: [../../../README.md](../../../README.md)
|
||||
- 简体中文: [../zh-CN/README.md](../zh-CN/README.md)
|
||||
- 日本語: [../ja/README.md](../ja/README.md)
|
||||
- 한국어: [../ko/README.md](../ko/README.md)
|
||||
- Tiếng Việt: [../vi/README.md](../vi/README.md)
|
||||
- Tagalog: [../tl/README.md](../tl/README.md)
|
||||
- Español: [../es/README.md](../es/README.md)
|
||||
- Português: [../pt/README.md](../pt/README.md)
|
||||
- Italiano: [../it/README.md](../it/README.md)
|
||||
- Deutsch: [../de/README.md](../de/README.md)
|
||||
- Français: [../fr/README.md](../fr/README.md)
|
||||
- العربية: [README.md](README.md)
|
||||
- हिन्दी: [../hi/README.md](../hi/README.md)
|
||||
- Русский: [../ru/README.md](../ru/README.md)
|
||||
- বাংলা: [../bn/README.md](../bn/README.md)
|
||||
- Ελληνικά: [../el/README.md](../el/README.md)
|
||||
@ -1,20 +0,0 @@
|
||||
# ZeroClaw Docs Summary (Arabic)
|
||||
|
||||
This is the Arabic locale summary entry point.
|
||||
|
||||
Last synchronized: **March 6, 2026**.
|
||||
|
||||
## Entry Points
|
||||
|
||||
- Arabic docs hub: [README.md](README.md)
|
||||
- English docs hub: [../../README.md](../../README.md)
|
||||
- English unified summary: [../../SUMMARY.md](../../SUMMARY.md)
|
||||
|
||||
## Operator References (English Source)
|
||||
|
||||
- [../../commands-reference.md](../../commands-reference.md)
|
||||
- [../../config-reference.md](../../config-reference.md)
|
||||
- [../../providers-reference.md](../../providers-reference.md)
|
||||
- [../../channels-reference.md](../../channels-reference.md)
|
||||
- [../../operations-runbook.md](../../operations-runbook.md)
|
||||
- [../../troubleshooting.md](../../troubleshooting.md)
|
||||
@ -1,35 +0,0 @@
|
||||
# ZeroClaw Documentation Hub (Bengali)
|
||||
|
||||
This locale hub is enabled for Bengali community support.
|
||||
|
||||
Last synchronized: **March 6, 2026**.
|
||||
|
||||
## Quick Links
|
||||
|
||||
- Bengali docs hub: [README.md](README.md)
|
||||
- Bengali summary: [SUMMARY.md](SUMMARY.md)
|
||||
- English docs hub: [../../README.md](../../README.md)
|
||||
- English summary: [../../SUMMARY.md](../../SUMMARY.md)
|
||||
|
||||
## Coverage Status
|
||||
|
||||
Current status: **hub-level support enabled**. Full document translation is in progress.
|
||||
|
||||
## Other Languages
|
||||
|
||||
- English: [../../../README.md](../../../README.md)
|
||||
- 简体中文: [../zh-CN/README.md](../zh-CN/README.md)
|
||||
- 日本語: [../ja/README.md](../ja/README.md)
|
||||
- 한국어: [../ko/README.md](../ko/README.md)
|
||||
- Tiếng Việt: [../vi/README.md](../vi/README.md)
|
||||
- Tagalog: [../tl/README.md](../tl/README.md)
|
||||
- Español: [../es/README.md](../es/README.md)
|
||||
- Português: [../pt/README.md](../pt/README.md)
|
||||
- Italiano: [../it/README.md](../it/README.md)
|
||||
- Deutsch: [../de/README.md](../de/README.md)
|
||||
- Français: [../fr/README.md](../fr/README.md)
|
||||
- العربية: [../ar/README.md](../ar/README.md)
|
||||
- हिन्दी: [../hi/README.md](../hi/README.md)
|
||||
- Русский: [../ru/README.md](../ru/README.md)
|
||||
- বাংলা: [README.md](README.md)
|
||||
- Ελληνικά: [../el/README.md](../el/README.md)
|
||||
@ -1,20 +0,0 @@
|
||||
# ZeroClaw Docs Summary (Bengali)
|
||||
|
||||
This is the Bengali locale summary entry point.
|
||||
|
||||
Last synchronized: **March 6, 2026**.
|
||||
|
||||
## Entry Points
|
||||
|
||||
- Bengali docs hub: [README.md](README.md)
|
||||
- English docs hub: [../../README.md](../../README.md)
|
||||
- English unified summary: [../../SUMMARY.md](../../SUMMARY.md)
|
||||
|
||||
## Operator References (English Source)
|
||||
|
||||
- [../../commands-reference.md](../../commands-reference.md)
|
||||
- [../../config-reference.md](../../config-reference.md)
|
||||
- [../../providers-reference.md](../../providers-reference.md)
|
||||
- [../../channels-reference.md](../../channels-reference.md)
|
||||
- [../../operations-runbook.md](../../operations-runbook.md)
|
||||
- [../../troubleshooting.md](../../troubleshooting.md)
|
||||
@ -1,35 +0,0 @@
|
||||
# ZeroClaw Documentation Hub (German)
|
||||
|
||||
This locale hub is enabled for German community support.
|
||||
|
||||
Last synchronized: **March 6, 2026**.
|
||||
|
||||
## Quick Links
|
||||
|
||||
- German docs hub: [README.md](README.md)
|
||||
- German summary: [SUMMARY.md](SUMMARY.md)
|
||||
- English docs hub: [../../README.md](../../README.md)
|
||||
- English summary: [../../SUMMARY.md](../../SUMMARY.md)
|
||||
|
||||
## Coverage Status
|
||||
|
||||
Current status: **hub-level support enabled**. Full document translation is in progress.
|
||||
|
||||
## Other Languages
|
||||
|
||||
- English: [../../../README.md](../../../README.md)
|
||||
- 简体中文: [../zh-CN/README.md](../zh-CN/README.md)
|
||||
- 日本語: [../ja/README.md](../ja/README.md)
|
||||
- 한국어: [../ko/README.md](../ko/README.md)
|
||||
- Tiếng Việt: [../vi/README.md](../vi/README.md)
|
||||
- Tagalog: [../tl/README.md](../tl/README.md)
|
||||
- Español: [../es/README.md](../es/README.md)
|
||||
- Português: [../pt/README.md](../pt/README.md)
|
||||
- Italiano: [../it/README.md](../it/README.md)
|
||||
- Deutsch: [README.md](README.md)
|
||||
- Français: [../fr/README.md](../fr/README.md)
|
||||
- العربية: [../ar/README.md](../ar/README.md)
|
||||
- हिन्दी: [../hi/README.md](../hi/README.md)
|
||||
- Русский: [../ru/README.md](../ru/README.md)
|
||||
- বাংলা: [../bn/README.md](../bn/README.md)
|
||||
- Ελληνικά: [../el/README.md](../el/README.md)
|
||||
@ -1,20 +0,0 @@
|
||||
# ZeroClaw Docs Summary (German)
|
||||
|
||||
This is the German locale summary entry point.
|
||||
|
||||
Last synchronized: **March 6, 2026**.
|
||||
|
||||
## Entry Points
|
||||
|
||||
- German docs hub: [README.md](README.md)
|
||||
- English docs hub: [../../README.md](../../README.md)
|
||||
- English unified summary: [../../SUMMARY.md](../../SUMMARY.md)
|
||||
|
||||
## Operator References (English Source)
|
||||
|
||||
- [../../commands-reference.md](../../commands-reference.md)
|
||||
- [../../config-reference.md](../../config-reference.md)
|
||||
- [../../providers-reference.md](../../providers-reference.md)
|
||||
- [../../channels-reference.md](../../channels-reference.md)
|
||||
- [../../operations-runbook.md](../../operations-runbook.md)
|
||||
- [../../troubleshooting.md](../../troubleshooting.md)
|
||||
@ -1,35 +0,0 @@
|
||||
# ZeroClaw Documentation Hub (Hindi)
|
||||
|
||||
This locale hub is enabled for Hindi community support.
|
||||
|
||||
Last synchronized: **March 6, 2026**.
|
||||
|
||||
## Quick Links
|
||||
|
||||
- Hindi docs hub: [README.md](README.md)
|
||||
- Hindi summary: [SUMMARY.md](SUMMARY.md)
|
||||
- English docs hub: [../../README.md](../../README.md)
|
||||
- English summary: [../../SUMMARY.md](../../SUMMARY.md)
|
||||
|
||||
## Coverage Status
|
||||
|
||||
Current status: **hub-level support enabled**. Full document translation is in progress.
|
||||
|
||||
## Other Languages
|
||||
|
||||
- English: [../../../README.md](../../../README.md)
|
||||
- 简体中文: [../zh-CN/README.md](../zh-CN/README.md)
|
||||
- 日本語: [../ja/README.md](../ja/README.md)
|
||||
- 한국어: [../ko/README.md](../ko/README.md)
|
||||
- Tiếng Việt: [../vi/README.md](../vi/README.md)
|
||||
- Tagalog: [../tl/README.md](../tl/README.md)
|
||||
- Español: [../es/README.md](../es/README.md)
|
||||
- Português: [../pt/README.md](../pt/README.md)
|
||||
- Italiano: [../it/README.md](../it/README.md)
|
||||
- Deutsch: [../de/README.md](../de/README.md)
|
||||
- Français: [../fr/README.md](../fr/README.md)
|
||||
- العربية: [../ar/README.md](../ar/README.md)
|
||||
- हिन्दी: [README.md](README.md)
|
||||
- Русский: [../ru/README.md](../ru/README.md)
|
||||
- বাংলা: [../bn/README.md](../bn/README.md)
|
||||
- Ελληνικά: [../el/README.md](../el/README.md)
|
||||