@positronic/template-new-project 0.0.62 → 0.0.63
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/index.js +4 -4
- package/package.json +1 -1
- package/template/CLAUDE.md +3 -3
- package/template/docs/brain-dsl-guide.md +15 -14
- package/template/docs/tips-for-agents.md +8 -6
package/index.js
CHANGED
|
@@ -53,10 +53,10 @@ module.exports = {
|
|
|
53
53
|
],
|
|
54
54
|
setup: async ctx => {
|
|
55
55
|
const devRootPath = process.env.POSITRONIC_LOCAL_PATH;
|
|
56
|
-
let coreVersion = '^0.0.
|
|
57
|
-
let cloudflareVersion = '^0.0.
|
|
58
|
-
let clientVercelVersion = '^0.0.
|
|
59
|
-
let genUIComponentsVersion = '^0.0.
|
|
56
|
+
let coreVersion = '^0.0.63';
|
|
57
|
+
let cloudflareVersion = '^0.0.63';
|
|
58
|
+
let clientVercelVersion = '^0.0.63';
|
|
59
|
+
let genUIComponentsVersion = '^0.0.63';
|
|
60
60
|
|
|
61
61
|
// Map backend selection to package names
|
|
62
62
|
const backendPackageMap = {
|
package/package.json
CHANGED
package/template/CLAUDE.md
CHANGED
|
@@ -101,7 +101,7 @@ export default approvalWebhook;
|
|
|
101
101
|
|
|
102
102
|
### Using Webhooks in Brains
|
|
103
103
|
|
|
104
|
-
Import the webhook and use
|
|
104
|
+
Import the webhook and use `.wait()` to pause execution:
|
|
105
105
|
|
|
106
106
|
```typescript
|
|
107
107
|
import { brain } from '../brain.js';
|
|
@@ -109,9 +109,9 @@ import approvalWebhook from '../webhooks/approval.js';
|
|
|
109
109
|
|
|
110
110
|
export default brain('approval-workflow')
|
|
111
111
|
.step('Request approval', ({ state }) => ({
|
|
112
|
-
|
|
113
|
-
waitFor: [approvalWebhook(state.requestId)], // pause and wait
|
|
112
|
+
...state, status: 'pending',
|
|
114
113
|
}))
|
|
114
|
+
.wait('Wait for approval', ({ state }) => approvalWebhook(state.requestId))
|
|
115
115
|
.step('Process approval', ({ state, response }) => ({
|
|
116
116
|
...state,
|
|
117
117
|
status: response.approved ? 'approved' : 'rejected',
|
|
@@ -202,7 +202,7 @@ Each step receives these parameters:
|
|
|
202
202
|
- `client` - AI client for generating structured objects
|
|
203
203
|
- `resources` - Loaded resources (files, documents, etc.)
|
|
204
204
|
- `options` - Runtime options passed to the brain
|
|
205
|
-
- `response` - Webhook response data (available after `
|
|
205
|
+
- `response` - Webhook response data (available after `.wait()` completes)
|
|
206
206
|
- `page` - Generated page object (available after `.ui()` step)
|
|
207
207
|
- `pages` - Pages service for HTML page management
|
|
208
208
|
- `env` - Runtime environment containing `origin` (base URL) and `secrets` (typed secrets object)
|
|
@@ -1105,7 +1105,7 @@ The created page object contains:
|
|
|
1105
1105
|
|
|
1106
1106
|
## UI Steps
|
|
1107
1107
|
|
|
1108
|
-
UI steps allow brains to generate dynamic user interfaces using AI. The `.ui()` step generates a page and provides a `page` object to the next step. You then notify users and use `
|
|
1108
|
+
UI steps allow brains to generate dynamic user interfaces using AI. The `.ui()` step generates a page and provides a `page` object to the next step. You then notify users and use `.wait()` to pause until the form is submitted.
|
|
1109
1109
|
|
|
1110
1110
|
### Basic UI Step
|
|
1111
1111
|
|
|
@@ -1128,14 +1128,13 @@ brain('Feedback Collector')
|
|
|
1128
1128
|
comments: z.string(),
|
|
1129
1129
|
}),
|
|
1130
1130
|
})
|
|
1131
|
-
// Notify user
|
|
1132
|
-
.step('Notify
|
|
1131
|
+
// Notify user
|
|
1132
|
+
.step('Notify', async ({ state, page, slack }) => {
|
|
1133
1133
|
await slack.post('#feedback', `Please fill out: <%= '${page.url}' %>`);
|
|
1134
|
-
return
|
|
1135
|
-
state,
|
|
1136
|
-
waitFor: [page.webhook],
|
|
1137
|
-
};
|
|
1134
|
+
return state;
|
|
1138
1135
|
})
|
|
1136
|
+
// Wait for form submission
|
|
1137
|
+
.wait('Wait for submission', ({ page }) => page.webhook)
|
|
1139
1138
|
// Process the form data (comes through response, not page)
|
|
1140
1139
|
.step('Process Feedback', ({ state, response }) => ({
|
|
1141
1140
|
...state,
|
|
@@ -1151,8 +1150,8 @@ brain('Feedback Collector')
|
|
|
1151
1150
|
2. **AI Generation**: The AI creates a component tree based on the prompt
|
|
1152
1151
|
3. **Page Object**: Next step receives `page` with `url` and `webhook`
|
|
1153
1152
|
4. **Notification**: You notify users however you want (Slack, email, etc.)
|
|
1154
|
-
5. **Wait**: Use
|
|
1155
|
-
6. **Form Data**: Step after `
|
|
1153
|
+
5. **Wait**: Use `.wait('title', ({ page }) => page.webhook)` to pause until form submission
|
|
1154
|
+
6. **Form Data**: Step after `.wait()` receives form data via `response`
|
|
1156
1155
|
|
|
1157
1156
|
### The `page` Object
|
|
1158
1157
|
|
|
@@ -1225,10 +1224,11 @@ brain('User Onboarding')
|
|
|
1225
1224
|
dob: z.string(),
|
|
1226
1225
|
}),
|
|
1227
1226
|
})
|
|
1228
|
-
.step('
|
|
1227
|
+
.step('Notify Personal', async ({ state, page, notify }) => {
|
|
1229
1228
|
await notify(`Step 1: <%= '${page.url}' %>`);
|
|
1230
|
-
return
|
|
1229
|
+
return state;
|
|
1231
1230
|
})
|
|
1231
|
+
.wait('Wait for Personal', ({ page }) => page.webhook)
|
|
1232
1232
|
.step('Save Personal', ({ state, response }) => ({
|
|
1233
1233
|
...state,
|
|
1234
1234
|
userData: { ...state.userData, ...response },
|
|
@@ -1247,10 +1247,11 @@ brain('User Onboarding')
|
|
|
1247
1247
|
contactMethod: z.enum(['email', 'phone', 'sms']),
|
|
1248
1248
|
}),
|
|
1249
1249
|
})
|
|
1250
|
-
.step('
|
|
1250
|
+
.step('Notify Preferences', async ({ state, page, notify }) => {
|
|
1251
1251
|
await notify(`Step 2: <%= '${page.url}' %>`);
|
|
1252
|
-
return
|
|
1252
|
+
return state;
|
|
1253
1253
|
})
|
|
1254
|
+
.wait('Wait for Preferences', ({ page }) => page.webhook)
|
|
1254
1255
|
.step('Complete', ({ state, response }) => ({
|
|
1255
1256
|
...state,
|
|
1256
1257
|
userData: { ...state.userData, preferences: response },
|
|
@@ -207,8 +207,8 @@ Most generated brains should not have try-catch blocks. Only use them when the e
|
|
|
207
207
|
When you need to collect user input, use the `.ui()` method. The pattern is:
|
|
208
208
|
1. `.ui()` generates the page
|
|
209
209
|
2. Next step gets `page.url` and `page.webhook`
|
|
210
|
-
3. Notify users
|
|
211
|
-
4. Step after `
|
|
210
|
+
3. Notify users, then use `.wait()` with `page.webhook`
|
|
211
|
+
4. Step after `.wait()` gets form data in `response`
|
|
212
212
|
|
|
213
213
|
```typescript
|
|
214
214
|
import { z } from 'zod';
|
|
@@ -231,11 +231,13 @@ brain('feedback-collector')
|
|
|
231
231
|
comments: z.string(),
|
|
232
232
|
}),
|
|
233
233
|
})
|
|
234
|
-
// Notify
|
|
234
|
+
// Notify users
|
|
235
235
|
.step('Notify', async ({ state, page, slack }) => {
|
|
236
236
|
await slack.post('#feedback', `Fill out: <%= '${page.url}' %>`);
|
|
237
|
-
return
|
|
237
|
+
return state;
|
|
238
238
|
})
|
|
239
|
+
// Wait for form submission
|
|
240
|
+
.wait('Wait for submission', ({ page }) => page.webhook)
|
|
239
241
|
// Form data comes through response (not page)
|
|
240
242
|
.step('Process', ({ state, response }) => ({
|
|
241
243
|
...state,
|
|
@@ -246,8 +248,8 @@ brain('feedback-collector')
|
|
|
246
248
|
|
|
247
249
|
Key points:
|
|
248
250
|
- `page.url` - where to send users
|
|
249
|
-
- `page.webhook` - use with `
|
|
250
|
-
- `response` - form data arrives here (in step after `
|
|
251
|
+
- `page.webhook` - use with `.wait()` to pause for submission
|
|
252
|
+
- `response` - form data arrives here (in step after `.wait()`)
|
|
251
253
|
- You control how users are notified (Slack, email, etc.)
|
|
252
254
|
|
|
253
255
|
See `/docs/brain-dsl-guide.md` for more UI step examples.
|