claude-mcp-workflow 0.1.0
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.
- package/.claude-plugin/plugin.json +13 -0
- package/.mcp.json +9 -0
- package/LICENSE +21 -0
- package/README.md +260 -0
- package/build/dashboard.d.ts +4 -0
- package/build/dashboard.d.ts.map +1 -0
- package/build/dashboard.js +91 -0
- package/build/dashboard.js.map +1 -0
- package/build/engine.d.ts +55 -0
- package/build/engine.d.ts.map +1 -0
- package/build/engine.js +486 -0
- package/build/engine.js.map +1 -0
- package/build/index.d.ts +2 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +60 -0
- package/build/index.js.map +1 -0
- package/build/loader.d.ts +29 -0
- package/build/loader.d.ts.map +1 -0
- package/build/loader.js +166 -0
- package/build/loader.js.map +1 -0
- package/build/modifier.d.ts +42 -0
- package/build/modifier.d.ts.map +1 -0
- package/build/modifier.js +96 -0
- package/build/modifier.js.map +1 -0
- package/build/storage.d.ts +12 -0
- package/build/storage.d.ts.map +1 -0
- package/build/storage.js +62 -0
- package/build/storage.js.map +1 -0
- package/build/tools.d.ts +7 -0
- package/build/tools.d.ts.map +1 -0
- package/build/tools.js +316 -0
- package/build/tools.js.map +1 -0
- package/build/types.d.ts +417 -0
- package/build/types.d.ts.map +1 -0
- package/build/types.js +82 -0
- package/build/types.js.map +1 -0
- package/dashboard/dagre.min.js +801 -0
- package/dashboard/index.html +652 -0
- package/hooks/hooks.json +24 -0
- package/hooks/workflow-cleanup.sh +51 -0
- package/hooks/workflow-start.sh +79 -0
- package/package.json +44 -0
- package/templates/bug-fix.yaml +283 -0
- package/templates/code-review.yaml +164 -0
- package/templates/coding.yaml +176 -0
- package/templates/debugging.yaml +162 -0
- package/templates/explore.yaml +90 -0
- package/templates/file-code.yaml +69 -0
- package/templates/file-review.yaml +164 -0
- package/templates/investigate.yaml +84 -0
- package/templates/master.yaml +202 -0
- package/templates/new-feature.yaml +41 -0
- package/templates/planning.yaml +85 -0
- package/templates/refactoring.yaml +56 -0
- package/templates/reflection.yaml +61 -0
- package/templates/skills/architecture/SKILL.md +55 -0
- package/templates/skills/coding-skill-selector/SKILL.md +25 -0
- package/templates/skills/lang-haxe/SKILL.md +257 -0
- package/templates/skills/lang-python/SKILL.md +16 -0
- package/templates/skills/math/SKILL.md +14 -0
- package/templates/skills/preferences/SKILL.md +25 -0
- package/templates/skills/task-delegation/SKILL.md +53 -0
- package/templates/skills/web-reading/SKILL.md +62 -0
- package/templates/subagent.yaml +67 -0
- package/templates/testing.yaml +120 -0
- package/templates/web-research.yaml +53 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "workflow",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Structured workflow orchestration for AI agents via finite-state machines",
|
|
5
|
+
"author": {
|
|
6
|
+
"name": "AxGord",
|
|
7
|
+
"email": "axgord@gmail.com",
|
|
8
|
+
"url": "https://github.com/AxGord"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/AxGord/claude-workflow",
|
|
11
|
+
"repository": "https://github.com/AxGord/claude-workflow",
|
|
12
|
+
"license": "MIT"
|
|
13
|
+
}
|
package/.mcp.json
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 AxGord
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="docs/banner.png" alt="Claude Workflow" width="100%">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="package.json"><img src="https://img.shields.io/badge/version-1.0.0-blue" alt="Version"></a>
|
|
7
|
+
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="License"></a>
|
|
8
|
+
<a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-5.7-3178c6" alt="TypeScript"></a>
|
|
9
|
+
<a href="https://code.claude.com/docs/en/plugins"><img src="https://img.shields.io/badge/Claude_Code-Plugin-ff6600" alt="Claude Code Plugin"></a>
|
|
10
|
+
</p>
|
|
11
|
+
|
|
12
|
+
A Claude Code plugin that drives agents through YAML-defined state machines. The engine tracks state, enforces guards, manages nested sub-workflow stacks, and visualizes everything in a web dashboard.
|
|
13
|
+
|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
## Features
|
|
17
|
+
|
|
18
|
+
- **FSM-based state machines** — define workflows in YAML with states, transitions, and prompts
|
|
19
|
+
- **Stack-based sub-workflows** — states can push nested workflows (max depth 10), auto-pop on completion
|
|
20
|
+
- **Three-tier loading** — bundled templates < global (`~/.claude/workflows/`) < project (`.claude/workflows/`)
|
|
21
|
+
- **Snapshot isolation** — workflow definitions frozen at session start; hot-reloads don't affect running sessions
|
|
22
|
+
- **Runtime overlays** — modify workflows on the fly without touching YAML files
|
|
23
|
+
- **Web dashboard** — real-time session monitoring with DAG graph visualization
|
|
24
|
+
- **16 bundled workflows** — complete agent lifecycle from routing to reflection
|
|
25
|
+
- **8 bundled skills** — reusable knowledge modules auto-provisioned on first run
|
|
26
|
+
- **SessionStart hook** — auto-provisions missing skills and injects workflow context
|
|
27
|
+
|
|
28
|
+
## Quick Start
|
|
29
|
+
|
|
30
|
+
### From the Official Marketplace
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
/plugin install workflow@claude-plugin-directory
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### From GitHub
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# 1. Add the repository as a marketplace source
|
|
40
|
+
/plugin marketplace add AxGord/claude-workflow
|
|
41
|
+
|
|
42
|
+
# 2. Install the plugin
|
|
43
|
+
/plugin install workflow@AxGord-claude-workflow
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Manual (for development)
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
git clone https://github.com/AxGord/claude-workflow.git
|
|
50
|
+
cd claude-workflow
|
|
51
|
+
npm install
|
|
52
|
+
npm run build
|
|
53
|
+
claude --plugin-dir ./
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## How It Works
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
Agent Engine Storage
|
|
60
|
+
│ │ │
|
|
61
|
+
├── start() ───────────────►├─ snapshot workflows ─────────►├ session.json
|
|
62
|
+
│◄── initial state prompt ──┤ │
|
|
63
|
+
│ │ │
|
|
64
|
+
├── transition() ──────────►├─ validate & advance ─────────►├ update JSON
|
|
65
|
+
│◄── new state prompt ──────┤ (push/pop sub-workflows) │
|
|
66
|
+
│ │ │
|
|
67
|
+
├── transition() ──────────►├─ terminal state? ────────────►├ mark complete
|
|
68
|
+
│◄── done ──────────────────┤ (auto-pop to parent) │
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
1. `start()` — creates a session, snapshots all workflow definitions, returns the initial state prompt
|
|
72
|
+
2. `transition()` — validates the transition, advances state, handles sub-workflow push/pop, returns the new prompt
|
|
73
|
+
3. Every mutation is atomically persisted to JSON (temp file + rename + lockfile)
|
|
74
|
+
4. Dashboard visualizes sessions and workflow graphs at `localhost:3100`
|
|
75
|
+
|
|
76
|
+
## Workflow YAML
|
|
77
|
+
|
|
78
|
+
```yaml
|
|
79
|
+
name: my-workflow
|
|
80
|
+
description: "Example workflow"
|
|
81
|
+
initial: start
|
|
82
|
+
max_transitions: 50
|
|
83
|
+
|
|
84
|
+
states:
|
|
85
|
+
start:
|
|
86
|
+
prompt: "Analyze the task and decide on approach"
|
|
87
|
+
transitions:
|
|
88
|
+
implement: write_code
|
|
89
|
+
explore: research
|
|
90
|
+
|
|
91
|
+
research:
|
|
92
|
+
sub_workflow: explore # pushes nested workflow
|
|
93
|
+
on_complete: write_code # returns here on success
|
|
94
|
+
on_fail: start # returns here on failure
|
|
95
|
+
|
|
96
|
+
write_code:
|
|
97
|
+
prompt: "Write the implementation"
|
|
98
|
+
transitions:
|
|
99
|
+
done: finish
|
|
100
|
+
|
|
101
|
+
finish:
|
|
102
|
+
terminal: true
|
|
103
|
+
outcome: complete # or "fail"
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Three-Tier Loading
|
|
107
|
+
|
|
108
|
+
Workflows load from three sources in ascending priority — later tiers override earlier ones:
|
|
109
|
+
|
|
110
|
+
| Tier | Path | Purpose |
|
|
111
|
+
|------|------|---------|
|
|
112
|
+
| Bundled | `templates/` (plugin root) | Base workflows shipped with the plugin |
|
|
113
|
+
| Global | `~/.claude/workflows/` | User customizations shared across projects |
|
|
114
|
+
| Project | `.claude/workflows/` | Project-specific workflows |
|
|
115
|
+
|
|
116
|
+
A project workflow named `coding` overrides the bundled `coding` template. Same-name global workflows sit in between.
|
|
117
|
+
|
|
118
|
+
## Bundled Workflows
|
|
119
|
+
|
|
120
|
+
| Workflow | Description |
|
|
121
|
+
|----------|-------------|
|
|
122
|
+
| `master` | Single entry point — analyzes task, loads skills, routes to sub-workflows |
|
|
123
|
+
| `coding` | Code writing pipeline: think → delegate → write → review → verify |
|
|
124
|
+
| `bug-fix` | Standard bug fix: classify → diagnose → fix → verify |
|
|
125
|
+
| `new-feature` | New feature implementation with planning and testing |
|
|
126
|
+
| `refactoring` | Bring every touched file to current standards |
|
|
127
|
+
| `debugging` | Diagnose first, fix never (until diagnosed) |
|
|
128
|
+
| `code-review` | Code review with per-file deep analysis |
|
|
129
|
+
| `explore` | Codebase exploration — understand structure, trace code, find patterns |
|
|
130
|
+
| `investigate` | Resolve unknowns before deciding on action |
|
|
131
|
+
| `planning` | Explore, design plan, record workflow context |
|
|
132
|
+
| `testing` | Testing verification — unit tests first, then integration |
|
|
133
|
+
| `web-research` | Check existing knowledge, then delegate to web subagents |
|
|
134
|
+
| `reflection` | Self-reflection after significant tasks — evaluate, classify, act |
|
|
135
|
+
| `subagent` | Lightweight routing for sub-agents (no chat/plan/reflect) |
|
|
136
|
+
| `file-code` | Per-file coding — spawned by coding/bug-fix for each file |
|
|
137
|
+
| `file-review` | Per-file deep review — spawned by code-review for each file |
|
|
138
|
+
|
|
139
|
+

|
|
140
|
+
|
|
141
|
+
## Bundled Skills
|
|
142
|
+
|
|
143
|
+
Skills are reusable knowledge modules loaded by workflows via `Skill()`. Auto-provisioned to `~/.claude/skills/` on first run if missing.
|
|
144
|
+
|
|
145
|
+
| Skill | Description |
|
|
146
|
+
|-------|-------------|
|
|
147
|
+
| `preferences` | User's general coding preferences |
|
|
148
|
+
| `architecture` | Simplicity-first architecture decisions |
|
|
149
|
+
| `task-delegation` | When and how to delegate to subagents |
|
|
150
|
+
| `coding-skill-selector` | Select and load coding skills by file extensions and domains |
|
|
151
|
+
| `lang-haxe` | Haxe language gotchas |
|
|
152
|
+
| `lang-python` | Python language gotchas |
|
|
153
|
+
| `math` | Math overflow boundary gotchas |
|
|
154
|
+
| `web-reading` | Fetch web content via subagents |
|
|
155
|
+
|
|
156
|
+
## MCP Tools
|
|
157
|
+
|
|
158
|
+
All tools are registered under the `wf` server. Full tool prefix: `mcp__plugin_workflow_wf__`.
|
|
159
|
+
|
|
160
|
+
| Tool | Description | Key Parameters |
|
|
161
|
+
|------|-------------|----------------|
|
|
162
|
+
| `list` | List all available workflow definitions | — |
|
|
163
|
+
| `start` | Start a workflow, return initial prompt | `workflow`, `actor`, `parent_session_id` |
|
|
164
|
+
| `status` | Get current state, stack, transitions, history | `session_id` |
|
|
165
|
+
| `transition` | Advance to next state (auto push/pop sub-workflows) | `session_id`, `transition` |
|
|
166
|
+
| `context_set` | Save key-value data in session context | `session_id`, `key`, `value` |
|
|
167
|
+
| `modify` | Runtime overlay — add/change/remove states and transitions | `session_id`, `add_state`, `add_transition` |
|
|
168
|
+
| `create` | Create new workflow definition (saves YAML) | `name`, `definition`, `scope` |
|
|
169
|
+
| `delete` | Delete a workflow definition | `name`, `scope` |
|
|
170
|
+
| `abort` | Abort workflow, pop all stack frames | `session_id` |
|
|
171
|
+
| `sessions` | List all sessions (active first) | — |
|
|
172
|
+
|
|
173
|
+
## Dashboard
|
|
174
|
+
|
|
175
|
+
The web dashboard runs on `localhost:3100` and provides real-time monitoring:
|
|
176
|
+
|
|
177
|
+
- **Sessions panel** — active, completed, and abandoned sessions with status badges
|
|
178
|
+
- **Workflow list** — all loaded workflows with state counts
|
|
179
|
+
- **Session detail** — full state history, stack depth, context data
|
|
180
|
+
- **Workflow graphs** — interactive DAG visualization rendered with dagre
|
|
181
|
+
|
|
182
|
+
### REST API
|
|
183
|
+
|
|
184
|
+
| Method | Endpoint | Description |
|
|
185
|
+
|--------|----------|-------------|
|
|
186
|
+
| `GET` | `/api/sessions` | List all sessions |
|
|
187
|
+
| `GET` | `/api/session/:id` | Get session detail |
|
|
188
|
+
| `POST` | `/api/session/:id/abandon` | Abandon a session |
|
|
189
|
+
| `GET` | `/api/workflows` | List all workflow definitions |
|
|
190
|
+
|
|
191
|
+
## Configuration
|
|
192
|
+
|
|
193
|
+
| Variable | Default | Purpose |
|
|
194
|
+
|----------|---------|---------|
|
|
195
|
+
| `WORKFLOW_DIR` | `~/.claude/workflows/` | Global workflow YAML directory |
|
|
196
|
+
| `STATE_DIR` | `~/.claude/workflow-state/` | Session JSON persistence |
|
|
197
|
+
| `DASHBOARD_PORT` | `3100` | Web dashboard HTTP port |
|
|
198
|
+
|
|
199
|
+
## Status Line
|
|
200
|
+
|
|
201
|
+
Show the active workflow and state in Claude Code's status bar:
|
|
202
|
+
|
|
203
|
+

|
|
204
|
+
|
|
205
|
+
Add this snippet to your statusline script:
|
|
206
|
+
|
|
207
|
+
```sh
|
|
208
|
+
# Workflow status — add to your ~/.claude/statusline-command.sh
|
|
209
|
+
wf_state_dir="$HOME/.claude/workflow-state"
|
|
210
|
+
if [ -d "$wf_state_dir" ]; then
|
|
211
|
+
for f in "$wf_state_dir"/*.json; do
|
|
212
|
+
[ -f "$f" ] || continue
|
|
213
|
+
slen=$(jq -r '.stack | length' "$f" 2>/dev/null)
|
|
214
|
+
if [ "$slen" -gt 0 ]; then
|
|
215
|
+
cpid=$(jq -r '.context.claude_code_pid // 0' "$f" 2>/dev/null)
|
|
216
|
+
[ "$cpid" != "$PPID" ] && continue
|
|
217
|
+
wf=$(jq -r '.stack[.active_frame].workflow // ""' "$f" 2>/dev/null)
|
|
218
|
+
st=$(jq -r '.stack[.active_frame].current_state // ""' "$f" 2>/dev/null)
|
|
219
|
+
printf "\033[96m\xE2\x9A\x99 %s:%s\033[0m" "$wf" "$st"
|
|
220
|
+
break
|
|
221
|
+
fi
|
|
222
|
+
done
|
|
223
|
+
fi
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Then in `~/.claude/settings.json`:
|
|
227
|
+
|
|
228
|
+
```json
|
|
229
|
+
{
|
|
230
|
+
"statusLine": {
|
|
231
|
+
"type": "command",
|
|
232
|
+
"command": "bash ~/.claude/statusline-command.sh"
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## Development
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
npm run build # tsc → compiles src/ to build/
|
|
241
|
+
npm run dev # tsc --watch
|
|
242
|
+
npm start # node build/index.js
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### Architecture
|
|
246
|
+
|
|
247
|
+
| File | Responsibility |
|
|
248
|
+
|------|---------------|
|
|
249
|
+
| `src/index.ts` | Entry point — resolves dirs, wires components, starts stdio transport |
|
|
250
|
+
| `src/engine.ts` | FSM core — start, transition, abort, context, stack push/pop |
|
|
251
|
+
| `src/loader.ts` | YAML loading + Zod validation + fs.watch hot-reload |
|
|
252
|
+
| `src/storage.ts` | JSON persistence with atomic writes and lockfile mutex |
|
|
253
|
+
| `src/modifier.ts` | Runtime overlays + create (YAML writer) |
|
|
254
|
+
| `src/tools.ts` | MCP tool registrations + response formatting |
|
|
255
|
+
| `src/dashboard.ts` | Express REST API + static file serving |
|
|
256
|
+
| `src/types.ts` | Zod schemas, TypeScript types, constants |
|
|
257
|
+
|
|
258
|
+
## License
|
|
259
|
+
|
|
260
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard.d.ts","sourceRoot":"","sources":["../src/dashboard.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAiG1C,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAGpF"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import express from "express";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
4
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
5
|
+
function buildApp(storage, loader) {
|
|
6
|
+
const app = express();
|
|
7
|
+
app.use(express.json());
|
|
8
|
+
// API endpoints
|
|
9
|
+
app.get("/api/sessions", (_req, res) => {
|
|
10
|
+
const sessions = storage.readAll();
|
|
11
|
+
res.json(sessions);
|
|
12
|
+
});
|
|
13
|
+
app.get("/api/session/:id", (req, res) => {
|
|
14
|
+
const session = storage.read(req.params.id);
|
|
15
|
+
if (!session) {
|
|
16
|
+
res.status(404).json({ error: "Session not found" });
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
res.json(session);
|
|
20
|
+
});
|
|
21
|
+
app.get("/api/workflows", (_req, res) => {
|
|
22
|
+
const workflows = loader.getAll();
|
|
23
|
+
const result = {};
|
|
24
|
+
for (const [name, wf] of workflows) {
|
|
25
|
+
result[name] = {
|
|
26
|
+
name: wf.name,
|
|
27
|
+
description: wf.description,
|
|
28
|
+
initial: wf.initial,
|
|
29
|
+
max_transitions: wf.max_transitions,
|
|
30
|
+
states: wf.states,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
res.json(result);
|
|
34
|
+
});
|
|
35
|
+
// Abandon a session via REST (used by SessionEnd hook)
|
|
36
|
+
app.post("/api/session/:id/abandon", async (req, res) => {
|
|
37
|
+
try {
|
|
38
|
+
const session = storage.read(req.params.id);
|
|
39
|
+
if (!session) {
|
|
40
|
+
res.status(404).json({ error: "Session not found" });
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
// Idempotent: already inactive — return current outcome
|
|
44
|
+
if (session.stack.length === 0) {
|
|
45
|
+
res.json({ session_id: session.session_id, outcome: session.outcome ?? "completed" });
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const now = new Date().toISOString();
|
|
49
|
+
const updated = {
|
|
50
|
+
...session,
|
|
51
|
+
stack: [],
|
|
52
|
+
active_frame: -1,
|
|
53
|
+
updated_at: now,
|
|
54
|
+
history: [...session.history, { frame: session.active_frame, event: "abandon", at: now }],
|
|
55
|
+
outcome: "abandoned",
|
|
56
|
+
};
|
|
57
|
+
await storage.write(session.session_id, updated);
|
|
58
|
+
res.json({ session_id: session.session_id, outcome: "abandoned" });
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
res.status(500).json({ error: err.message });
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
// Serve dashboard HTML
|
|
65
|
+
const dashboardDir = path.resolve(__dirname, "..", "dashboard");
|
|
66
|
+
app.use(express.static(dashboardDir));
|
|
67
|
+
app.get("/", (_req, res) => {
|
|
68
|
+
res.sendFile(path.join(dashboardDir, "index.html"));
|
|
69
|
+
});
|
|
70
|
+
return app;
|
|
71
|
+
}
|
|
72
|
+
function tryListen(app, port) {
|
|
73
|
+
const server = app.listen(port);
|
|
74
|
+
server.on("listening", () => {
|
|
75
|
+
console.error(`Dashboard running at http://localhost:${port}`);
|
|
76
|
+
});
|
|
77
|
+
server.on("error", (err) => {
|
|
78
|
+
if (err.code === "EADDRINUSE") {
|
|
79
|
+
console.error(`Dashboard port ${port} in use — retrying in 20s`);
|
|
80
|
+
setTimeout(() => tryListen(app, port), 20_000);
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
console.error(`Dashboard error: ${err.message}`);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
export function createDashboard(storage, loader, port) {
|
|
88
|
+
const app = buildApp(storage, loader);
|
|
89
|
+
tryListen(app, port);
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=dashboard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dashboard.js","sourceRoot":"","sources":["../src/dashboard.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { StackFrame, HistoryEntry, StateDefinition } from "./types.js";
|
|
2
|
+
import type { Storage } from "./storage.js";
|
|
3
|
+
import type { Loader } from "./loader.js";
|
|
4
|
+
export interface TransitionResult {
|
|
5
|
+
readonly prompt: string;
|
|
6
|
+
readonly warnings: string[];
|
|
7
|
+
readonly autoTransitions: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface TaskOp {
|
|
10
|
+
readonly action: "create" | "complete";
|
|
11
|
+
readonly subject: string;
|
|
12
|
+
}
|
|
13
|
+
export interface StatusResult {
|
|
14
|
+
readonly sessionId: string;
|
|
15
|
+
readonly stack: StackFrame[];
|
|
16
|
+
readonly activeFrame: number;
|
|
17
|
+
readonly currentState: StateDefinition;
|
|
18
|
+
readonly currentStateName: string;
|
|
19
|
+
readonly currentWorkflow: string;
|
|
20
|
+
readonly availableTransitions: Record<string, string>;
|
|
21
|
+
readonly prompt: string;
|
|
22
|
+
readonly history: HistoryEntry[];
|
|
23
|
+
readonly context: Record<string, unknown>;
|
|
24
|
+
readonly taskOps: TaskOp[];
|
|
25
|
+
readonly visitCount: number;
|
|
26
|
+
}
|
|
27
|
+
export declare class Engine {
|
|
28
|
+
private readonly _storage;
|
|
29
|
+
private readonly _loader;
|
|
30
|
+
private readonly _snapshots;
|
|
31
|
+
constructor(storage: Storage, loader: Loader);
|
|
32
|
+
/** Find the most recently updated active session for the current Claude Code PID. */
|
|
33
|
+
resolveSessionId(sessionId?: string): string;
|
|
34
|
+
start(workflowName: string, actor?: string, parentSessionId?: string): Promise<StatusResult>;
|
|
35
|
+
transition(sessionId: string, transitionName: string, actor?: string): Promise<StatusResult>;
|
|
36
|
+
abort(sessionId: string): Promise<void>;
|
|
37
|
+
getStatus(sessionId: string): StatusResult;
|
|
38
|
+
/**
|
|
39
|
+
* Retry a deferred pop. Called by Modifier after overlays change,
|
|
40
|
+
* in case on_complete/on_fail was added to the parent state.
|
|
41
|
+
* Returns the new status if pop succeeded, or null if still pending.
|
|
42
|
+
*/
|
|
43
|
+
retryPendingPop(sessionId: string): Promise<StatusResult | null>;
|
|
44
|
+
setContext(sessionId: string, key: string, value: unknown, actor?: string): Promise<void>;
|
|
45
|
+
private _pushSubWorkflow;
|
|
46
|
+
private _popStack;
|
|
47
|
+
private _formatChildrenBlockError;
|
|
48
|
+
private _getActiveChildren;
|
|
49
|
+
private _cascadeAbandonChildren;
|
|
50
|
+
private _getWorkflow;
|
|
51
|
+
private _resolveState;
|
|
52
|
+
private _applyTransitionOverrides;
|
|
53
|
+
private _buildStatus;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=engine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../src/engine.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAEV,UAAU,EACV,YAAY,EAEZ,eAAe,EAEhB,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAE1C,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC;IAC5B,QAAQ,CAAC,eAAe,EAAE,MAAM,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,MAAM;IACrB,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,UAAU,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,UAAU,EAAE,CAAC;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,YAAY,EAAE,eAAe,CAAC;IACvC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,oBAAoB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC1C,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,qBAAa,MAAM;IACjB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAU;IACnC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IAEjC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA2D;gBAE1E,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM;IAK5C,qFAAqF;IAC9E,gBAAgB,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,MAAM;IAWtC,KAAK,CAAC,YAAY,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IA0D5F,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IA8G5F,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsB7C,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,YAAY;IAMjD;;;;OAIG;IACU,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAsBhE,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAexF,gBAAgB;YAuChB,SAAS;IAiHvB,OAAO,CAAC,yBAAyB;IAYjC,OAAO,CAAC,kBAAkB;YAMZ,uBAAuB;IAkBrC,OAAO,CAAC,YAAY;IAQpB,OAAO,CAAC,aAAa;IA6BrB,OAAO,CAAC,yBAAyB;IAyBjC,OAAO,CAAC,YAAY;CA8CrB"}
|