smithers-orchestrator 0.2.4 → 0.2.6
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/README.md +220 -218
- package/dist/bin/cli.js +30 -0
- package/dist/src/components/index.js +75 -72
- package/dist/src/core/index.js +50 -8
- package/dist/src/db/index.js +30 -0
- package/dist/src/db/schema.sql +586 -0
- package/dist/src/index.js +160 -81
- package/dist/src/reconciler/index.js +55 -9
- package/package.json +4 -2
- package/preload.ts +9 -0
package/README.md
CHANGED
|
@@ -1,92 +1,95 @@
|
|
|
1
1
|
# Smithers
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/smithers)
|
|
3
|
+
[](https://www.npmjs.com/package/smithers-orchestrator)
|
|
4
4
|
[](https://opensource.org/licenses/MIT)
|
|
5
5
|
[](https://www.typescriptlang.org/)
|
|
6
6
|
[](https://bun.sh/)
|
|
7
7
|
|
|
8
|
-
**
|
|
8
|
+
**Let your agent write agents.**
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
React-style orchestration your coding agent can generate, then run safely as durable Ralph loops.
|
|
11
11
|
|
|
12
12
|
<!-- TODO: Add GIF demo -->
|
|
13
13
|
|
|
14
14
|

|
|
15
15
|
|
|
16
|
+
```
|
|
17
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
18
|
+
│ React tree ──▶ Smithers executor ──▶ Tools + Claude ──▶ SQLite DB │
|
|
19
|
+
│ │
|
|
20
|
+
│ "React syntax, non-UI renderer" │
|
|
21
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- **Agent-native syntax** - Easy for Claude Code to generate, easy for humans to review
|
|
25
|
+
- **Sophisticated loops** - Multi-phase, parallel agents, conditional branches
|
|
26
|
+
- **Composable** - Build complex workflows from simple React components
|
|
27
|
+
|
|
16
28
|
---
|
|
17
29
|
|
|
18
30
|
## Table of Contents
|
|
19
31
|
|
|
20
|
-
- [Why](#why)
|
|
32
|
+
- [Why Smithers](#why-smithers)
|
|
21
33
|
- [Getting Started](#getting-started)
|
|
22
|
-
- [
|
|
23
|
-
- [Recipes](#recipes)
|
|
34
|
+
- [Starter Workflows](#starter-workflows)
|
|
24
35
|
- [Features](#features)
|
|
25
36
|
- [Claude Component](#claude-component)
|
|
26
|
-
- [Ralph
|
|
37
|
+
- [Sophisticated Ralph Loops](#sophisticated-ralph-loops)
|
|
27
38
|
- [Structured Output with Zod](#structured-output-with-zod)
|
|
28
39
|
- [MCP Tool Integration](#mcp-tool-integration)
|
|
29
40
|
- [Smithers Subagent](#smithers-subagent)
|
|
30
41
|
- [Git/JJ VCS Integration](#gitjj-vcs-integration)
|
|
31
|
-
- [Orchestration Lifecycle](#orchestration-lifecycle)
|
|
32
42
|
- [PhaseRegistry & Step](#phaseregistry--step)
|
|
33
43
|
- [Parallel Execution](#parallel-execution)
|
|
34
|
-
- [Database
|
|
35
|
-
|
|
44
|
+
- [Database Persistence](#database-persistence)
|
|
45
|
+
- [FAQ](#faq)
|
|
36
46
|
- [Contributing](#contributing)
|
|
37
47
|
|
|
38
48
|
---
|
|
39
49
|
|
|
40
|
-
## Why
|
|
50
|
+
## Why Smithers
|
|
41
51
|
|
|
42
|
-
|
|
52
|
+
### The Problem
|
|
43
53
|
|
|
44
|
-
|
|
45
|
-
-
|
|
46
|
-
-
|
|
47
|
-
-
|
|
48
|
-
-
|
|
49
|
-
- **Use reactive primitives** - React state means my workflows respond to state changes automatically
|
|
50
|
-
- **Compose complex behaviors from simple components** - loops, phases, steps, and validation all snap together
|
|
51
|
-
- **Keep everything in version control** - workflows are just TypeScript files
|
|
54
|
+
Simple Ralph loops work great for basic iteration. But as workflows grow complex:
|
|
55
|
+
- Multi-phase orchestration becomes hard to manage
|
|
56
|
+
- Parallel agents need coordination
|
|
57
|
+
- Plans live in prompts, not reviewable code
|
|
58
|
+
- Manual orchestration doesn't scale
|
|
52
59
|
|
|
53
|
-
|
|
60
|
+
### The Solution
|
|
54
61
|
|
|
55
|
-
|
|
62
|
+
Smithers uses React's component model + markup-like syntax to define execution plans. This isn't UI - it renders to **execution**.
|
|
56
63
|
|
|
57
|
-
|
|
64
|
+
**One syntax both humans and agents can work with:**
|
|
65
|
+
- You can read and review it
|
|
66
|
+
- Claude Code can generate it reliably
|
|
67
|
+
- Git can version it
|
|
58
68
|
|
|
59
|
-
|
|
60
|
-
-
|
|
69
|
+
**Sophisticated Ralph loops that stay reliable:**
|
|
70
|
+
- Multi-phase workflows with parallel agents
|
|
71
|
+
- Conditional branches, phases, steps
|
|
72
|
+
- Composable components you can reuse
|
|
73
|
+
- Persist state and audit history when you need it
|
|
61
74
|
|
|
62
|
-
|
|
63
|
-
- **[jj (Jujutsu)](https://github.com/martinvonz/jj)** - Alternative VCS with better snapshot support
|
|
64
|
-
- **[Codex CLI](https://github.com/openai/codex)** - Used for post-commit code reviews
|
|
75
|
+
---
|
|
65
76
|
|
|
66
|
-
|
|
77
|
+
## Getting Started
|
|
67
78
|
|
|
68
|
-
|
|
79
|
+
### Prerequisites
|
|
69
80
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
"projects": {
|
|
73
|
-
"/path/to/your/project": {
|
|
74
|
-
"mcpServers": {},
|
|
75
|
-
"allowedTools": ["smithers-orchestrator:*"]
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
```
|
|
81
|
+
- **[Bun](https://bun.sh/)** v1.0+ (JavaScript runtime)
|
|
82
|
+
- **[Claude Code](https://www.npmjs.com/package/@anthropic-ai/claude-code)** - `bun install -g @anthropic-ai/claude-code`
|
|
80
83
|
|
|
81
|
-
|
|
84
|
+
### Install
|
|
82
85
|
|
|
83
86
|
```bash
|
|
84
|
-
bun add
|
|
87
|
+
bun add smithers-orchestrator
|
|
85
88
|
```
|
|
86
89
|
|
|
87
|
-
###
|
|
90
|
+
### Let Claude Write It
|
|
88
91
|
|
|
89
|
-
**You don't have to write Smithers yourself.**
|
|
92
|
+
**You don't have to write Smithers yourself.** Describe what you want:
|
|
90
93
|
|
|
91
94
|
```
|
|
92
95
|
User: "Create a workflow that monitors my CI, fixes failures automatically,
|
|
@@ -95,191 +98,157 @@ User: "Create a workflow that monitors my CI, fixes failures automatically,
|
|
|
95
98
|
Claude: *generates ci-recovery.tsx*
|
|
96
99
|
```
|
|
97
100
|
|
|
98
|
-
|
|
101
|
+
### Run It
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
bun my-workflow.tsx
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Inspect History
|
|
108
|
+
|
|
109
|
+
```bash
|
|
110
|
+
smithers db executions # View execution history
|
|
111
|
+
smithers db state --execution-id abc123 # Inspect specific run
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
---
|
|
115
|
+
|
|
116
|
+
## Starter Workflows
|
|
99
117
|
|
|
100
|
-
### Run
|
|
118
|
+
### 1. Night Shift: Run Until Tests Pass
|
|
119
|
+
|
|
120
|
+
Goal: Keep iterating until all tests pass, with incremental commits.
|
|
101
121
|
|
|
102
122
|
```tsx
|
|
103
123
|
#!/usr/bin/env bun
|
|
124
|
+
import { createSmithersRoot, createSmithersDB, SmithersProvider, Claude } from "smithers-orchestrator";
|
|
104
125
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
import { SmithersProvider } from "smithers-orchestrator/components/SmithersProvider";
|
|
108
|
-
import { Claude } from "smithers-orchestrator/components/Claude";
|
|
109
|
-
|
|
110
|
-
const db = await createSmithersDB({ path: ".smithers/my-task" });
|
|
111
|
-
const executionId = await db.execution.start("My Task", "scripts/my-task.tsx");
|
|
126
|
+
const db = await createSmithersDB({ path: ".smithers/night-shift" });
|
|
127
|
+
const executionId = await db.execution.start("Night Shift", "night-shift.tsx");
|
|
112
128
|
|
|
113
|
-
|
|
129
|
+
function NightShift() {
|
|
114
130
|
return (
|
|
115
|
-
<SmithersProvider db={db} executionId={executionId}>
|
|
131
|
+
<SmithersProvider db={db} executionId={executionId} maxIterations={50}>
|
|
116
132
|
<Claude
|
|
117
133
|
model="sonnet"
|
|
118
|
-
|
|
119
|
-
|
|
134
|
+
onFinished={(result) => {
|
|
135
|
+
if (result.output.includes("All tests pass")) {
|
|
136
|
+
db.state.set("complete", "true");
|
|
137
|
+
}
|
|
138
|
+
}}
|
|
120
139
|
>
|
|
121
|
-
|
|
140
|
+
Run tests. If any fail, fix them and commit the fix. Repeat until all tests pass.
|
|
122
141
|
</Claude>
|
|
123
142
|
</SmithersProvider>
|
|
124
143
|
);
|
|
125
144
|
}
|
|
126
145
|
|
|
127
146
|
const root = createSmithersRoot();
|
|
128
|
-
await root.mount(
|
|
147
|
+
await root.mount(NightShift);
|
|
129
148
|
await db.close();
|
|
130
149
|
```
|
|
131
150
|
|
|
132
151
|
```bash
|
|
133
|
-
bun
|
|
152
|
+
bun night-shift.tsx
|
|
134
153
|
```
|
|
135
154
|
|
|
136
|
-
###
|
|
155
|
+
### 2. PRD to Implementation
|
|
137
156
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
```bash
|
|
141
|
-
smithers db executions # View execution history
|
|
142
|
-
smithers db state --execution-id abc123 # View specific execution state
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
---
|
|
146
|
-
|
|
147
|
-
## AI SDK React Hooks
|
|
148
|
-
|
|
149
|
-
Smithers re-exports the Vercel AI SDK React hooks so you can import everything
|
|
150
|
-
from a single package:
|
|
157
|
+
Goal: Plan, implement, test, produce PR summary.
|
|
151
158
|
|
|
152
159
|
```tsx
|
|
153
|
-
|
|
160
|
+
#!/usr/bin/env bun
|
|
161
|
+
import { createSmithersRoot, createSmithersDB, SmithersProvider, Phase, Step, Claude } from "smithers-orchestrator";
|
|
154
162
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const { db } = useSmithers();
|
|
163
|
+
const db = await createSmithersDB({ path: ".smithers/prd-impl" });
|
|
164
|
+
const executionId = await db.execution.start("PRD Implementation", "prd-impl.tsx");
|
|
158
165
|
|
|
166
|
+
function PRDToImplementation() {
|
|
159
167
|
return (
|
|
160
|
-
<
|
|
161
|
-
<
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
</
|
|
168
|
-
|
|
168
|
+
<SmithersProvider db={db} executionId={executionId} maxIterations={20}>
|
|
169
|
+
<Phase name="Plan">
|
|
170
|
+
<Step name="analyze-prd">
|
|
171
|
+
<Claude model="sonnet">
|
|
172
|
+
Read PRD.md. Create implementation plan with acceptance criteria.
|
|
173
|
+
</Claude>
|
|
174
|
+
</Step>
|
|
175
|
+
</Phase>
|
|
176
|
+
|
|
177
|
+
<Phase name="Implement">
|
|
178
|
+
<Step name="write-code">
|
|
179
|
+
<Claude model="sonnet">
|
|
180
|
+
Implement the plan. Commit after each logical unit of work.
|
|
181
|
+
</Claude>
|
|
182
|
+
</Step>
|
|
183
|
+
<Step name="write-tests">
|
|
184
|
+
<Claude model="sonnet">
|
|
185
|
+
Write tests for the implementation. Ensure all pass.
|
|
186
|
+
</Claude>
|
|
187
|
+
</Step>
|
|
188
|
+
</Phase>
|
|
189
|
+
|
|
190
|
+
<Phase name="Summary">
|
|
191
|
+
<Step name="pr-summary">
|
|
192
|
+
<Claude model="sonnet">
|
|
193
|
+
Generate PR summary with what changed and why.
|
|
194
|
+
</Claude>
|
|
195
|
+
</Step>
|
|
196
|
+
</Phase>
|
|
197
|
+
</SmithersProvider>
|
|
169
198
|
);
|
|
170
199
|
}
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
You can also import directly from the hooks subpath:
|
|
174
200
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
201
|
+
const root = createSmithersRoot();
|
|
202
|
+
await root.mount(PRDToImplementation);
|
|
203
|
+
await db.close();
|
|
178
204
|
```
|
|
179
205
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
## Recipes
|
|
206
|
+
### 3. Refactor with Checkpoints
|
|
183
207
|
|
|
184
|
-
|
|
208
|
+
Goal: Staged refactoring with checkpoints and rollback capability.
|
|
185
209
|
|
|
186
210
|
```tsx
|
|
187
|
-
|
|
188
|
-
|
|
211
|
+
#!/usr/bin/env bun
|
|
212
|
+
import { createSmithersRoot, createSmithersDB, SmithersProvider, Phase, Step, Claude, Worktree } from "smithers-orchestrator";
|
|
213
|
+
|
|
214
|
+
const db = await createSmithersDB({ path: ".smithers/refactor" });
|
|
215
|
+
const executionId = await db.execution.start("Refactor", "refactor.tsx");
|
|
189
216
|
|
|
217
|
+
function RefactorWorkflow() {
|
|
190
218
|
return (
|
|
191
|
-
<SmithersProvider db={db} executionId={executionId} maxIterations={
|
|
192
|
-
<
|
|
193
|
-
|
|
194
|
-
<
|
|
195
|
-
<Claude
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
219
|
+
<SmithersProvider db={db} executionId={executionId} maxIterations={30}>
|
|
220
|
+
<Worktree branch="smithers/refactor" cleanup>
|
|
221
|
+
<Phase name="Analyze">
|
|
222
|
+
<Step name="identify-targets">
|
|
223
|
+
<Claude model="sonnet">
|
|
224
|
+
Identify code that needs refactoring. Create a prioritized list.
|
|
225
|
+
</Claude>
|
|
226
|
+
</Step>
|
|
227
|
+
</Phase>
|
|
228
|
+
|
|
229
|
+
<Phase name="Refactor">
|
|
230
|
+
<Step name="refactor-code" snapshotBefore commitAfter>
|
|
231
|
+
<Claude model="sonnet">
|
|
232
|
+
Refactor each item. Run tests after each change. Commit if green.
|
|
233
|
+
</Claude>
|
|
234
|
+
</Step>
|
|
235
|
+
</Phase>
|
|
236
|
+
|
|
237
|
+
<Phase name="Verify">
|
|
238
|
+
<Step name="final-check">
|
|
239
|
+
<Claude model="sonnet">
|
|
240
|
+
Run full test suite. Document all changes made.
|
|
200
241
|
</Claude>
|
|
201
|
-
</
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
{phase === "review" && (
|
|
205
|
-
<Phase name="Code Review">
|
|
206
|
-
<Review
|
|
207
|
-
target={{ type: "diff", ref: "main" }}
|
|
208
|
-
criteria={[
|
|
209
|
-
"No security vulnerabilities",
|
|
210
|
-
"Tests cover edge cases",
|
|
211
|
-
"Types are properly defined",
|
|
212
|
-
]}
|
|
213
|
-
onFinished={(review) => {
|
|
214
|
-
if (review.approved) {
|
|
215
|
-
db.state.set("phase", "complete");
|
|
216
|
-
} else {
|
|
217
|
-
db.state.set("phase", "implement");
|
|
218
|
-
}
|
|
219
|
-
}}
|
|
220
|
-
/>
|
|
221
|
-
</Phase>
|
|
222
|
-
)}
|
|
223
|
-
</Orchestration>
|
|
242
|
+
</Step>
|
|
243
|
+
</Phase>
|
|
244
|
+
</Worktree>
|
|
224
245
|
</SmithersProvider>
|
|
225
246
|
);
|
|
226
247
|
}
|
|
227
|
-
```
|
|
228
|
-
|
|
229
|
-
### Structured Output with Validation
|
|
230
|
-
|
|
231
|
-
```tsx
|
|
232
|
-
import { z } from 'zod'
|
|
233
|
-
|
|
234
|
-
const AnalysisSchema = z.object({
|
|
235
|
-
summary: z.string(),
|
|
236
|
-
issues: z.array(z.object({
|
|
237
|
-
severity: z.enum(['low', 'medium', 'high', 'critical']),
|
|
238
|
-
file: z.string(),
|
|
239
|
-
description: z.string(),
|
|
240
|
-
})),
|
|
241
|
-
recommendations: z.array(z.string()),
|
|
242
|
-
})
|
|
243
|
-
|
|
244
|
-
<Claude
|
|
245
|
-
model="sonnet"
|
|
246
|
-
schema={AnalysisSchema}
|
|
247
|
-
schemaRetries={2}
|
|
248
|
-
onFinished={(result) => {
|
|
249
|
-
// result.structured is typed!
|
|
250
|
-
for (const issue of result.structured.issues) {
|
|
251
|
-
console.log(`[${issue.severity}] ${issue.file}: ${issue.description}`)
|
|
252
|
-
}
|
|
253
|
-
}}
|
|
254
|
-
>
|
|
255
|
-
Analyze this codebase for security issues.
|
|
256
|
-
</Claude>
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
### Database Access with MCP
|
|
260
|
-
|
|
261
|
-
```tsx
|
|
262
|
-
<Claude model="sonnet" maxTurns={5}>
|
|
263
|
-
<Sqlite path="./analytics.db">
|
|
264
|
-
The database contains user_events and sessions tables. Use this to answer
|
|
265
|
-
questions about user behavior.
|
|
266
|
-
</Sqlite>
|
|
267
|
-
What are the top 10 most common user actions this week?
|
|
268
|
-
</Claude>
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
### Spawning Subagent Workflows
|
|
272
248
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
executionModel="sonnet"
|
|
277
|
-
onFinished={(result) => console.log(result.output)}
|
|
278
|
-
>
|
|
279
|
-
Create a comprehensive test suite for the authentication module. Include unit
|
|
280
|
-
tests, integration tests, and edge cases. Set up proper mocking for external
|
|
281
|
-
dependencies.
|
|
282
|
-
</Smithers>
|
|
249
|
+
const root = createSmithersRoot();
|
|
250
|
+
await root.mount(RefactorWorkflow);
|
|
251
|
+
await db.close();
|
|
283
252
|
```
|
|
284
253
|
|
|
285
254
|
---
|
|
@@ -309,25 +278,40 @@ The core agent component that executes Claude with full tool access:
|
|
|
309
278
|
</Claude>
|
|
310
279
|
```
|
|
311
280
|
|
|
312
|
-
### Ralph
|
|
281
|
+
### Sophisticated Ralph Loops
|
|
313
282
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
Named after Ralph Wiggum's "I'm in danger" catchphrase - controls iterative loops that could run away:
|
|
283
|
+
Ralphing = continuous agent iteration with verification gates. Smithers lets you build **complex** Ralph loops with structure:
|
|
317
284
|
|
|
318
285
|
```tsx
|
|
319
|
-
<SmithersProvider db={db} executionId={executionId} maxIterations={
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
>
|
|
326
|
-
|
|
327
|
-
|
|
286
|
+
<SmithersProvider db={db} executionId={executionId} maxIterations={50}>
|
|
287
|
+
<Phase name="Implement">
|
|
288
|
+
<Parallel>
|
|
289
|
+
<Claude model="sonnet">Fix auth module</Claude>
|
|
290
|
+
<Claude model="sonnet">Fix database module</Claude>
|
|
291
|
+
</Parallel>
|
|
292
|
+
</Phase>
|
|
293
|
+
|
|
294
|
+
<Phase name="Verify">
|
|
295
|
+
<Claude
|
|
296
|
+
model="sonnet"
|
|
297
|
+
onFinished={(result) => {
|
|
298
|
+
if (result.output.includes("All tests pass")) {
|
|
299
|
+
db.state.set("complete", "true");
|
|
300
|
+
}
|
|
301
|
+
}}
|
|
302
|
+
>
|
|
303
|
+
Run tests. If failures, iterate.
|
|
304
|
+
</Claude>
|
|
305
|
+
</Phase>
|
|
328
306
|
</SmithersProvider>
|
|
329
307
|
```
|
|
330
308
|
|
|
309
|
+
**What Smithers adds:**
|
|
310
|
+
- Multi-phase workflows with conditional transitions
|
|
311
|
+
- Parallel agent execution with coordination
|
|
312
|
+
- Composable, reusable components
|
|
313
|
+
- Optional persistence for long-running workflows
|
|
314
|
+
|
|
331
315
|
### Structured Output with Zod
|
|
332
316
|
|
|
333
317
|
Get typed, validated responses with automatic retry:
|
|
@@ -473,39 +457,57 @@ Run multiple agents concurrently within a step:
|
|
|
473
457
|
</Parallel>
|
|
474
458
|
```
|
|
475
459
|
|
|
476
|
-
### Database
|
|
460
|
+
### Database Persistence
|
|
477
461
|
|
|
478
|
-
|
|
462
|
+
Every run is a "flight recorder" - all state persists in SQLite:
|
|
479
463
|
|
|
480
464
|
```tsx
|
|
481
|
-
// Set state
|
|
482
|
-
await db.state.set("phase", "review"
|
|
465
|
+
// Set state (survives restarts)
|
|
466
|
+
await db.state.set("phase", "review");
|
|
483
467
|
|
|
484
468
|
// Get state
|
|
485
469
|
const phase = await db.state.get("phase");
|
|
486
470
|
|
|
487
|
-
// Query history
|
|
471
|
+
// Query history - see how state evolved
|
|
488
472
|
const history = await db.state.getHistory("phase");
|
|
489
473
|
|
|
490
|
-
//
|
|
491
|
-
const
|
|
474
|
+
// Resume incomplete executions
|
|
475
|
+
const incomplete = await db.execution.findIncomplete();
|
|
476
|
+
if (incomplete) {
|
|
477
|
+
// Pick up exactly where you left off
|
|
478
|
+
executionId = incomplete.id;
|
|
479
|
+
}
|
|
492
480
|
```
|
|
493
481
|
|
|
494
|
-
|
|
482
|
+
```bash
|
|
483
|
+
# Inspect from CLI
|
|
484
|
+
smithers db executions # List all runs
|
|
485
|
+
smithers db state --execution-id abc123 # See state for a run
|
|
486
|
+
smithers db stats # Database statistics
|
|
487
|
+
```
|
|
488
|
+
|
|
489
|
+
---
|
|
495
490
|
|
|
496
|
-
|
|
491
|
+
## FAQ
|
|
497
492
|
|
|
498
|
-
|
|
499
|
-
import { createRateLimitMonitor } from "smithers-orchestrator/rate-limits";
|
|
493
|
+
### Is this actually React? Do I need to run a UI?
|
|
500
494
|
|
|
501
|
-
|
|
502
|
-
anthropic: { apiKey: process.env.ANTHROPIC_API_KEY! },
|
|
503
|
-
db,
|
|
504
|
-
});
|
|
495
|
+
No UI. React is a component model + markup-like syntax. People already use it to render to non-DOM targets (CLI, PDFs, native). Smithers renders to **execution**, not DOM.
|
|
505
496
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
497
|
+
### Why not YAML/JSON for workflows?
|
|
498
|
+
|
|
499
|
+
Because you want:
|
|
500
|
+
- Composition and reuse
|
|
501
|
+
- Version control diffs that make sense
|
|
502
|
+
- Something your coding agent can generate AND you can review like normal code
|
|
503
|
+
|
|
504
|
+
### How does this relate to Ralphing?
|
|
505
|
+
|
|
506
|
+
Ralphing is the outer loop (iterate until verification passes). Smithers gives it structure, persistence, and inspectability. Think: "Smithers productionizes Ralph loops."
|
|
507
|
+
|
|
508
|
+
### What's a Ralph loop?
|
|
509
|
+
|
|
510
|
+
From [vercel-labs/ralph-loop-agent](https://github.com/vercel-labs/ralph-loop-agent): continuous autonomy where the agent loops until the task is actually done, with verification gates (tests/linters). Smithers makes these loops durable.
|
|
509
511
|
|
|
510
512
|
---
|
|
511
513
|
|
|
@@ -521,4 +523,4 @@ See [CONTRIBUTING.md](./CONTRIBUTING.md) for details.
|
|
|
521
523
|
|
|
522
524
|
---
|
|
523
525
|
|
|
524
|
-
**Built with React, powered by Claude.**
|
|
526
|
+
**Let your agent write agents. Built with React, powered by Claude.**
|
package/dist/bin/cli.js
CHANGED
|
@@ -3679,6 +3679,25 @@ function createStateModule(ctx) {
|
|
|
3679
3679
|
return rdb.query("SELECT * FROM transitions WHERE key = ? ORDER BY created_at DESC LIMIT ?", [key, limit]);
|
|
3680
3680
|
}
|
|
3681
3681
|
return rdb.query("SELECT * FROM transitions ORDER BY created_at DESC LIMIT ?", [limit]);
|
|
3682
|
+
},
|
|
3683
|
+
has: (key) => {
|
|
3684
|
+
if (rdb.isClosed)
|
|
3685
|
+
return false;
|
|
3686
|
+
const row = rdb.queryOne("SELECT COUNT(*) as count FROM state WHERE key = ?", [key]);
|
|
3687
|
+
return (row?.count ?? 0) > 0;
|
|
3688
|
+
},
|
|
3689
|
+
delete: (key, trigger) => {
|
|
3690
|
+
if (rdb.isClosed)
|
|
3691
|
+
return;
|
|
3692
|
+
const oldValue = state.get(key);
|
|
3693
|
+
if (oldValue === null)
|
|
3694
|
+
return;
|
|
3695
|
+
rdb.run("DELETE FROM state WHERE key = ?", [key]);
|
|
3696
|
+
rdb.invalidate(["state"]);
|
|
3697
|
+
const currentExecutionId = getCurrentExecutionId();
|
|
3698
|
+
if (currentExecutionId) {
|
|
3699
|
+
rdb.run("INSERT INTO transitions (id, execution_id, key, old_value, new_value, trigger, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)", [uuid(), currentExecutionId, key, JSON.stringify(oldValue), "null", trigger ?? "delete", now()]);
|
|
3700
|
+
}
|
|
3682
3701
|
}
|
|
3683
3702
|
};
|
|
3684
3703
|
return state;
|
|
@@ -4181,6 +4200,17 @@ function createTasksModule(ctx) {
|
|
|
4181
4200
|
return 0;
|
|
4182
4201
|
const result = rdb.queryOne("SELECT value FROM state WHERE key = 'ralphCount'");
|
|
4183
4202
|
return parseJson(result?.value, 0);
|
|
4203
|
+
},
|
|
4204
|
+
withTask: async (componentType, componentName, fn) => {
|
|
4205
|
+
const taskId = tasks.start(componentType, componentName);
|
|
4206
|
+
try {
|
|
4207
|
+
const result = await fn();
|
|
4208
|
+
tasks.complete(taskId);
|
|
4209
|
+
return result;
|
|
4210
|
+
} catch (error2) {
|
|
4211
|
+
tasks.fail(taskId);
|
|
4212
|
+
throw error2;
|
|
4213
|
+
}
|
|
4184
4214
|
}
|
|
4185
4215
|
};
|
|
4186
4216
|
return tasks;
|