@mindstudio-ai/remy 0.1.257 → 0.1.258
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/dist/prompt/compiled/interfaces.md +19 -464
- package/dist/prompt/compiled/methods.md +6 -10
- package/dist/prompt/skills/agentInterfaces.md +91 -2
- package/dist/prompt/skills/inboundEmail.md +116 -0
- package/dist/prompt/skills/mcpInterfaces.md +221 -21
- package/dist/prompt/skills/restApi.md +149 -0
- package/dist/prompt/skills/scheduledJobs.md +51 -0
- package/dist/prompt/skills/webhooks.md +108 -0
- package/dist/prompt/static/authoring.md +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Scheduled Jobs
|
|
3
|
+
what: Methods that run on a schedule, declared as cron expressions in an interface config and synced to the platform on deploy. Nothing to host and no scheduler to run — a job is a method plus a schedule line.
|
|
4
|
+
when: Before adding a `cron` interface or writing a method meant to run on a timer.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Cron Interfaces
|
|
8
|
+
|
|
9
|
+
Scheduled method execution.
|
|
10
|
+
|
|
11
|
+
## Config (`interface.json`)
|
|
12
|
+
|
|
13
|
+
The top-level key must match the interface type (`cron`):
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"cron": {
|
|
18
|
+
"jobs": [
|
|
19
|
+
{
|
|
20
|
+
"schedule": "0 9 * * 5",
|
|
21
|
+
"method": "process-weekly-payments",
|
|
22
|
+
"description": "Process approved invoices every Friday at 9am"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
"schedule": "*/30 * * * *",
|
|
26
|
+
"method": "sync-vendor-status",
|
|
27
|
+
"description": "Sync vendor statuses every 30 minutes"
|
|
28
|
+
}
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Standard cron expression format. `method` is the id of a method in `methods[]`. Jobs are synced to the
|
|
35
|
+
platform on deploy.
|
|
36
|
+
|
|
37
|
+
Declare it in `mindstudio.json`:
|
|
38
|
+
|
|
39
|
+
```json
|
|
40
|
+
{ "type": "cron", "path": "dist/interfaces/cron/interface.json" }
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Auth
|
|
44
|
+
|
|
45
|
+
Methods invoked through this interface run with `auth.roles: ['system']` — the platform is calling, not
|
|
46
|
+
a user session, so there's no user to impersonate. Use `auth.requireRole('system')` to gate methods that
|
|
47
|
+
should only be reachable on a schedule. The auth reference in your system prompt covers the system role
|
|
48
|
+
in full.
|
|
49
|
+
|
|
50
|
+
A scheduled job that needs to act on user data acts as the system, not as any user, so it reaches
|
|
51
|
+
everything. Scope what it touches in the method itself rather than relying on role checks to narrow it.
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Webhooks
|
|
3
|
+
what: Inbound HTTP endpoints that run a method synchronously, routed by a secret in the URL rather than by an auth header — which is what makes them the right fit for provider callbacks from Stripe, GitHub, Shopify, Slack or Twilio, since those senders can't present a bearer token. Signature verification works natively off the raw request body.
|
|
4
|
+
when: Before adding a `webhook` interface or writing a method that receives a provider callback. Also load it before reaching for any confirmation-token, polling, or proxy workaround for inbound HTTP — those aren't needed here.
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Webhook Interfaces
|
|
8
|
+
|
|
9
|
+
Inbound HTTP endpoints that invoke a method directly and synchronously — the caller waits for the
|
|
10
|
+
method to finish. Use for receiving webhooks from external services (Stripe, GitHub, Shopify, Slack,
|
|
11
|
+
Twilio). Direct inbound webhooks with signature verification work natively; do **not** build
|
|
12
|
+
confirmation-token or polling workarounds.
|
|
13
|
+
|
|
14
|
+
The other native path for inbound HTTP is the API interface, which uses bearer auth and exposes the raw
|
|
15
|
+
body at `input._request.rawBody` instead of at the top level. Use that one when the caller can send an
|
|
16
|
+
`Authorization` header and you want a documented REST surface; use this one for provider callbacks.
|
|
17
|
+
Load the `restApi` skill if that's the direction.
|
|
18
|
+
|
|
19
|
+
Webhook secrets are configured at the project level by the user through the Remy platform. Your job is
|
|
20
|
+
the `interface.json` and the handling method.
|
|
21
|
+
|
|
22
|
+
## Config (`interface.json`)
|
|
23
|
+
|
|
24
|
+
The top-level key must match the interface type (`webhook`):
|
|
25
|
+
|
|
26
|
+
```json
|
|
27
|
+
{
|
|
28
|
+
"webhook": {
|
|
29
|
+
"endpoints": [
|
|
30
|
+
{
|
|
31
|
+
"method": "handle-payment-webhook",
|
|
32
|
+
"secret": "whsec_pick_a_long_random_token",
|
|
33
|
+
"description": "Stripe events"
|
|
34
|
+
}
|
|
35
|
+
]
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
- `method` — the id of a method in `methods[]` to invoke.
|
|
41
|
+
- `secret` — a developer-chosen opaque token that is **both the routing key and the access guard**. It
|
|
42
|
+
is stable across deploys (compilation is a passthrough — redeploying never rotates it), so a URL you
|
|
43
|
+
register with Stripe/GitHub stays valid. Generate one long random value per endpoint and keep it
|
|
44
|
+
constant.
|
|
45
|
+
- Declare multiple endpoints if needed; each `secret` maps to one method.
|
|
46
|
+
|
|
47
|
+
Declare it in `mindstudio.json`:
|
|
48
|
+
|
|
49
|
+
```json
|
|
50
|
+
{ "type": "webhook", "path": "dist/interfaces/webhook/interface.json" }
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## Endpoint URL
|
|
54
|
+
|
|
55
|
+
Register this with the external service:
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
https://{app-host}/_/webhook/{secret}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
`{app-host}` is any host the app is served on: its `custom_subdomain` host (e.g.
|
|
62
|
+
`myapp.madewithremy.com`), a custom domain if configured, or the UUID host
|
|
63
|
+
(`<appId>.madewithremy.com` / `.msagent.ai`). All HTTP verbs are accepted.
|
|
64
|
+
|
|
65
|
+
## Input
|
|
66
|
+
|
|
67
|
+
The method receives:
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
{
|
|
71
|
+
method: string; // HTTP method
|
|
72
|
+
headers: Record<string, string>; // request headers
|
|
73
|
+
query: Record<string, string>; // query params
|
|
74
|
+
body: any; // parsed JSON / form body
|
|
75
|
+
rawBody: string; // exact raw request bytes (UTF-8), pre-parse
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
For signature verification **always use `rawBody`, never `body`** — providers (Stripe, GitHub, Shopify,
|
|
80
|
+
Slack) HMAC the raw payload, and a re-serialized `body` will not match:
|
|
81
|
+
|
|
82
|
+
```typescript
|
|
83
|
+
const event = stripe.webhooks.constructEvent(
|
|
84
|
+
input.rawBody,
|
|
85
|
+
input.headers['stripe-signature'],
|
|
86
|
+
process.env.STRIPE_WEBHOOK_SECRET!,
|
|
87
|
+
);
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
`rawBody` is populated for `application/json` and `application/x-www-form-urlencoded` bodies (what these
|
|
91
|
+
providers send).
|
|
92
|
+
|
|
93
|
+
## Response
|
|
94
|
+
|
|
95
|
+
Whatever the method returns as output is sent back to the caller as JSON; if it returns no output, the
|
|
96
|
+
platform responds `204`. A wrong/unknown secret returns `401`; an app with no live release returns
|
|
97
|
+
`404`.
|
|
98
|
+
|
|
99
|
+
## Auth
|
|
100
|
+
|
|
101
|
+
Methods invoked through this interface run with `auth.roles: ['system']` — the platform is calling, not
|
|
102
|
+
a user session, so there's no user to impersonate. Use `auth.requireRole('system')` to gate methods that
|
|
103
|
+
should only be reachable via a platform trigger. The auth reference in your system prompt covers the
|
|
104
|
+
system role in full.
|
|
105
|
+
|
|
106
|
+
Note that the URL secret is the only access control on the endpoint itself, which is why it needs to be
|
|
107
|
+
long and random. Signature verification is a second, independent check that the payload really came from
|
|
108
|
+
the provider — do both.
|
|
@@ -19,7 +19,7 @@ The scaffold starts with these spec files that cover the full picture of the app
|
|
|
19
19
|
- **`src/interfaces/@brand/voice.md`** — voice and terminology: tone, error messages, word choices
|
|
20
20
|
- **`src/roadmap/`** — feature roadmap. One file per feature (`type: roadmap`). See "Roadmap" below.
|
|
21
21
|
|
|
22
|
-
These are starting points, not constraints. Create as many spec files as the project needs — the `src/` folder is your workspace and every `.md` file in it becomes compilation context. If the app has substantial content (presentation slides, copy, lesson plans, menu items, quiz questions), put it in its own file (`src/content.md`, `src/slides.md`, `src/menu.md`, etc.) rather than cramming it into `app.md` or `web.md`. If the domain is complex, split `app.md` into multiple files by area (`src/billing.md`, `src/approvals.md`). Add interface specs for other interface types (`api.md`, `webhook.md`, `cron.md`, `
|
|
22
|
+
These are starting points, not constraints. Create as many spec files as the project needs — the `src/` folder is your workspace and every `.md` file in it becomes compilation context. If the app has substantial content (presentation slides, copy, lesson plans, menu items, quiz questions), put it in its own file (`src/content.md`, `src/slides.md`, `src/menu.md`, etc.) rather than cramming it into `app.md` or `web.md`. If the domain is complex, split `app.md` into multiple files by area (`src/billing.md`, `src/approvals.md`). Add interface specs for other interface types (`api.md`, `webhook.md`, `cron.md`, `email.md`, `mcp.md`, `agent.md`) if the app uses them. Each of those has a skill carrying its spec format and config — `restApi`, `webhooks`, `scheduledJobs`, `inboundEmail`, `mcpInterfaces`, `agentInterfaces` — and you should load the relevant one before writing the spec rather than after, since the spec is what the config is compiled from. For external HTTP the choice is between two of them: the Webhook interface handles inbound provider webhooks (Stripe, GitHub) via secret-in-URL routing, while the API interface covers bearer-auth sync endpoints, public REST APIs, and batch tools. Organize however serves clarity — the platform reads the entire `src/` folder.
|
|
23
23
|
|
|
24
24
|
Remember: users care about look and feel as much as (and often more than) underlying data structures. Don't treat the brand and interface specs as an afterthought — for many users, the visual identity and voice are the first things they want to get right.
|
|
25
25
|
|