feat(onboard): distributable "APESS Onboard" App Lab app + packaging
Close the last onboarding gap: one shareable App Lab app a student imports and Runs, no adb / no host install. - package-onboard-app.sh: assemble a self-contained bundle — ZeroClaw binary (matrix_text + i2c_scan), single-agent config, skills, responder sketch, and the BAKED cloud token. Ships without .secret_key (each board mints its own) or a team Telegram token; dist/ is gitignored. - onboard-app/config.toml: the canonical packaged config (proven anthropic.max single 'default' agent, matrix + i2c_scan allowlisted, Telegram-ready, secrets stripped). - ONBOARDING.md: the full flow — instructor packages once, student imports + Runs, then the wizard. Notes APESS_URL (mDNS/per-team) + LAN reachability. Validated on-hardware: a freshly-imported bundle mints its key, boots the cloud agent, and runs the matrix + i2c_scan prompts in-container. Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
8ce8474d33
commit
838a0ba334
@@ -0,0 +1,405 @@
|
||||
schema_version = 3
|
||||
|
||||
[providers.models.openrouter.default]
|
||||
temperature = 0.3
|
||||
|
||||
[risk_profiles.default.delegation_policy]
|
||||
mode = "forbidden"
|
||||
|
||||
[risk_profiles.sense_only.delegation_policy]
|
||||
mode = "forbidden"
|
||||
|
||||
[risk_profiles.field_ops.delegation_policy]
|
||||
mode = "forbidden"
|
||||
|
||||
[risk_profiles.field_flash.delegation_policy]
|
||||
mode = "forbidden"
|
||||
|
||||
[risk_profiles.demo.delegation_policy]
|
||||
mode = "forbidden"
|
||||
|
||||
[runtime_profiles.unoq.context_compression]
|
||||
enabled = true
|
||||
identifier_policy = "strict"
|
||||
max_passes = 3
|
||||
protect_first_n = 3
|
||||
protect_last_n = 4
|
||||
source_max_chars = 50000
|
||||
summary_max_chars = 4000
|
||||
summary_provider = ""
|
||||
threshold_ratio = 0.5
|
||||
timeout_secs = 60
|
||||
tool_result_retrim_chars = 2000
|
||||
tool_result_trim_exempt = []
|
||||
|
||||
[runtime_profiles.unoq.eval]
|
||||
enabled = false
|
||||
max_retries = 1
|
||||
min_quality_score = 0.5
|
||||
|
||||
[runtime_profiles.unoq.history_pruning]
|
||||
collapse_tool_results = true
|
||||
enabled = false
|
||||
keep_recent = 4
|
||||
max_tokens = 8192
|
||||
|
||||
[runtime_profiles.unoq.thinking]
|
||||
default_level = "medium"
|
||||
native_thinking = false
|
||||
|
||||
[runtime_profiles.unoq.tool_receipts]
|
||||
enabled = false
|
||||
inject_system_prompt = true
|
||||
show_in_response = false
|
||||
|
||||
[runtime_profiles.offline.context_compression]
|
||||
enabled = true
|
||||
identifier_policy = "strict"
|
||||
max_passes = 3
|
||||
protect_first_n = 3
|
||||
protect_last_n = 4
|
||||
source_max_chars = 50000
|
||||
summary_max_chars = 4000
|
||||
summary_provider = ""
|
||||
threshold_ratio = 0.5
|
||||
timeout_secs = 60
|
||||
tool_result_retrim_chars = 2000
|
||||
tool_result_trim_exempt = []
|
||||
|
||||
[runtime_profiles.offline.eval]
|
||||
enabled = false
|
||||
max_retries = 1
|
||||
min_quality_score = 0.5
|
||||
|
||||
[runtime_profiles.offline.history_pruning]
|
||||
collapse_tool_results = true
|
||||
enabled = false
|
||||
keep_recent = 4
|
||||
max_tokens = 8192
|
||||
|
||||
[runtime_profiles.offline.thinking]
|
||||
default_level = "medium"
|
||||
native_thinking = false
|
||||
|
||||
[runtime_profiles.offline.tool_receipts]
|
||||
enabled = false
|
||||
inject_system_prompt = true
|
||||
show_in_response = false
|
||||
|
||||
[agents.default.a2a]
|
||||
exposed_skills = []
|
||||
published = false
|
||||
|
||||
[agents.default.identity]
|
||||
format = "openclaw"
|
||||
|
||||
[agents.default.memory]
|
||||
backend = "sqlite"
|
||||
|
||||
[agents.default.precheck]
|
||||
enabled = true
|
||||
timeout_secs = 5
|
||||
|
||||
[agents.default.workspace]
|
||||
read_memory_from = []
|
||||
unrestricted_filesystem = false
|
||||
|
||||
[agents.cloud.a2a]
|
||||
exposed_skills = []
|
||||
published = false
|
||||
|
||||
[agents.cloud.identity]
|
||||
format = "openclaw"
|
||||
|
||||
[agents.cloud.memory]
|
||||
backend = "sqlite"
|
||||
|
||||
[agents.cloud.precheck]
|
||||
enabled = true
|
||||
timeout_secs = 5
|
||||
|
||||
[agents.cloud.workspace]
|
||||
read_memory_from = []
|
||||
unrestricted_filesystem = false
|
||||
|
||||
[agents.demo.a2a]
|
||||
exposed_skills = []
|
||||
published = false
|
||||
|
||||
[agents.demo.identity]
|
||||
format = "openclaw"
|
||||
|
||||
[agents.demo.memory]
|
||||
backend = "sqlite"
|
||||
|
||||
[agents.demo.precheck]
|
||||
enabled = true
|
||||
timeout_secs = 5
|
||||
|
||||
[agents.demo.workspace]
|
||||
read_memory_from = []
|
||||
unrestricted_filesystem = false
|
||||
|
||||
[[peripherals.boards]]
|
||||
baud = 115200
|
||||
board = "arduino-uno-q"
|
||||
transport = "bridge"
|
||||
|
||||
[peer_groups.telegram_default]
|
||||
admin_for_agent_scope = false
|
||||
agents = []
|
||||
channel = "telegram.default"
|
||||
external_peers = ["8512813413"]
|
||||
ignore = []
|
||||
output_modality = "mirror"
|
||||
|
||||
[providers.models.custom.cloud]
|
||||
uri = "http://127.0.0.1:8091/v1"
|
||||
model = "sonnet"
|
||||
native_tools = false
|
||||
|
||||
[runtime_profiles.unoq.thinking.budget_tokens]
|
||||
|
||||
[runtime_profiles.offline.thinking.budget_tokens]
|
||||
|
||||
[agents.default.workspace.access]
|
||||
|
||||
[agents.cloud.workspace.access]
|
||||
|
||||
[agents.demo.workspace.access]
|
||||
|
||||
# Native Anthropic via a Claude Max setup-token (sk-ant-oat01-…). Credential
|
||||
# comes from the ANTHROPIC_OAUTH_TOKEN env on the daemon — kept OFF DISK.
|
||||
|
||||
[providers.models.anthropic.max]
|
||||
model = "claude-sonnet-5"
|
||||
|
||||
[providers.models.custom.claude]
|
||||
uri = "http://127.0.0.1:8091/v1"
|
||||
model = "sonnet"
|
||||
native_tools = false
|
||||
fallback = ["llamacpp.local"]
|
||||
|
||||
[providers.models.llamacpp]
|
||||
|
||||
[providers.models.llamacpp.local]
|
||||
uri = "http://127.0.0.1:8083/v1"
|
||||
timeout_secs = 300
|
||||
model = "qwen"
|
||||
native_tools = false
|
||||
|
||||
[providers.models.custom]
|
||||
|
||||
[gateway]
|
||||
port = 8080
|
||||
host = "0.0.0.0"
|
||||
allow_public_bind = true
|
||||
require_pairing = false
|
||||
web_dist_dir = "/app/web-dist"
|
||||
paired_tokens = []
|
||||
|
||||
[skills]
|
||||
prompt_injection_mode = "compact"
|
||||
|
||||
[risk_profiles.default]
|
||||
level = "supervised"
|
||||
allowed_tools = ["matrix_pattern", "matrix_text", "i2c_scan", "uno_q_flash", "sysfs_led", "camera", "network", "i2cdetect", "read_skill", "file_read", "content_search"]
|
||||
auto_approve = ["matrix_pattern", "matrix_text", "i2c_scan", "uno_q_flash", "sysfs_led", "camera", "network", "i2cdetect", "read_skill", "file_read", "content_search", "memory_recall", "web_search_tool", "web_fetch", "calculator", "glob_search", "image_info", "weather", "tool_search", "browser", "browser_open"]
|
||||
allowed_commands = ["git", "npm", "cargo", "ls", "cat", "grep", "find", "echo", "pwd", "wc", "head", "tail", "date", "df", "du", "uname", "uptime", "hostname", "python", "python3", "pip", "node", "free"]
|
||||
allowed_roots = []
|
||||
always_ask = []
|
||||
block_high_risk_commands = true
|
||||
excluded_tools = []
|
||||
firejail_args = []
|
||||
forbidden_paths = ["/etc", "/root", "/home", "/usr", "/bin", "/sbin", "/lib", "/opt", "/boot", "/dev", "/proc", "/sys", "/var", "/tmp", "~/.ssh", "~/.gnupg", "~/.aws", "~/.config"]
|
||||
require_approval_for_medium_risk = true
|
||||
shell_env_passthrough = []
|
||||
workspace_only = true
|
||||
|
||||
[runtime_profiles.unoq]
|
||||
agentic = true
|
||||
max_tool_iterations = 6
|
||||
strict_tool_parsing = false
|
||||
max_actions_per_hour = 20
|
||||
max_cost_per_day_cents = 500
|
||||
max_delegation_depth = 0
|
||||
shell_timeout_secs = 60
|
||||
tool_call_dedup_exempt = []
|
||||
tool_filter_groups = []
|
||||
|
||||
[agents.default]
|
||||
enabled = true
|
||||
model_provider = "anthropic.max"
|
||||
risk_profile = "default"
|
||||
runtime_profile = "unoq"
|
||||
acp_enable_mcp = false
|
||||
channels = ["telegram.default"]
|
||||
classifier_provider = ""
|
||||
cron_jobs = []
|
||||
delegate_same_risk_profile = true
|
||||
delegates = []
|
||||
knowledge_bundles = []
|
||||
mcp_bundles = []
|
||||
skill_bundles = ["unoq"]
|
||||
summary_provider = ""
|
||||
transcription_provider = ""
|
||||
tts_provider = ""
|
||||
|
||||
[peripherals]
|
||||
enabled = true
|
||||
|
||||
[agents.cloud]
|
||||
enabled = false
|
||||
model_provider = "anthropic.max"
|
||||
risk_profile = "default"
|
||||
runtime_profile = "unoq"
|
||||
acp_enable_mcp = false
|
||||
channels = []
|
||||
classifier_provider = ""
|
||||
cron_jobs = []
|
||||
delegate_same_risk_profile = true
|
||||
delegates = []
|
||||
knowledge_bundles = []
|
||||
mcp_bundles = []
|
||||
skill_bundles = ["unoq"]
|
||||
summary_provider = ""
|
||||
transcription_provider = ""
|
||||
tts_provider = ""
|
||||
|
||||
[providers.models.custom.dead]
|
||||
uri = "http://127.0.0.1:9099/v1"
|
||||
model = "sonnet"
|
||||
native_tools = false
|
||||
fallback = ["llamacpp.local"]
|
||||
|
||||
[channels.voice_duplex.default]
|
||||
enabled = true
|
||||
excluded_tools = []
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# LEAN OFFLINE PROFILE (experiment 2026-07-19)
|
||||
# Everything that controls prompt size lives on the runtime profile.
|
||||
# Goal: get the prompt from ~4718 tokens down under ~800 so the on-board
|
||||
# 0.5B (17 tok/s prefill) can actually answer in seconds, not minutes.
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
[runtime_profiles.offline]
|
||||
agentic = true
|
||||
max_tool_iterations = 3
|
||||
strict_tool_parsing = false
|
||||
compact_context = true
|
||||
prompt_injection_mode = "compact"
|
||||
max_system_prompt_chars = 2000
|
||||
max_context_tokens = 3000
|
||||
max_history_messages = 2
|
||||
memory_recall_limit = 1
|
||||
parallel_tools = false
|
||||
max_actions_per_hour = 20
|
||||
max_cost_per_day_cents = 500
|
||||
max_delegation_depth = 0
|
||||
shell_timeout_secs = 60
|
||||
tool_call_dedup_exempt = []
|
||||
tool_filter_groups = []
|
||||
|
||||
# Narrow tool surface. Dropping the other peripheral tools also drops the
|
||||
# hardware block + Uno-Q flash imperative from the system prompt entirely.
|
||||
|
||||
[risk_profiles.sense_only]
|
||||
level = "supervised"
|
||||
allowed_tools = ["i2cdetect"]
|
||||
auto_approve = ["i2cdetect"]
|
||||
allowed_commands = ["git", "npm", "cargo", "ls", "cat", "grep", "find", "echo", "pwd", "wc", "head", "tail", "date", "df", "du", "uname", "uptime", "hostname", "python", "python3", "pip", "node", "free"]
|
||||
allowed_roots = []
|
||||
always_ask = []
|
||||
block_high_risk_commands = true
|
||||
excluded_tools = []
|
||||
firejail_args = []
|
||||
forbidden_paths = ["/etc", "/root", "/home", "/usr", "/bin", "/sbin", "/lib", "/opt", "/boot", "/dev", "/proc", "/sys", "/var", "/tmp", "~/.ssh", "~/.gnupg", "~/.aws", "~/.config"]
|
||||
require_approval_for_medium_risk = true
|
||||
shell_env_passthrough = []
|
||||
workspace_only = true
|
||||
|
||||
[risk_profiles.field_ops]
|
||||
level = "supervised"
|
||||
allowed_tools = ["i2cdetect", "sysfs_led", "file_read", "content_search", "network"]
|
||||
auto_approve = ["i2cdetect", "sysfs_led", "file_read", "content_search", "network"]
|
||||
allowed_commands = ["git", "npm", "cargo", "ls", "cat", "grep", "find", "echo", "pwd", "wc", "head", "tail", "date", "df", "du", "uname", "uptime", "hostname", "python", "python3", "pip", "node", "free"]
|
||||
allowed_roots = []
|
||||
always_ask = []
|
||||
block_high_risk_commands = true
|
||||
excluded_tools = []
|
||||
firejail_args = []
|
||||
forbidden_paths = ["/etc", "/root", "/home", "/usr", "/bin", "/sbin", "/lib", "/opt", "/boot", "/dev", "/proc", "/sys", "/var", "/tmp", "~/.ssh", "~/.gnupg", "~/.aws", "~/.config"]
|
||||
require_approval_for_medium_risk = true
|
||||
shell_env_passthrough = []
|
||||
workspace_only = true
|
||||
|
||||
[risk_profiles.field_flash]
|
||||
level = "supervised"
|
||||
allowed_tools = ["i2cdetect", "sysfs_led", "file_read", "content_search", "network", "uno_q_flash"]
|
||||
auto_approve = ["i2cdetect", "sysfs_led", "file_read", "content_search", "network", "uno_q_flash"]
|
||||
allowed_commands = ["git", "npm", "cargo", "ls", "cat", "grep", "find", "echo", "pwd", "wc", "head", "tail", "date", "df", "du", "uname", "uptime", "hostname", "python", "python3", "pip", "node", "free"]
|
||||
allowed_roots = []
|
||||
always_ask = []
|
||||
block_high_risk_commands = true
|
||||
excluded_tools = []
|
||||
firejail_args = []
|
||||
forbidden_paths = ["/etc", "/root", "/home", "/usr", "/bin", "/sbin", "/lib", "/opt", "/boot", "/dev", "/proc", "/sys", "/var", "/tmp", "~/.ssh", "~/.gnupg", "~/.aws", "~/.config"]
|
||||
require_approval_for_medium_risk = true
|
||||
shell_env_passthrough = []
|
||||
workspace_only = true
|
||||
|
||||
[risk_profiles.demo]
|
||||
level = "supervised"
|
||||
allowed_tools = ["matrix_pattern", "i2cdetect"]
|
||||
auto_approve = ["matrix_pattern", "i2cdetect"]
|
||||
allowed_commands = ["git", "npm", "cargo", "ls", "cat", "grep", "find", "echo", "pwd", "wc", "head", "tail", "date", "df", "du", "uname", "uptime", "hostname", "python", "python3", "pip", "node", "free"]
|
||||
allowed_roots = []
|
||||
always_ask = []
|
||||
block_high_risk_commands = true
|
||||
excluded_tools = []
|
||||
firejail_args = []
|
||||
forbidden_paths = ["/etc", "/root", "/home", "/usr", "/bin", "/sbin", "/lib", "/opt", "/boot", "/dev", "/proc", "/sys", "/var", "/tmp", "~/.ssh", "~/.gnupg", "~/.aws", "~/.config"]
|
||||
require_approval_for_medium_risk = true
|
||||
shell_env_passthrough = []
|
||||
workspace_only = true
|
||||
|
||||
[agents.demo]
|
||||
enabled = false
|
||||
model_provider = "anthropic.max"
|
||||
risk_profile = "default"
|
||||
runtime_profile = "unoq"
|
||||
skill_bundles = ["unoq"]
|
||||
mcp_bundles = []
|
||||
channels = ["telegram.default"]
|
||||
acp_enable_mcp = false
|
||||
classifier_provider = ""
|
||||
cron_jobs = []
|
||||
delegate_same_risk_profile = true
|
||||
delegates = []
|
||||
knowledge_bundles = []
|
||||
summary_provider = ""
|
||||
transcription_provider = ""
|
||||
tts_provider = ""
|
||||
|
||||
[channels.telegram.default]
|
||||
enabled = true
|
||||
bot_token = ""
|
||||
api_base_url = "https://api.telegram.org"
|
||||
approval_timeout_secs = 120
|
||||
draft_update_interval_ms = 1000
|
||||
excluded_tools = []
|
||||
interrupt_on_new_message = false
|
||||
mention_only = false
|
||||
reply_min_interval_secs = 0
|
||||
reply_queue_depth_max = 0
|
||||
stream_mode = "off"
|
||||
|
||||
# All Uno Q hardware skills (led-matrix, uno-q-hardware, flashing, sketch-patterns,
|
||||
# modulino, bridge, i2c/spi, ADXL355 context…) loaded onto every agent so it knows
|
||||
# the board it is on and how to interface with the onboard devices.
|
||||
|
||||
[skill_bundles.unoq]
|
||||
directory = "shared/skills"
|
||||
include = []
|
||||
exclude = []
|
||||
Reference in New Issue
Block a user