cc-workflow 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. cc_workflow-0.1.0.dist-info/METADATA +495 -0
  2. cc_workflow-0.1.0.dist-info/RECORD +49 -0
  3. cc_workflow-0.1.0.dist-info/WHEEL +5 -0
  4. cc_workflow-0.1.0.dist-info/entry_points.txt +2 -0
  5. cc_workflow-0.1.0.dist-info/licenses/LICENSE +21 -0
  6. cc_workflow-0.1.0.dist-info/top_level.txt +1 -0
  7. wflow/__init__.py +8 -0
  8. wflow/adapters/__init__.py +0 -0
  9. wflow/adapters/claude_cli.py +293 -0
  10. wflow/adapters/notifiers/__init__.py +15 -0
  11. wflow/adapters/notifiers/base.py +26 -0
  12. wflow/adapters/notifiers/registry.py +39 -0
  13. wflow/adapters/notifiers/welink.py +38 -0
  14. wflow/adapters/opencode_cli.py +325 -0
  15. wflow/adapters/script_runner.py +97 -0
  16. wflow/api/__init__.py +0 -0
  17. wflow/api/cron.py +134 -0
  18. wflow/api/deps.py +28 -0
  19. wflow/api/runs.py +415 -0
  20. wflow/api/status.py +66 -0
  21. wflow/api/workflows.py +74 -0
  22. wflow/cli/__init__.py +0 -0
  23. wflow/cli/main.py +337 -0
  24. wflow/common/__init__.py +0 -0
  25. wflow/common/json_parser.py +52 -0
  26. wflow/common/time_utils.py +8 -0
  27. wflow/common/workspace.py +49 -0
  28. wflow/engine/__init__.py +0 -0
  29. wflow/engine/executor.py +605 -0
  30. wflow/engine/node_handler.py +298 -0
  31. wflow/engine/node_runner.py +47 -0
  32. wflow/engine/scheduler.py +180 -0
  33. wflow/engine/session_manager.py +125 -0
  34. wflow/engine/state_machine.py +41 -0
  35. wflow/engine/template.py +62 -0
  36. wflow/logging.py +160 -0
  37. wflow/main.py +122 -0
  38. wflow/models/__init__.py +0 -0
  39. wflow/models/db.py +103 -0
  40. wflow/models/workflow.py +97 -0
  41. wflow/services/__init__.py +0 -0
  42. wflow/services/execution_svc.py +138 -0
  43. wflow/services/run_launcher.py +232 -0
  44. wflow/services/schedule_svc.py +56 -0
  45. wflow/services/workflow_svc.py +68 -0
  46. wflow/web/css/style.css +972 -0
  47. wflow/web/index.html +349 -0
  48. wflow/web/js/app.js +729 -0
  49. wflow/web/js/utils.js +30 -0
@@ -0,0 +1,495 @@
1
+ Metadata-Version: 2.4
2
+ Name: cc-workflow
3
+ Version: 0.1.0
4
+ Summary: AI workflow orchestrator built on Claude Code CLI / OpenCode CLI
5
+ Author-email: MooYeh <yangtao279@huawei.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/MooYeh279/cc-workflow
8
+ Project-URL: Repository, https://github.com/MooYeh279/cc-workflow
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Topic :: Software Development :: Build Tools
17
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
18
+ Requires-Python: >=3.11
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: fastapi>=0.110
22
+ Requires-Dist: uvicorn[standard]
23
+ Requires-Dist: sqlalchemy[asyncio]>=2.0
24
+ Requires-Dist: aiosqlite
25
+ Requires-Dist: pydantic>=2.0
26
+ Requires-Dist: apscheduler>=3.10
27
+ Requires-Dist: click>=8.0
28
+ Requires-Dist: httpx>=0.27
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest>=8.0; extra == "dev"
31
+ Requires-Dist: pytest-asyncio; extra == "dev"
32
+ Requires-Dist: pytest-cov; extra == "dev"
33
+ Requires-Dist: pytest-playwright; extra == "dev"
34
+ Requires-Dist: httpx; extra == "dev"
35
+ Dynamic: license-file
36
+
37
+ # WFlow — 工作流编排器
38
+
39
+ 基于 Claude Code CLI / OpenCode CLI 的 AI 工作流编排工具。通过 JSON 定义工作流 DAG,支持条件分支、回路(Loop-back)、人工审核(Human Review)、Session 复用、断点续跑、定时触发。
40
+
41
+ ## 安装
42
+
43
+ ```bash
44
+ cd cc-workflow
45
+ pip install -e ".[dev]"
46
+ wflow --help
47
+ ```
48
+
49
+ **前置依赖:** Python 3.11+,系统已安装 `claude` 和/或 `opencode` CLI 工具。
50
+
51
+ ---
52
+
53
+ ## 快速开始
54
+
55
+ ```bash
56
+ # 1. 启动服务
57
+ wflow server start --port 8100
58
+
59
+ # 2. 导入工作流
60
+ wflow workflow create examples/code-review.json
61
+
62
+ # 3. 启动任务
63
+ wflow run start <workflow-id> --input requirement="编写一个 Python 计算器"
64
+
65
+ # 4. 查看状态(实时日志)
66
+ wflow run logs <run-id> --follow
67
+
68
+ # 5. 设置每天早上 9 点自动触发
69
+ wflow cron add <workflow-id> "0 9 * * *"
70
+
71
+ # 6. 打开 Web 界面
72
+ # → http://localhost:8100
73
+ ```
74
+
75
+ ---
76
+
77
+ ## 工作流 JSON 配置
78
+
79
+ ### 节点类型
80
+
81
+ 支持 4 种节点类型:`claude`、`opencode`、`script`、`human_review`。
82
+
83
+ ### Claude 节点
84
+
85
+ 调用 Claude Code CLI,`prompt` 为纯角色/任务描述,系统自动注入上下文:
86
+
87
+ ```json
88
+ {
89
+ "id": "coding",
90
+ "type": "claude",
91
+ "prompt": "你是一个资深软件工程师。根据用户输入编写代码并写入文件。",
92
+ "tools": { "allowed": ["Read","Write","Edit","Bash","Grep"] },
93
+ "model": "deepseek-v4-pro",
94
+ "output": {
95
+ "type": "object",
96
+ "properties": {
97
+ "files_changed": { "type": "array", "items": { "type": "string" } },
98
+ "summary": { "type": "string" }
99
+ }
100
+ },
101
+ "retry": { "max_retries": 2 }
102
+ }
103
+ ```
104
+
105
+ | 字段 | 说明 |
106
+ |------|------|
107
+ | `prompt` | 角色/任务描述(纯文本,系统自动注入上游输出和用户输入) |
108
+ | `tools.allowed` | 允许的工具 `["Read","Write","Edit","Bash","Grep"]` |
109
+ | `tools.disallowed` | 禁用的工具 |
110
+ | `model` | 模型名称(如 `sonnet`、`opus`、`deepseek-v4-pro`) |
111
+ | `output` | JSON Schema,Claude 必须输出符合此格式的 JSON |
112
+ | `retry.max_retries` | 失败重试次数 |
113
+
114
+ ### OpenCode 节点
115
+
116
+ ```json
117
+ {
118
+ "id": "review",
119
+ "type": "opencode",
120
+ "prompt": "审查上游代码,输出审查意见。",
121
+ "model": "deepseek-v4-pro",
122
+ "output": {
123
+ "type": "object",
124
+ "properties": {
125
+ "approved": { "type": "boolean" },
126
+ "feedback": { "type": "string" }
127
+ }
128
+ },
129
+ "retry": { "max_retries": 1 }
130
+ }
131
+ ```
132
+
133
+ 配置字段与 Claude 节点类似,但不支持 `tools` 配置。
134
+
135
+ ### Script 节点
136
+
137
+ 通过 subprocess 执行外部命令,stdin 传入上下文 JSON,stdout 捕获输出:
138
+
139
+ ```json
140
+ {
141
+ "id": "validate",
142
+ "type": "script",
143
+ "command": "python ./scripts/validate.py",
144
+ "timeout_seconds": 60,
145
+ "output": {
146
+ "type": "object",
147
+ "properties": { "passed": { "type": "boolean" } }
148
+ }
149
+ }
150
+ ```
151
+
152
+ | 字段 | 说明 |
153
+ |------|------|
154
+ | `command` | 要执行的命令 |
155
+ | `timeout_seconds` | 超时秒数(默认 300) |
156
+ | `output` | JSON Schema,脚本 stdout 必须匹配 |
157
+
158
+ 脚本通过 stdin 接收:`{"inputs": {...}, "upstream": {...}, "nodes": {...}, "run": {...}}`
159
+
160
+ ### Human Review 节点
161
+
162
+ 人工审核节点——执行到该节点时 workflow 暂停,等待人工通过/驳回:
163
+
164
+ ```json
165
+ {
166
+ "id": "review_design",
167
+ "type": "human_review",
168
+ "prompt": "请审核上游设计方案。通过则进入下一阶段,驳回则退回设计节点修改。",
169
+ "output": {
170
+ "type": "object",
171
+ "properties": {
172
+ "approved": { "type": "boolean" },
173
+ "feedback": { "type": "string" }
174
+ }
175
+ }
176
+ }
177
+ ```
178
+
179
+ - **通过 (approved=true)**: 上游节点的产出透传到下一个节点(审批元数据 `approved`/`feedback` 也会保留)
180
+ - **驳回 (approved=false)**: 通过条件边 `{{ nodes.xxx.output.approved }} == false` 回路到上游重做
181
+ - 审核 API: `POST /runs/{id}/nodes/{node_id}/review` `{"approved": true, "feedback": ""}`
182
+ - 示例见 `examples/human-review-workflow.json`
183
+
184
+ ### 条件分支
185
+
186
+ 边 (edge) 上的 `condition` 支持 `{{ }}` 模板:
187
+
188
+ ```json
189
+ {
190
+ "edges": [
191
+ { "from": "review", "to": "coding",
192
+ "condition": "{{ nodes.review.output.approved }} == false" },
193
+ { "from": "review", "to": null,
194
+ "condition": "{{ nodes.review.output.approved }} == true" }
195
+ ]
196
+ }
197
+ ```
198
+
199
+ - 无 `condition` 的边为无条件边(始终可通行)
200
+ - `to: null` 表示终止(流程结束)
201
+ - 条件边按数组顺序求值,匹配的第一条生效
202
+
203
+ ### 系统自动注入上下文
204
+
205
+ ```
206
+ ## 角色任务
207
+ <prompt原文>
208
+
209
+ ## 用户输入 ← 首节点
210
+ {"requirement": "编写快排算法"}
211
+
212
+ ## 上游节点输出 ← 后续节点
213
+ {"files_changed": [...], "summary": "..."}
214
+
215
+ ## 上次输出错误 ← 重试时
216
+ No valid JSON found — 请修正后重新输出
217
+ ```
218
+
219
+ ### 模板变量
220
+
221
+ | 变量 | 示例 | 说明 |
222
+ |------|------|------|
223
+ | `{{ nodes.<id>.output.<key> }}` | `{{ nodes.review.output.approved }}` | 节点输出字段 |
224
+ | `{{ nodes.<id>.status }}` | `completed` | 节点状态 |
225
+ | `{{ inputs.<key> }}` | `{{ inputs.requirement }}` | 用户输入 |
226
+
227
+ ### 完整示例
228
+
229
+ 参见 `examples/` 目录:
230
+ - `examples/simple-script.json` — Script 单节点
231
+ - `examples/simple-opencode.json` — OpenCode 审查回路
232
+ - `examples/code-review.json` — Claude 代码审查回路
233
+ - `examples/complex-workflow.json` — 多起点+汇集+回路,含三种节点类型
234
+ - `examples/human-review-workflow.json` — Claude + 人工审核回路
235
+ - `examples/design-review-workflow.json` — 需求分析→设计→评审→计划→评审,双层人工审核
236
+
237
+ ---
238
+
239
+ ## CLI 命令参考
240
+
241
+ ### 服务管理
242
+
243
+ ```bash
244
+ wflow server start [--host 127.0.0.1] [--port 8100] [--db ./data/workflows.db]
245
+ ```
246
+
247
+ ### 工作流管理
248
+
249
+ ```bash
250
+ wflow workflow list [--status active]
251
+ wflow workflow show <workflow-id>
252
+ wflow workflow create <file.json>
253
+ ```
254
+
255
+ ### 运行管理
256
+
257
+ ```bash
258
+ wflow run start <workflow-id> [--input key=value ...] [--watch]
259
+ wflow run status <run-id>
260
+ wflow run pause <run-id>
261
+ wflow run resume <run-id>
262
+ wflow run stop <run-id>
263
+ wflow run logs <run-id> [--follow] [--level info]
264
+ ```
265
+
266
+ ### 定时任务
267
+
268
+ ```bash
269
+ wflow cron list
270
+ wflow cron add <workflow-id> <cron-expr>
271
+ wflow cron toggle <cron-id>
272
+ wflow cron remove <cron-id>
273
+ ```
274
+
275
+ **Cron 表达式:**
276
+
277
+ 支持 5 字段(分钟级)和 6 字段(秒级):
278
+
279
+ | 表达式 | 含义 |
280
+ |--------|------|
281
+ | `0 9 * * *` | 每天 9:00 |
282
+ | `*/5 * * * *` | 每 5 分钟 |
283
+ | `*/10 * * * * *` | 每 10 秒(6 字段) |
284
+ | `0 */6 * * *` | 每 6 小时 |
285
+ | `30 8 * * 1-5` | 工作日 8:30 |
286
+ | `0 0 1 * *` | 每月 1 号 |
287
+
288
+ ---
289
+
290
+ ## Skills 与脚本
291
+
292
+ wflow 启动时自动检测项目根目录下的 `.claude`、`.opencode`、`.wflow` 目录,并在每次 run 的工作目录中创建**拷贝或符号链接**:
293
+
294
+ ```
295
+ 项目根目录/
296
+ ├── .claude/
297
+ │ ├── settings.json # Claude Code 配置
298
+ │ ├── CLAUDE.md # 项目级别指令(Claude 自动读取)
299
+ │ └── skills/ # 自定义 skills
300
+ ├── .opencode/
301
+ │ └── opencode.json # OpenCode 配置
302
+ └── .wflow/
303
+ └── validate.py # 自定义脚本 / 工具
304
+ ```
305
+
306
+ ### 工作原理
307
+
308
+ 1. 服务启动时通过 `WFLOW_PROJECT_DIR` 环境变量(默认当前目录)检测上述目录
309
+ 2. 每次创建 run 工作目录时,将检测到的目录**复制或符号链接**进去
310
+ 3. 工作目录内的 Claude/OpenCode 节点可直接使用项目 skills、配置和脚本
311
+
312
+ ### 配置方式
313
+
314
+ ```bash
315
+ # 方式 1: 在项目根目录启动服务(自动检测当前目录)
316
+ cd my-project
317
+ wflow server start --port 8100
318
+
319
+ # 方式 2: 显式指定项目目录
320
+ wflow server start --port 8100 --project-dir /path/to/project
321
+
322
+ # 方式 3: 环境变量
323
+ WFLOW_PROJECT_DIR=/path/to/project wflow server start
324
+ ```
325
+
326
+ ### 使用场景
327
+
328
+ | 场景 | 配置方式 |
329
+ |------|---------|
330
+ | Claude 节点触发 skill | 项目根目录下放置 `.claude/skills/` 或 `.claude/CLAUDE.md` |
331
+ | OpenCode 节点使用配置 | 项目根目录下放置 `.opencode/opencode.json` |
332
+ | Script 节点引用脚本 | `"command": "python .wflow/validate.py"`(脚本放在 `.wflow/` 下)|
333
+
334
+ > **注意:** 拷贝发生在 run 创建时。如果更新了 skill 或配置,需要**重新启动 run** 才会生效。
335
+
336
+ ---
337
+
338
+ ## Web UI
339
+
340
+ 启动服务后访问 `http://localhost:8100`。
341
+
342
+ ### 页面概览
343
+
344
+ | 页面 | 功能 |
345
+ |------|------|
346
+ | Dashboard | 运行中/已完成/失败工作流统计 |
347
+ | Workflows | 列表、JSON 创建、一键启动、**DAG 拓扑图预览** |
348
+ | Runs | 运行列表、**DAG 状态图(支持 Ctrl+滚轮缩放/拖拽)**、节点执行详情、工作目录文件浏览、日志查看 |
349
+ | Cron | 定时任务管理:**动态参数表单**、Cron 预设、启用/禁用 |
350
+
351
+ ### Workflows 页面
352
+
353
+ ![Workflows](docs/images/workflows.jpg)
354
+
355
+ 1. 点击 **+ Create** 粘贴 JSON 创建工作流
356
+ 2. 每个工作流卡片显示节点数、边数、输入 Schema
357
+ 3. 点击 **▶ Run** → 弹窗填写参数 → 启动
358
+ 4. 点击 **◈ DAG** → 查看工作流拓扑图
359
+ 5. 点击 **Del** → 删除
360
+
361
+ ### Runs 页面
362
+
363
+ ![Run Detail](docs/images/run-detail.jpg)
364
+
365
+ 1. 点击运行记录旁的 **Details** 进入详情
366
+ 2. **Workflow Graph**: 展开查看 DAG 状态图
367
+ - 绿色节点 = 已完成,橙色 = 运行中,紫色 = 等待审核
368
+ - 绿色边 = 已通过路径,灰色虚线 = 回路
369
+ - **Ctrl + 滚轮** 缩放,鼠标拖拽平移
370
+ 3. **Files**: 左侧文件树浏览器,右侧文件内容查看,支持拖动分隔条调整宽度
371
+ 4. **Node Executions**: 折叠展开每个节点的执行详情(输入/输出/错误)
372
+ 5. **Recent Logs**: 最新日志在上,textarea 展示,支持滚动
373
+
374
+ ### 人工审核
375
+
376
+ <!-- TODO: 截图审核弹窗 -->
377
+ ![Review](docs/images/review.jpg)
378
+
379
+ 当工作流执行到 `human_review` 节点时:
380
+ 1. Runs 页面该 run 旁出现 **Review** 按钮
381
+ 2. 点击进入审核弹窗,查看上游产出和审核说明
382
+ 3. 选择 **Approve**(通过)或 **Reject**(驳回)
383
+ 4. 驳回需填写反馈意见,上游节点将根据反馈重做
384
+
385
+ ### Cron 页面
386
+
387
+ <!-- TODO: 截图 cron 创建表单 -->
388
+ ![Cron](docs/images/crons.jpg)
389
+
390
+ 1. 点击 **+ New Job** 展开创建表单
391
+ 2. **Workflow** 下拉选择 → 自动加载该工作流的输入 Schema,每个参数独立填写
392
+ 3. **Cron Expression**: 点击预设按钮(5min / Hourly / Daily 9am 等)快速填入,也支持手动输入 5 或 6 字段表达式
393
+ 4. 表格中点击 **Latest Run** 列的 run ID 可跳转查看运行详情
394
+ 5. **Pause / Resume** 启用/禁用定时任务
395
+
396
+ ---
397
+
398
+ ## REST API
399
+
400
+ | 方法 | 路径 | 说明 |
401
+ |------|------|------|
402
+ | `GET` | `/api/v1/status` | 服务器状态 |
403
+ | `POST` | `/api/v1/workflows` | 创建工作流 |
404
+ | `GET` | `/api/v1/workflows` | 工作流列表 |
405
+ | `GET` | `/api/v1/workflows/{id}` | 工作流详情 |
406
+ | `POST` | `/api/v1/runs` | 启动任务 |
407
+ | `GET` | `/api/v1/runs` | 任务列表 |
408
+ | `GET` | `/api/v1/runs/{id}` | 任务详情(含节点状态/DAG/日志) |
409
+ | `GET` | `/api/v1/runs/{id}/files` | 浏览工作目录文件 |
410
+ | `GET` | `/api/v1/runs/{id}/files/content?path=` | 读取文件内容 |
411
+ | `POST` | `/api/v1/runs/{id}/pause` | 暂停 |
412
+ | `POST` | `/api/v1/runs/{id}/resume` | 恢复 |
413
+ | `POST` | `/api/v1/runs/{id}/stop` | 停止 |
414
+ | `POST` | `/api/v1/runs/{id}/rerun` | 重新运行 |
415
+ | `DELETE` | `/api/v1/runs/{id}` | 删除 |
416
+ | `GET` | `/api/v1/runs/{id}/logs` | 查看日志 |
417
+ | `POST` | `/api/v1/runs/{id}/nodes/{nid}/review` | 提交人工审核 |
418
+ | `POST` | `/api/v1/cron` | 创建定时任务 |
419
+ | `GET` | `/api/v1/cron` | 定时任务列表 |
420
+ | `GET` | `/api/v1/cron/{id}` | 定时任务详情 |
421
+ | `POST` | `/api/v1/cron/{id}/toggle` | 启用/禁用 |
422
+ | `DELETE` | `/api/v1/cron/{id}` | 删除 |
423
+ | `POST` | `/api/v1/cron/{id}/trigger` | 手动触发 |
424
+
425
+ 访问 `http://localhost:8100/docs` 查看交互式 Swagger 文档。
426
+
427
+ ---
428
+
429
+ ## 架构
430
+
431
+ ```
432
+ wflow server start
433
+ └─ FastAPI
434
+ ├─ APScheduler → 定时触发 WorkflowRun
435
+ ├─ NodeHandler (ABC)
436
+ │ ├─ ClaudeHandler → ClaudeCLI subprocess (stream-json)
437
+ │ ├─ OpenCodeHandler → OpenCodeCLI subprocess (json)
438
+ │ ├─ ScriptHandler → ScriptRunner subprocess (stdin/stdout)
439
+ │ └─ HumanReviewHandler → 暂停等待审核
440
+ ├─ WorkflowExecutor → DAG 拓扑遍历 + 回路检测
441
+ └─ SQLite (aiosqlite) → 持久化
442
+ ```
443
+
444
+ ### 核心设计
445
+
446
+ | 概念 | 说明 |
447
+ |------|------|
448
+ | **NodeHandler 继承体系** | `NodeHandler` ABC → `ClaudeHandler` / `OpenCodeHandler` / `ScriptHandler` / `HumanReviewHandler`,新增类型只需子类化 |
449
+ | **Session 复用** | 每个 (run_id, node_id) 一个固定 session。回路重入同一节点时自动 Resume |
450
+ | **回路检测** | 基于无条件边构建 ancestor 关系,条件边仅当 target 是 source 的祖先时才触发 staleness |
451
+ | **流式日志** | Claude/OpenCode 使用 `stream-json` 输出,实时记录工具调用和状态 |
452
+ | **工作目录隔离** | 每个 run 创建 `workspace/<run_id[:8]>-<uuid>` 独立目录,自动拷贝项目的 `.claude`/`.opencode`/`.wflow` 配置 |
453
+ | **条件分支** | Edge `condition` 支持 `==`/`!=` 比较,模板变量引用上游输出 |
454
+ | **断点续跑** | 任务状态和 work_dir 持久化到 DB,支持重跑和恢复 |
455
+ | **人工审核透传** | `human_review` approved 时将上游节点真实产出传递到下游 |
456
+
457
+ ### 项目结构
458
+
459
+ ```
460
+ src/wflow/
461
+ ├── main.py # FastAPI 应用工厂 + scheduler 生命周期
462
+ ├── api/ # REST API (status, workflows, runs, cron)
463
+ ├── cli/ # Click CLI
464
+ ├── engine/ # 核心引擎
465
+ │ ├── executor.py # DAG 拓扑遍历 + 回路检测
466
+ │ ├── node_handler.py # NodeHandler ABC + 4 个处理器
467
+ │ ├── node_runner.py # 处理器派发
468
+ │ ├── scheduler.py # Cron 调度
469
+ │ ├── session_manager.py # Session 管理
470
+ │ ├── state_machine.py # 状态机
471
+ │ └── template.py # {{ }} 模板解析
472
+ ├── adapters/ # 外部适配器 (claude_cli, opencode_cli, script_runner)
473
+ ├── models/ # Pydantic + SQLAlchemy 模型
474
+ ├── services/ # 业务逻辑层
475
+ └── web/ # Alpine.js SPA
476
+ ```
477
+
478
+ ### 环境变量
479
+
480
+ | 变量 | 默认值 | 说明 |
481
+ |------|--------|------|
482
+ | `WFLOW_DB_URL` | `sqlite+aiosqlite:///./data/workflows.db` | 数据库路径 |
483
+ | `WFLOW_RUNS_DIR` | `./workspace` | 工作目录根路径 |
484
+ | `WFLOW_SERVER_URL` | `http://localhost:8100` | CLI 连接地址 |
485
+ | `WFLOW_PROJECT_DIR` | 当前目录 | 项目根目录(.claude/.opencode/.wflow 检测) |
486
+
487
+ ---
488
+
489
+ ## 运行测试
490
+
491
+ ```bash
492
+ pytest tests/ -v
493
+ pytest tests/test_engine/ -v
494
+ pytest tests/test_adapters/ -v
495
+ ```
@@ -0,0 +1,49 @@
1
+ cc_workflow-0.1.0.dist-info/licenses/LICENSE,sha256=LN3HRPbCb5UvanVlzrBfs8Jj6l2xH3E6KmWUMsfhz-Q,1063
2
+ wflow/__init__.py,sha256=8Vs19KYzudAPe8oO8v6U0_XleGMugfMicwUyGr2k6d8,246
3
+ wflow/logging.py,sha256=sQXBlNP3oBld-323NWoQ-IH5fwDPf0RGcqASY_wFas4,4816
4
+ wflow/main.py,sha256=R_0aOK8h9GYpo4pNhuta0aSZ9O52_9d27D8zr_4AxxM,4174
5
+ wflow/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
+ wflow/adapters/claude_cli.py,sha256=EdPNZ31Xx06W_42JVbvSbOBSxbewEKC0sdcePNfdzXg,10933
7
+ wflow/adapters/opencode_cli.py,sha256=33WvGCKYO0ZUuztHI8MrSEN_h2JF8e0ZUgLSs2wDITY,11585
8
+ wflow/adapters/script_runner.py,sha256=MBnyKxBEK3zEw5BBTZLjfY2pn_FgepYEV5JfV2S-PH0,3256
9
+ wflow/adapters/notifiers/__init__.py,sha256=iKRKzlf8NcDSAVKYl-inQIliGkb7GTcGFL6Kicqnfus,548
10
+ wflow/adapters/notifiers/base.py,sha256=VmKX3KeFKN_C-cq-DuudI9QIwkewW7MBMmD-UKliBO0,819
11
+ wflow/adapters/notifiers/registry.py,sha256=qfIIhCvHMvk8dhzOY-0oO8j6chcLgmAvFtQEv_f_zrU,1258
12
+ wflow/adapters/notifiers/welink.py,sha256=_4ty8o3grP5y0y1SEZpinxsourBJ6arrihle-ibexI8,1218
13
+ wflow/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ wflow/api/cron.py,sha256=XcLwEdX2P4QPQOEfrQUZKjG_I4mbMDlHz5xjzgbzqqE,5085
15
+ wflow/api/deps.py,sha256=MIaEMTW9TIC9ZrHQpz9dfZs1GArMA5zBFDA92lADX8Y,836
16
+ wflow/api/runs.py,sha256=g6YgPIzHwCiiEzMiFf8AFw5QKwGNdglFfkiXA_MyeSc,15386
17
+ wflow/api/status.py,sha256=4DAXefgijngqzTbYeP7kAowtd4pjOkMbyZ0OKC9R_O4,1840
18
+ wflow/api/workflows.py,sha256=M6ilOg0FQAZKgG5yYSslaLAfXWLgYUJ1iQCug7x7O28,2852
19
+ wflow/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ wflow/cli/main.py,sha256=Bl2tY04KPBN6FOupkgV-qlC3bRz9HXqftXlBQPOlCyo,11145
21
+ wflow/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ wflow/common/json_parser.py,sha256=p_VsMHzB843rjoKcHdynBhUmTfHVGxnPU2U1GhzPj98,1509
23
+ wflow/common/time_utils.py,sha256=g9KOOOngzoVTq2YuDDnu0jCMqCBlEMyDsy7f81YT5Bc,251
24
+ wflow/common/workspace.py,sha256=PCyduarJe6aLHCXlnDx01oNPZHAyry6UHUlSJVnaInE,1623
25
+ wflow/engine/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
+ wflow/engine/executor.py,sha256=G6maCBx2cOuZV3UWD54Jd7rnN8WSDTmeIPQpdTyyqkA,24617
27
+ wflow/engine/node_handler.py,sha256=2zKiL6sQdsTuOYCMInGsbSdIMDcCGWIcaMUijROkI-w,11929
28
+ wflow/engine/node_runner.py,sha256=1b7c8TbJlgLnsu8KPdFMiLHwI6BLU_YXPS3bEK9Mnv8,1453
29
+ wflow/engine/scheduler.py,sha256=YhyicYIMRFNdQyOQRP1zNLEywUHXZuUY2HKaPrOoxu4,6687
30
+ wflow/engine/session_manager.py,sha256=aqUGoqMbbsXmx4abERjTo83Ii_k936dnk7-cBshbPF8,4617
31
+ wflow/engine/state_machine.py,sha256=QUM3BucEOxlbDghEH3ZQKp1UICGLu6wFLviFmEBtnbI,1466
32
+ wflow/engine/template.py,sha256=pX6Y8tzQUNNTZletT8lQ83uUpjes9Y0edyHmtZYa4NE,2044
33
+ wflow/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
+ wflow/models/db.py,sha256=WlrB1ceXLLwxMdQAlqjWllVy71njl3rl7CMqFO7NVZw,3689
35
+ wflow/models/workflow.py,sha256=hxwWvnNl0-DUff-Vof6eumgUiz7Pvj17EwlDfuDNtVQ,2922
36
+ wflow/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
+ wflow/services/execution_svc.py,sha256=aZj7WtwFBO524B1ggUvojPgG4QgPIltyrvUoTBp5UFg,5064
38
+ wflow/services/run_launcher.py,sha256=ZCzFR1q2OB5EOpEe87U3phAjxLNtgTfqCPQiVZcuKc8,7653
39
+ wflow/services/schedule_svc.py,sha256=_Q6Bu1yWNwQyx8ZlcL9TVTuHtrPWFtu109gUvd2Fekc,1844
40
+ wflow/services/workflow_svc.py,sha256=CkiksS6zvX0S3VftSMvFTVNHbrhp94RrJkBKnKk8Gl0,2223
41
+ wflow/web/index.html,sha256=95Gjam6lfrVf-CRoZ2E8kdh7EitwnoMS7HI4pZXYBdo,16849
42
+ wflow/web/css/style.css,sha256=-cTJmuzdEjWca3QA8ig_Mv5pBGz8_k-0bJkG9sB1g6c,40729
43
+ wflow/web/js/app.js,sha256=rqqSbqCk1EOafIeN51IXIZUHgpkiw8vUZ8O-L6tkBhQ,38447
44
+ wflow/web/js/utils.js,sha256=yzbKiCK_975qttIGcsj0ZthkQD3lBVCjtLLrgLNJpAQ,926
45
+ cc_workflow-0.1.0.dist-info/METADATA,sha256=nDYzkKIhBt09UF5rB2e3eRBSy8eheQQbx7oWIBxLGyw,16625
46
+ cc_workflow-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
47
+ cc_workflow-0.1.0.dist-info/entry_points.txt,sha256=GK0maCZ0-y9LAqOJWgwWbFyA53A14u_6klo6AgqY3dI,45
48
+ cc_workflow-0.1.0.dist-info/top_level.txt,sha256=sB_pNHQwKnV36qY8-E8xjI4Gh2WL1b-i-UAvXU0YwRw,6
49
+ cc_workflow-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ wflow = wflow.cli.main:cli
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 MooYeh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ wflow
wflow/__init__.py ADDED
@@ -0,0 +1,8 @@
1
+ """
2
+ WFlow — AI workflow orchestrator built on Claude Code CLI / OpenCode CLI.
3
+
4
+ Define workflows as JSON DAGs with conditional branching, loop-back,
5
+ human review, session reuse, checkpoint resume, and cron scheduling.
6
+ """
7
+
8
+ __version__ = "0.1.0"
File without changes