Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
6c4e20b
feat: add recipe authoring workbench (#116)
Keith-CY Mar 12, 2026
29148a9
feat: import external recipe libraries
Keith-CY Mar 12, 2026
7993293
fix: simplify dedicated agent recipe import fixture
Keith-CY Mar 12, 2026
9c072e7
feat: allow deleting workspace recipe drafts
Keith-CY Mar 12, 2026
766e6ba
refactor: restyle workspace recipe draft cards
Keith-CY Mar 12, 2026
526c954
test: add dockerized openclaw recipe e2e
Keith-CY Mar 12, 2026
0374156
ci: scope e2e workflow for recipe branch
Keith-CY Mar 12, 2026
e1f0ded
feat: polish bundled recipe workflows
Keith-CY Mar 12, 2026
c6bf6f0
docs: add recipe authoring guide
Keith-CY Mar 12, 2026
d9f8276
feat: expand recipe runner action surface
Keith-CY Mar 12, 2026
ba8460e
docs: update recipe authoring and runner boundaries
Keith-CY Mar 12, 2026
3550eeb
fix: preserve recipe content newlines
Keith-CY Mar 13, 2026
b240dca
feat: align recipe actions with openclaw cli
Keith-CY Mar 13, 2026
39c1223
docs: align recipe action documentation
Keith-CY Mar 13, 2026
f3b0e90
fix: fallback remote recipe discovery to config
Keith-CY Mar 13, 2026
1f8e27b
docs: add local docker openclaw debug guide
Keith-CY Mar 13, 2026
3c78eb7
fix: support recipe URLs and bundled seed lookup
Keith-CY Mar 13, 2026
ba41bd7
fix: resolve bundled recipe assets from _up_
Keith-CY Mar 13, 2026
70a695f
feat: load recipes from single recipe folders
Keith-CY Mar 13, 2026
5315c70
feat: unify recipe source import flow
Keith-CY Mar 13, 2026
e2feb58
fix: make recipe folder picker non-blocking
Keith-CY Mar 13, 2026
0bdb226
feat: add recipe approval and bundled upgrades
Keith-CY Mar 13, 2026
123d3f3
docs: describe recipe trust and upgrade flow
Keith-CY Mar 13, 2026
28cea2f
fix: scope cook auth blockers to active recipe
Keith-CY Mar 13, 2026
979ecb7
fix: stabilize recipe docker approval and identity sync
Keith-CY Mar 13, 2026
98f7150
refactor: defer agent workspaces to openclaw defaults
Keith-CY Mar 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,58 @@ on:
branches:
- main
- develop
- feat/recipe
pull_request:
branches:
- main
- develop
- feat/recipe

concurrency:
group: e2e-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
recipe-docker-e2e:
name: Docker Recipe E2E
runs-on: ubuntu-latest
timeout-minutes: 25
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Install system dependencies
run: |
sudo apt-get update
sudo apt-get install -y \
libwebkit2gtk-4.1-dev \
libappindicator3-dev \
librsvg2-dev \
patchelf \
libssl-dev \
libgtk-3-dev \
libsoup-3.0-dev \
libjavascriptcoregtk-4.1-dev

- name: Setup Rust
uses: dtolnay/rust-toolchain@stable

- name: Cache Rust dependencies
uses: Swatinem/rust-cache@v2
with:
workspaces: src-tauri

- name: Verify Docker is available
run: docker info

- name: Run recipe docker e2e
env:
CLAWPAL_RUN_DOCKER_RECIPE_E2E: "1"
run: cargo test -p clawpal --test recipe_docker_e2e -- --nocapture --test-threads=1
working-directory: src-tauri

profile-e2e:
name: Provider Auth E2E
runs-on: ubuntu-latest
environment: ${{ (github.base_ref == 'main' || github.ref == 'refs/heads/main') && 'production' || 'development' }}
steps:
Expand Down
94 changes: 94 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,17 @@ src-tauri/ Rust + Tauri backend
docs/plans/ Design and implementation plans
```

## Recipe docs

- [`docs/recipe-authoring.md`](docs/recipe-authoring.md) — how to write and package a ClawPal recipe
- [`docs/recipe-cli-action-catalog.md`](docs/recipe-cli-action-catalog.md) — full CLI-backed recipe action catalog and support matrix
- [`docs/recipe-runner-boundaries.md`](docs/recipe-runner-boundaries.md) — runner/backend boundaries and OpenClaw-first design rules

## Testing docs

- [`docs/testing/business-flow-test-matrix.md`](docs/testing/business-flow-test-matrix.md) — local and CI validation layers
- [`docs/testing/local-docker-openclaw-debug.md`](docs/testing/local-docker-openclaw-debug.md) — rebuild the isolated Ubuntu/OpenClaw Docker target used for recipe debugging

## License

Proprietary. All rights reserved.
39 changes: 35 additions & 4 deletions clawpal-core/src/ssh/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ const RUSSH_SFTP_TIMEOUT_SECS: u64 = 30;
#[derive(Clone)]
struct SshHandler;

fn russh_exec_timeout_secs_from_env_var(raw: Option<String>) -> u64 {
raw.and_then(|value| value.trim().parse::<u64>().ok())
.filter(|secs| *secs > 0)
.unwrap_or(RUSSH_EXEC_TIMEOUT_SECS)
}

fn russh_exec_timeout_secs() -> u64 {
russh_exec_timeout_secs_from_env_var(std::env::var("CLAWPAL_RUSSH_EXEC_TIMEOUT_SECS").ok())
}

#[async_trait::async_trait]
impl client::Handler for SshHandler {
type Error = russh::Error;
Expand Down Expand Up @@ -147,7 +157,8 @@ impl SshSession {
.await
.map_err(|e| SshError::CommandFailed(e.to_string()))?;

let wait_result = timeout(Duration::from_secs(RUSSH_EXEC_TIMEOUT_SECS), async {
let exec_timeout_secs = russh_exec_timeout_secs();
let wait_result = timeout(Duration::from_secs(exec_timeout_secs), async {
let mut stdout = Vec::new();
let mut stderr = Vec::new();
let mut exit_code = -1;
Expand All @@ -170,9 +181,7 @@ impl SshSession {
.await;

let (stdout, stderr, exit_code) = wait_result.map_err(|_| {
SshError::CommandFailed(format!(
"russh exec timed out after {RUSSH_EXEC_TIMEOUT_SECS}s"
))
SshError::CommandFailed(format!("russh exec timed out after {exec_timeout_secs}s"))
})?;

Ok(ExecResult {
Expand Down Expand Up @@ -948,4 +957,26 @@ mod tests {
assert!(p.contains("id_ed25519") || p.contains("id_rsa"));
}
}

#[test]
fn russh_exec_timeout_secs_uses_default_without_env_override() {
assert_eq!(
russh_exec_timeout_secs_from_env_var(None),
RUSSH_EXEC_TIMEOUT_SECS
);
assert_eq!(
russh_exec_timeout_secs_from_env_var(Some(String::new())),
RUSSH_EXEC_TIMEOUT_SECS
);
assert_eq!(
russh_exec_timeout_secs_from_env_var(Some("not-a-number".into())),
RUSSH_EXEC_TIMEOUT_SECS
);
}

#[test]
fn russh_exec_timeout_secs_accepts_positive_env_override() {
assert_eq!(russh_exec_timeout_secs_from_env_var(Some("60".into())), 60);
assert_eq!(russh_exec_timeout_secs_from_env_var(Some("5".into())), 5);
}
}
10 changes: 10 additions & 0 deletions docs/mvp-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,13 @@
- [x] 每步显示执行结果、错误态重试入口、命令摘要
- [x] 完成 `ready` 后可直接衔接 Doctor/Recipes 配置流程
- [ ] 四种方式接入真实执行器(当前为可审计命令计划与流程骨架)

## 8. Recipe Authoring Workbench(v0.5)

- [x] 内置 recipe 可 `Fork to workspace`
- [x] Workspace recipe 支持 `New / Save / Save As / Delete`
- [x] UI 可直接编辑 canonical recipe source,并通过后端做 validate / list / plan
- [x] Studio 支持 sample params 与 live plan preview
- [x] Draft 可直接进入 Cook 并执行
- [x] Runtime run 可追溯到 `source origin / source digest / workspace path`
- [x] 至少一个 workspace recipe 可在 `Source / Form` 模式之间往返且不丢关键字段
Loading
Loading