@positronic/template-new-project 0.0.49 → 0.0.52

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 CHANGED
@@ -53,9 +53,9 @@ module.exports = {
53
53
  ],
54
54
  setup: async ctx => {
55
55
  const devRootPath = process.env.POSITRONIC_LOCAL_PATH;
56
- let coreVersion = '^0.0.49';
57
- let cloudflareVersion = '^0.0.49';
58
- let clientVercelVersion = '^0.0.49';
56
+ let coreVersion = '^0.0.52';
57
+ let cloudflareVersion = '^0.0.52';
58
+ let clientVercelVersion = '^0.0.52';
59
59
 
60
60
  // Map backend selection to package names
61
61
  const backendPackageMap = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@positronic/template-new-project",
3
- "version": "0.0.49",
3
+ "version": "0.0.52",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -8,10 +8,13 @@ import {
8
8
  ScheduleDO,
9
9
  PositronicManifest,
10
10
  } from "@positronic/cloudflare";
11
- // Import the generated manifest - NOTE the .js extension for runtime compatibility
11
+ // Import the generated manifests - NOTE the .js extension for runtime compatibility
12
12
  // @ts-expect-error - _manifest.js is generated during template processing
13
13
  import { manifest as brainManifest } from "./_manifest.js";
14
+ // @ts-expect-error - _webhookManifest.js is generated during template processing
15
+ import { webhookManifest } from "./_webhookManifest.js";
14
16
  import { runner } from "./runner.js";
17
+
15
18
  // Configure the manifest to use the statically generated list
16
19
  const manifest = new PositronicManifest({
17
20
  manifest: brainManifest,
@@ -19,12 +22,7 @@ const manifest = new PositronicManifest({
19
22
 
20
23
  setManifest(manifest);
21
24
  setBrainRunner(runner);
22
-
23
- // Register webhooks here if your brains use waitFor with webhooks
24
- // Example:
25
- // import { myWebhook } from '../../webhooks/my-webhook.js';
26
- // setWebhookManifest({ 'my-webhook': myWebhook });
27
- setWebhookManifest({});
25
+ setWebhookManifest(webhookManifest);
28
26
 
29
27
  // Define Env type based on wrangler.jsonc bindings
30
28
  interface Env {
@@ -9,6 +9,7 @@ This is a Positronic project - an AI-powered framework for building and running
9
9
  ## Project Structure
10
10
 
11
11
  - **`/brains`** - AI workflow definitions using the Brain DSL
12
+ - **`/webhooks`** - Webhook definitions for external integrations (auto-discovered)
12
13
  - **`/resources`** - Files and documents that brains can access via the resource system
13
14
  - **`/tests`** - Test files for brains (kept separate to avoid deployment issues)
14
15
  - **`/docs`** - Documentation including brain testing guide
@@ -61,6 +62,69 @@ export default myBrain;
61
62
 
62
63
  Resources are files that brains can access during execution. They're stored in the `/resources` directory and are automatically typed based on the manifest.
63
64
 
65
+ ## Webhooks
66
+
67
+ Webhooks allow brains to pause execution and wait for external events (like form submissions, API callbacks, or user approvals). Webhooks are auto-discovered from the `/webhooks` directory.
68
+
69
+ ### Creating a Webhook
70
+
71
+ Create a file in the `/webhooks` directory with a default export:
72
+
73
+ ```typescript
74
+ // webhooks/approval.ts
75
+ import { createWebhook } from '@positronic/core';
76
+ import { z } from 'zod';
77
+
78
+ const approvalWebhook = createWebhook(
79
+ 'approval', // webhook name (should match filename)
80
+ z.object({ // response schema - what the webhook returns to the brain
81
+ approved: z.boolean(),
82
+ reviewerNote: z.string().optional(),
83
+ }),
84
+ async (request: Request) => {
85
+ // Parse the incoming request and return identifier + response
86
+ const body = await request.json();
87
+ return {
88
+ type: 'webhook',
89
+ identifier: body.requestId, // matches the identifier used in waitFor
90
+ response: {
91
+ approved: body.approved,
92
+ reviewerNote: body.note,
93
+ },
94
+ };
95
+ }
96
+ );
97
+
98
+ export default approvalWebhook;
99
+ ```
100
+
101
+ ### Using Webhooks in Brains
102
+
103
+ Import the webhook and use it with `waitFor`:
104
+
105
+ ```typescript
106
+ import { brain } from '../brain.js';
107
+ import approvalWebhook from '../webhooks/approval.js';
108
+
109
+ export default brain('approval-workflow')
110
+ .step('Request approval', ({ state }) => ({
111
+ state: { ...state, status: 'pending' },
112
+ waitFor: [approvalWebhook(state.requestId)], // pause and wait
113
+ }))
114
+ .step('Process approval', ({ state, response }) => ({
115
+ ...state,
116
+ status: response.approved ? 'approved' : 'rejected',
117
+ reviewerNote: response.reviewerNote,
118
+ }));
119
+ ```
120
+
121
+ ### How Auto-Discovery Works
122
+
123
+ - Place webhook files in `/webhooks` directory
124
+ - Each file must have a default export using `createWebhook()`
125
+ - The dev server generates `_webhookManifest.ts` automatically
126
+ - Webhook name comes from the filename (e.g., `approval.ts` → `'approval'`)
127
+
64
128
  ## Development Workflow
65
129
 
66
130
  1. Define your brain in `/brains`
File without changes